aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2022-09-14 05:27:30 +0300
committereug-vs <eugene@eug-vs.xyz>2022-09-14 05:27:30 +0300
commit6f7cfbfcde39a57a59db17882339fa26055b75a0 (patch)
treeb2477a1b5c9fef015b62664e96b054f374ac3e14
parent8e1d090e0f5c8d2e72fc1e90c22404a9ef808606 (diff)
downloadj1chess-6f7cfbfcde39a57a59db17882339fa26055b75a0.tar.gz
feat: precompute king attack tables
-rw-r--r--src/board.c19
-rw-r--r--src/board.h2
-rw-r--r--src/main.c43
3 files changed, 46 insertions, 18 deletions
diff --git a/src/board.c b/src/board.c
index 83fe8ce..a0b1bb7 100644
--- a/src/board.c
+++ b/src/board.c
@@ -18,7 +18,7 @@ void print_bitboard(Bitboard bb) {
void precompute_knight_attack_table(Bitboard attacks[64]) {
for (int index = 0; index < 64; index++) {
- U64 position = (U64)1 << index;
+ U64 position = BIT << index;
attacks[index] =
((position & notAFile & notBFile) << 6) |
@@ -32,6 +32,17 @@ void precompute_knight_attack_table(Bitboard attacks[64]) {
}
}
+void precompute_king_attack_table(Bitboard attacks[64]) {
+ for (int index = 0; index < 64; index++) {
+ U64 position = BIT << index;
+
+ attacks[index] =
+ (position & notAFile) << 7 | (position << 8) | (position & notHFile) << 9 |
+ (position & notAFile) >> 1 | (position & notHFile) << 1 |
+ (position & notAFile) >> 9 | (position >> 8) | (position & notHFile) >> 7;
+ }
+}
+
Board parse_FEN(char* FEN) {
Board board;
for (int i = 0; i < 12; i++) board.pieces[i] = 0;
@@ -42,7 +53,7 @@ Board parse_FEN(char* FEN) {
for (int k = 0; k < strlen(FEN); k++) {
int c = FEN[k];
int index = rank * 8 + file;
- Bitboard position = (Bitboard)1 << index;
+ Bitboard position = BIT << index;
if (c > '0' && c <= '8') file += c - '0';
else {
@@ -87,8 +98,6 @@ Board parse_FEN(char* FEN) {
rank--;
file = -1; // So that it becomes 0
break;
- case ' ': // TODO: parse everything after
- return board;
}
file++;
}
@@ -103,7 +112,7 @@ void print_board(Board board) {
printf("%i|", rank + 1);
for (int file = 0; file < 8; file++) {
int index = rank * 8 + file;
- Bitboard position = (Bitboard)1 << index;
+ Bitboard position = BIT << index;
int found = 0;
for (int piece = 0; piece < 12; piece++) {
diff --git a/src/board.h b/src/board.h
index c9d8153..11b0c71 100644
--- a/src/board.h
+++ b/src/board.h
@@ -11,6 +11,7 @@
#define KING 0b1010
typedef U64 Bitboard;
+#define BIT (U64)1
typedef struct {
Bitboard pieces[12];
@@ -56,6 +57,7 @@ static const char* pieces[] = {
};
void precompute_knight_attack_table();
+void precompute_king_attack_table();
void print_bitboard(Bitboard bb);
int pop_count(Bitboard bb);
void print_board(Board board);
diff --git a/src/main.c b/src/main.c
index 5f19585..c8c82cf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,7 +6,16 @@ int main() {
start_test_section("Bitboards");
unit_test(pop_count(0b01110) == 3, "Pop count of 01110 is 3");
}
-
+ {
+ start_test_section("Default FEN string");
+ Board board = parse_FEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
+ unit_test(pop_count(board.pieces[PAWN] | board.pieces[PAWN | BLACK]) == 16, "There are 16 pawns total");
+ unit_test(pop_count(board.pieces[ROOK]) == 2, "There are 2 white rooks");
+ // TODO
+ unit_test(board.side == WHITE, "Side to move is white");
+ unit_test(board.castling_rights == 0, "Both sides can castle");
+ unit_test(board.en_passant_square == 0, "No en passant move is avaialble");
+ }
{
start_test_section("Test knight attacks");
Bitboard attacks[64];
@@ -19,25 +28,33 @@ int main() {
}
unit_test(max_attacks == 8, "Max amount of knight attacks should be 8");
+ unit_test(
+ attacks[b7] == ((BIT << d8) | (BIT << d6) | (BIT << c5) | (BIT << a5)),
+ "Knight on b7 attacks only d8, d6, c5, a5"
+ );
+ }
+ {
+ start_test_section("Test king attacks");
+ Bitboard attacks[64];
+ precompute_king_attack_table(attacks);
+
+ int max_attacks = 0;
+ for (int i = 0; i < 64; i++) {
+ int attack_count = pop_count(attacks[i]);
+ if (attack_count > max_attacks) max_attacks = attack_count;
+ }
+ unit_test(max_attacks == 8, "Max amount of king attacks should be 8");
+
{
U64 bit = 1;
unit_test(
- attacks[b7] == ((bit << d8) | (bit << d6) | (bit << c5) | (bit << a5)),
- "Knight on b7 attacks only d8, d6, c5, a5"
+ attacks[h2] == ((BIT << h1) | (BIT << g1) | (BIT << g2) | (BIT << g3) | (BIT << h3)),
+ "King on h2 attacks only h1, g1, g2, g3, h3"
);
}
}
- {
- start_test_section("Default FEN string");
- Board board = parse_FEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
- unit_test(pop_count(board.pieces[PAWN] | board.pieces[PAWN | BLACK]) == 16, "There are 16 pawns total");
- unit_test(pop_count(board.pieces[ROOK]) == 2, "There are 2 white rooks");
- // TODO
- unit_test(board.side == WHITE, "Side to move is white");
- unit_test(board.castling_rights == 0, "Everyone can castle");
- unit_test(board.en_passant_square == 0, "No en passant move is avaialble");
- }
+
report();
return 0;