diff options
author | eug-vs <eugene@eug-vs.xyz> | 2022-09-14 19:15:50 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2022-09-14 19:15:50 +0300 |
commit | 318067f9e66b363b14e684492b7a1af021eb6a20 (patch) | |
tree | 61008e7dc3b9aa4efb8e07ff83bcc42db2acabb0 | |
parent | a881be4856c6d3dc7675059d5a635d34434b5797 (diff) | |
download | j1chess-318067f9e66b363b14e684492b7a1af021eb6a20.tar.gz |
feat: add initial attacksToSquare
-rw-r--r-- | src/board.c | 16 | ||||
-rw-r--r-- | src/board.h | 11 | ||||
-rw-r--r-- | src/main.c | 58 |
3 files changed, 60 insertions, 25 deletions
diff --git a/src/board.c b/src/board.c index c5c4eb2..e87a666 100644 --- a/src/board.c +++ b/src/board.c @@ -2,6 +2,10 @@ #include <string.h> #include "board.h" +Bitboard KNIGHT_ATTACKS[64]; +Bitboard WHITE_PAWN_ATTACKS[64]; +Bitboard BLACK_PAWN_ATTACKS[64]; + Board parseFEN(char* FEN) { Board board; for (int i = 0; i < 12; i++) board.pieces[i] = 0; @@ -125,3 +129,15 @@ void precomputePawnAttackTable(Bitboard attacks[64], BYTE color) { } } + +/* Given a TO square return all pseudo-legal FROM squares which attack or protect that square + * In order to be color-specific, intersect the result with appropriate color bitboard */ +Bitboard attacksToSquare(Board board, enumSquare sq) { + Bitboard knights = board.pieces[KNIGHT] | board.pieces[KNIGHT | BLACK]; + Bitboard whitePawns = board.pieces[PAWN]; + Bitboard blackPawns = board.pieces[PAWN | BLACK]; + + return (KNIGHT_ATTACKS[sq] & knights) + | (BLACK_PAWN_ATTACKS[sq] & whitePawns) + | (WHITE_PAWN_ATTACKS[sq] & blackPawns); +}; diff --git a/src/board.h b/src/board.h index e24a130..b63b494 100644 --- a/src/board.h +++ b/src/board.h @@ -17,7 +17,7 @@ typedef struct { BYTE enPassantSquare; } Board; -enum enumSquare { +typedef enum enumSquare { a1, b1, c1, d1, e1, f1, g1, h1, a2, b2, c2, d2, e2, f2, g2, h2, a3, b3, c3, d3, e3, f3, g3, h3, @@ -26,7 +26,7 @@ enum enumSquare { a6, b6, c6, d6, e6, f6, g6, h6, a7, b7, c7, d7, e7, f7, g7, h7, a8, b8, c8, d8, e8, f8, g8, h8 -}; +} enumSquare; static const char* notation[64] = { "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", @@ -60,3 +60,10 @@ void printBoard(Board board); void precomputeKnightAttackTable(Bitboard table[64]); void precomputeKingAttackTable(Bitboard table[64]); void precomputePawnAttackTable(Bitboard table[64], BYTE color); + +extern Bitboard KNIGHT_ATTACKS[64]; +extern Bitboard WHITE_PAWN_ATTACKS[64]; +extern Bitboard BLACK_PAWN_ATTACKS[64]; + +Bitboard attacksToSquare(Board board, enumSquare sq); + @@ -21,16 +21,16 @@ int main() { unitTest(board.enPassantSquare == 0, "No en passant move is avaialble"); } - testSection("Test knight attacks"); { + testSection("Knight attack table"); { Bitboard attacks[64]; precomputeKnightAttackTable(attacks); - int max_attacks = 0; + int maxAttacks = 0; for (int i = 0; i < 64; i++) { - int attack_count = popCount(attacks[i]); - if (attack_count > max_attacks) max_attacks = attack_count; + int attackCount = popCount(attacks[i]); + if (attackCount > maxAttacks) maxAttacks = attackCount; } - unitTest(max_attacks == 8, "Max amount of knight attacks should be 8"); + unitTest(maxAttacks == 8, "Max amount of knight attacks should be 8"); unitTest( attacks[b7] == ((BIT << d8) | (BIT << d6) | (BIT << c5) | (BIT << a5)), @@ -38,16 +38,16 @@ int main() { ); } - testSection("Test king attacks"); { + testSection("King attack table"); { Bitboard attacks[64]; precomputeKingAttackTable(attacks); - int max_attacks = 0; + int maxAttacks = 0; for (int i = 0; i < 64; i++) { - int attack_count = popCount(attacks[i]); - if (attack_count > max_attacks) max_attacks = attack_count; + int attackCount = popCount(attacks[i]); + if (attackCount > maxAttacks) maxAttacks = attackCount; } - unitTest(max_attacks == 8, "Max amount of king attacks should be 8"); + unitTest(maxAttacks == 8, "Max amount of king attacks should be 8"); unitTest( attacks[h2] == ((BIT << h1) | (BIT << g1) | (BIT << g2) | (BIT << g3) | (BIT << h3)), @@ -55,23 +55,35 @@ int main() { ); } - testSection("Test pawn attacks"); { - Bitboard white_attacks[64]; - Bitboard black_attacks[64]; + testSection("Pawn attack table"); { + Bitboard whiteAttacks[64]; + Bitboard blackAttacks[64]; - precomputePawnAttackTable(white_attacks, WHITE); - precomputePawnAttackTable(black_attacks, BLACK); + precomputePawnAttackTable(whiteAttacks, WHITE); + precomputePawnAttackTable(blackAttacks, BLACK); - int is_same = 0; - int max_attacks = 0; + int isSame = 0; + int maxAttacks = 0; for (int i = 0; i < 64; i++) { - int attack_count = popCount(white_attacks[i]); - if (attack_count > max_attacks) max_attacks = attack_count; - if (white_attacks[i] == black_attacks[i]) is_same = 1; + int attackCount = popCount(whiteAttacks[i]); + if (attackCount > maxAttacks) maxAttacks = attackCount; + if (whiteAttacks[i] == blackAttacks[i]) isSame = 1; } - unitTest(max_attacks == 2, "Max amount of pawn attacks should be 2"); - unitTest(is_same == 0, "Black and white pawns always move differently"); - unitTest(white_attacks[g2] == (BIT << h3 | BIT << f3), "White pawn on g2 attacks only h3 and f3"); + unitTest(maxAttacks == 2, "Max amount of pawn attacks should be 2"); + unitTest(isSame == 0, "Black and white pawns always move differently"); + unitTest(whiteAttacks[g2] == (BIT << h3 | BIT << f3), "White pawn on g2 attacks only h3 and f3"); + } + + testSection("Attacks to square in starting position"); { + precomputeKnightAttackTable(KNIGHT_ATTACKS); + precomputePawnAttackTable(WHITE_PAWN_ATTACKS, WHITE); + precomputePawnAttackTable(BLACK_PAWN_ATTACKS, BLACK); + Board board = parseFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); + + unitTest(attacksToSquare(board, c3) == ((BIT << b1) | (BIT << b2) | (BIT << d2)), "c3 is protected only by b1, b2, d2"); + unitTest(attacksToSquare(board, f6) == ((BIT << g8) | (BIT << g7) | (BIT << e7)), "f6 is protected only by g8, g7, e7"); + // TODO + unitTest(attacksToSquare(board, d2) == ((BIT << b1) | (BIT << c1) | (BIT << d1) | (BIT << e1)), "d2 is protected only b1, c1, d1, e1"); } report(); |