const Attacks = struct {
// leaper pieces
pawn_attacks: [2][64]Chess.BoardType = genPawnAttacks(),
king_attacks: [64]Chess.BoardType = genKingAttacks(),
knight_attacks: [64]Chess.BoardType = genKnightAttacks(),
// rider pieces
const bishop_magic: [64]Chess.BoardType = .{ 9241390835893862432, 9234710240556097536, 1227239730261824640, 577604527957049348, 6918659473418780672, 351888113804529668, 2328924575914001472, 4614013701991826049, 2331927815258656, 9016004274033184, 2305860618585916944, 648597650767120384, 577061163230053010, 579277706207166480, 4614220409926336512, 580964498095089664, 4616199239888937985, 1126041776325888, 616996207142899796, 10141929783173120, 5630608183136385, 36873230555873632, 181275456685879328, 576743335520240152, 2603115769260982529, 2380875882396914688, 2289189183030272, 171145581949894664, 1153203048319827969, 2305913930985283584, 72657961755345152, 1127003718435328, 148904939935000608, 282608955041792, 1153062518049211400, 10378688279935975552, 290279660069376, 290279660069376, 6922619801915492428, 6922619801915492428, 1158067358212916246, 2328924575914001472, 36319360414908928, 4611703757044990977, 1224980203021800448, 4521260535005248, 290561443953836160, 2310347987528229122, 2328924575914001472, 564053894369288, 1585408924206502016, 4675139272704, 144185593598050818, 7440091971840, 4612816883383795840, 9234710240556097536, 4614013701991826049, 580964498095089664, 83334186434036744, 648597650767120384, 17592766972164, 9439545093914103944, 2331927815258656, 9241390835893862432 };
const rook_magic: [64]Chess.BoardType = .{ 9259401108760043536, 594475563268280320, 144124055069409314, 72068610631143424, 72076285769418752, 108090789187420288, 324265770315940096, 9367487500631408770, 2305983747248373760, 14051934662285148160, 4612249107028804096, 72198881416318976, 9223653529145639440, 4648277836300289160, 1153204079162360320, 167055404054872320, 4791830278402211904, 13511073762115648, 10090880114674926608, 18332157638541321, 4902733343504729120, 141287311278592, 876517475657892112, 573945342918788, 35804994879488, 9223688714458236480, 72906490033217536, 844463587201024, 290486580455932032, 144117389246857344, 18295937913061888, 5406589228312428673, 9223442407754825769, 4503874543034369, 48431846559596576, 9295438429141602308, 18018869587216385, 3377768473690120, 2233852801025, 4785075694604450, 36030189125550082, 9227875774059790342, 9223407221495332992, 18332157638541321, 1155182100580696192, 35201820918080, 4612820723034226768, 45041495719411716, 603668391936256, 18084767791612032, 4612249107028804096, 15276649741245483264, 288371148000592256, 14628817498200408128, 1127068272296960, 4657003602455658752, 88510690829569, 2535612326510617, 144124055069409314, 2377918195506874625, 4611967527763988485, 1181631959278293026, 9232412290735146116, 261213468561048706 };
const bishop_masks = genBishopMasks();
const rook_masks = genRookMasks();
const bishop_relevant_bits = genRelevantOccupancy(.bishop);
const rook_relevant_bits = genRelevantOccupancy(.rook);
var bishop_attacks: [64][512]Chess.BoardType = undefined;
var rook_attacks: [64][4096]Chess.BoardType = undefined;
pub fn init() @This() {
var attacks: @This() = .{};
initSliderAttacks(.bishop);
initSliderAttacks(.rook);
return attacks;
}
fn initSliderAttacks(piece: Chess.Pieces) void {
for (std.enums.values(Chess.Square)) |square| {
const attack_mask = switch (piece) {
.bishop => bishop_masks[square.int()],
.rook => rook_masks[square.int()],
else => unreachable,
};
// init relevant occupancy bit count
const relevant_bits = @popCount(attack_mask);
const occupancy_idx = @as(Chess.BoardType, 1) << @intCast(u6, relevant_bits);
var idx: usize = 0;
while (idx < occupancy_idx) : (idx += 1) {
switch (piece) {
.bishop => {
const occupancy = setOccupancy(idx, relevant_bits, attack_mask);
var res: Chess.BoardType = undefined;
_ = @mulWithOverflow(Chess.BoardType, occupancy, bishop_magic[square.int()], &res);
const magic_index = res >>
@intCast(u6, @as(u7, 64) - bishop_relevant_bits[square.int()]);
bishop_attacks[square.int()][magic_index] =
attackWithBlocker(occupancy, square, .bishop);
},
.rook => {
const occupancy = setOccupancy(idx, relevant_bits, attack_mask);
var res: Chess.BoardType = undefined;
_ = @mulWithOverflow(Chess.BoardType, occupancy, rook_magic[square.int()], &res);
const magic_index = res >>
@intCast(u6, @as(u7, 64) - rook_relevant_bits[square.int()]);
rook_attacks[square.int()][magic_index] =
attackWithBlocker(occupancy, square, .rook);
},
else => unreachable,
}
}
}
}
fn getBishopAttacks(self: @This(), square: Chess.Square, occupancy: Chess.BoardType) Chess.BoardType {
_ = self;
var mut_occupancy: Chess.BoardType = occupancy;
mut_occupancy &= bishop_masks[square.int()];
mut_occupancy *= bishop_magic[square.int()];
mut_occupancy >>= @intCast(u6, @as(u7, 64) - bishop_relevant_bits[square.int()]);
return bishop_attacks[square.int()][mut_occupancy];
}
fn getRookAttacks(self: @This(), square: Chess.Square, occupancy: Chess.BoardType) Chess.BoardType {
_ = self;
var mut_occupancy: Chess.BoardType = occupancy;
mut_occupancy &= rook_masks[square.int()];
mut_occupancy *= rook_magic[square.int()];
mut_occupancy >>= @intCast(u6, @as(u7, 64) - rook_relevant_bits[square.int()]);
return rook_attacks[square.int()][mut_occupancy];
}
};
test "Attack Struct" {
const a = Attacks.init();
const occupancy = 0;