aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2022-09-14 19:15:50 +0300
committereug-vs <eugene@eug-vs.xyz>2022-09-14 19:15:50 +0300
commit318067f9e66b363b14e684492b7a1af021eb6a20 (patch)
tree61008e7dc3b9aa4efb8e07ff83bcc42db2acabb0
parenta881be4856c6d3dc7675059d5a635d34434b5797 (diff)
downloadj1chess-318067f9e66b363b14e684492b7a1af021eb6a20.tar.gz
feat: add initial attacksToSquare
-rw-r--r--src/board.c16
-rw-r--r--src/board.h11
-rw-r--r--src/main.c58
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);
+
diff --git a/src/main.c b/src/main.c
index f21e17c..904d8b7 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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();