From 21e5e0dc3de477df4b250673eb89c4e94aa00c2d Mon Sep 17 00:00:00 2001 From: Michael Captain Date: Fri, 2 Apr 2021 18:49:24 +0300 Subject: [PATCH] Add knight attacks with tests --- src/attack.zig | 63 ++++++++++++++++++++++++++++++++++++++++++------- src/main.zig | 17 +++++++++++++ test/attack.zig | 34 ++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 9 deletions(-) diff --git a/src/attack.zig b/src/attack.zig index 711157c..86afe7c 100644 --- a/src/attack.zig +++ b/src/attack.zig @@ -1,21 +1,25 @@ pub usingnamespace @import("board.zig"); const mask_not_a = 0xfefefefefefefefe; +const mask_not_ab = 0xfcfcfcfcfcfcfcfc; const mask_not_h = 0x7f7f7f7f7f7f7f7f; +const mask_not_gh = 0x3f3f3f3f3f3f3f3f; const pawn_attacks = initPawnAttacks(); fn initPawnAttacks() [2][64]u64 { - var sq: u6 = 0; - var attacks: [2][64]u64 = undefined; - while (sq < 63) : (sq += 1) { - attacks[0][sq] = maskPawnAttacks(Side.White, @intToEnum(Square, sq)); + comptime { + var sq: u8 = 0; + var attacks: [2][64]u64 = undefined; + while (sq < 64) : (sq += 1) { + attacks[0][sq] = maskPawnAttacks(Side.White, @intToEnum(Square, sq)); + } + sq = 0; + while (sq < 64) : (sq += 1) { + attacks[1][sq] = maskPawnAttacks(Side.Black, @intToEnum(Square, sq)); + } + return attacks; } - sq = 0; - while (sq < 63) : (sq += 1) { - attacks[1][sq] = maskPawnAttacks(Side.Black, @intToEnum(Square, sq)); - } - return attacks; } fn maskPawnAttacks(side: Side, pawn: Square) u64 { @@ -29,3 +33,44 @@ fn maskPawnAttacks(side: Side, pawn: Square) u64 { pub fn pawnAttacks(side: Side, pawn: Square) u64 { return pawn_attacks[@enumToInt(side)][@enumToInt(pawn)]; } + +const knight_attacks = initKnightAttacks(); + +fn initKnightAttacks() [64]u64 { + comptime { + var sq: u8 = 0; + var attacks: [64]u64 = undefined; + while (sq < 64) : (sq += 1) { + attacks[sq] = maskKnightAttacks(@intToEnum(Square, sq)); + } + return attacks; + } +} + +fn maskKnightAttacks(knight: Square) u64 { + const bitboard = bitboardFromSquare(knight); + // attacks considered clockwise + var attacks = bitboard >> 15 & mask_not_a; + attacks |= bitboard >> 6 & mask_not_ab; + attacks |= bitboard << 10 & mask_not_ab; + attacks |= bitboard << 17 & mask_not_a; + attacks |= bitboard << 15 & mask_not_h; + attacks |= bitboard << 6 & mask_not_gh; + attacks |= bitboard >> 10 & mask_not_gh; + attacks |= bitboard >> 17 & mask_not_h; + return attacks; +} + +pub fn knightAttacks(knight: Square) u64 { + return knight_attacks[@enumToInt(knight)]; +} + +const king_attacks = initKingAttacks(); + +fn initKingAttacks() [64]u64 { + return 0; +} + +pub fn kingAttacks(king: Square) u64 { + return king_attacks[@enumToInt(king)]; +} diff --git a/src/main.zig b/src/main.zig index d01e94b..2a99743 100644 --- a/src/main.zig +++ b/src/main.zig @@ -24,6 +24,23 @@ fn uciLoop() !void { } } +/// Helper function for getting the value of a specific bitboard. +fn bitboardBuilder() void { + var bitboard: u64 = 0; + var rank: u6 = 0; + while (rank < 8) : (rank += 1) { + var file: u6 = 0; + while (file < 8) : (file += 1) { + const square = 8 * rank + file; + if (file != 6 and file != 7) { + bitboard |= @as(u64, 1) << square; + } + } + } + board.printBitboard(bitboard); +} + pub fn main() !void { //uciLoop(); + //bitboardBuilder(); } diff --git a/test/attack.zig b/test/attack.zig index 664ade3..c218e98 100644 --- a/test/attack.zig +++ b/test/attack.zig @@ -60,3 +60,37 @@ test "black pawn on 1st rank attacks nothing" { const actual = pawnAttacks(side, pawn); expectEqual(expected, actual); } + +test "knight in center attacks all 8 squares" { + const knight = Square.e4; + const expected_attacked_squares = [8]Square{ + Square.f6, + Square.g5, + Square.g3, + Square.f2, + Square.d2, + Square.c3, + Square.c5, + Square.d6, + }; + const expected = bitboardFromSquares(expected_attacked_squares[0..]); + const actual = knightAttacks(knight); + expectEqual(expected, actual); +} + +test "knights in corners attack only 2 squares" { + const knight_a8 = Square.a8; + const knight_h8 = Square.h8; + const knight_h1 = Square.h1; + const knight_a1 = Square.a1; + + const expected_a8 = [2]Square{ Square.c7, Square.b6 }; + const expected_h8 = [2]Square{ Square.g6, Square.f7 }; + const expected_h1 = [2]Square{ Square.f2, Square.g3 }; + const expected_a1 = [2]Square{ Square.b3, Square.c2 }; + + expectEqual(bitboardFromSquares(expected_a8[0..]), knightAttacks(knight_a8)); + expectEqual(bitboardFromSquares(expected_h8[0..]), knightAttacks(knight_h8)); + expectEqual(bitboardFromSquares(expected_h1[0..]), knightAttacks(knight_h1)); + expectEqual(bitboardFromSquares(expected_a1[0..]), knightAttacks(knight_a1)); +} -- 2.45.2