commit 55197a63e49580de502e4ec9885ea85a10ef5049
parent 3ca8bda95f268b5177b3a0c22bf7bbcd21df775c
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Mon, 7 Aug 2023 17:20:48 +0200
Fix move generating and incremental hashing
Diffstat:
7 files changed, 93 insertions(+), 70 deletions(-)
diff --git a/src/board/board.c b/src/board/board.c
@@ -6,6 +6,7 @@
#include <cul/mem.h>
#include "board.h"
+#include "utils.h"
#include "zobrist.h"
Board *board_new(void) {
@@ -29,18 +30,10 @@ U64 board_occupancy(const Board *self) {
return self->color[WHITE] | self->color[BLACK];
}
-U64 board_piece_get_internal(const Board *self, ePiece piece, Square target) {
- return bit_get(self->piece[piece], target);
-}
-
U64 board_pieceSet(const Board *self, Piece piece) {
return self->piece[piece_piece(piece)] & self->color[piece_color(piece)];
}
-void board_enpassant_set(Board *self, Square target) {
- self->enpassant = target;
-}
-
void board_color_pop(Board *self, eColor color, Square target) {
bit_pop(self->color[color], target);
}
@@ -69,29 +62,10 @@ void board_piece_set(Board *self, Piece piece, Square square) {
bit_set(self->color[piece_color(piece)], square);
}
-void board_piece_move(Board *self, Piece Piece, Square source, Square target) {
- board_piece_pop(self, Piece, source);
- board_piece_set(self, Piece, target);
-}
-
U64 board_piece_attacks(const Board *self, Piece piece, Square src) {
return piece_attacks(piece)(src, board_occupancy(self));
}
-void board_piece_capture(Board *self, Piece piece, Piece taken, Square source,
- Square target) {
- board_piece_pop(self, piece, source);
- if (taken) board_piece_pop(self, taken, target);
- board_piece_set(self, piece, target);
-}
-
-void board_castle_pop(Board *self, eCastle castle) {
- bit_pop(self->castle, bit_lsb_index(castle));
-}
-
-void board_castle_and(Board *self, int exp) { self->castle &= exp; }
-void board_side_switch(Board *self) { self->side = !self->side; }
-
int board_isCheck(const Board *self) {
U64 king = self->piece[KING] & self->color[self->side];
return board_square_isAttack(self, bit_lsb_index(king), !self->side);
@@ -103,7 +77,7 @@ int board_square_isOccupied(const Board *self, Square square) {
int board_square_isAttack(const Board *self, Square square, eColor side) {
U64 occupancy = self->color[WHITE] | self->color[BLACK];
- for (int i = 0; i < 6; i++) {
+ for (int i = KING; i >= PAWN; i--) {
if (piece_attacks(piece_get(i, !side))(square, occupancy) &
self->piece[i] & self->color[side])
return 1;
@@ -112,10 +86,24 @@ int board_square_isAttack(const Board *self, Square square, eColor side) {
return 0;
}
+void board_side_switch(Board *self) {
+ self->side = !self->side;
+ self->hash ^= zobrist_key_side();
+}
+
+void board_enpassant_set(Board *self, Square target) {
+ if (self->enpassant != no_sq)
+ self->hash ^= zobrist_key_enpassant(self->enpassant);
+
+ if (target != no_sq) self->hash ^= zobrist_key_enpassant(target);
+ self->enpassant = target;
+}
+
+void board_castle_and(Board *self, int exp) { self->castle &= exp; }
+
Piece board_square_piece(const Board *self, Square square, eColor color) {
for (ePiece i = 0; i < 6; i++)
- if (board_piece_get_internal(self, i, square))
- return piece_get(i, color);
+ if (bit_get(self->piece[i], square)) return piece_get(i, color);
return NULL;
}
@@ -217,6 +205,6 @@ void board_print(const Board *self) {
printf(" Castling: %c%c%c%c\n", (self->castle & WK) ? 'K' : '-',
(self->castle & WQ) ? 'Q' : '-', (self->castle & BK) ? 'k' : '-',
(self->castle & BQ) ? 'q' : '-');
- printf(" Hash: %llu\n", self->hash);
+ printf(" Hash: %llx\n", self->hash);
printf("\n");
}
diff --git a/src/board/zobrist.c b/src/board/zobrist.c
@@ -9,6 +9,13 @@ U64 enpassant_keys[64];
U64 piece_keys[16][64];
U64 side_key;
+U64 zobrist_key_side(void) { return side_key; }
+U64 zobrist_key_castle(int exp) { return castle_keys[exp]; }
+U64 zobrist_key_enpassant(Square square) { return enpassant_keys[square]; }
+U64 zobrist_key_piece(Piece piece, Square square) {
+ return piece_keys[piece_index(piece)][square];
+}
+
void init_hash_keys() {
random_state_reset();
diff --git a/src/include/board.h b/src/include/board.h
@@ -33,14 +33,13 @@ eColor board_side(const Board *self);
Square board_enpassant(const Board *self);
U64 board_hash(const Board *self);
+void board_side_switch(Board *self);
void board_enpassant_set(Board *self, Square target);
+void board_castle_and(Board *self, int exp);
U64 board_pieceSet(const Board *self, Piece piece);
U64 board_piece_attacks(const Board *self, Piece piece, Square src);
-void board_piece_capture(Board *self, Piece piece, Piece taken, Square source,
- Square target);
-void board_piece_move(Board *self, Piece Piece, Square square, Square target);
void board_piece_pop(Board *self, Piece Piece, Square square);
void board_piece_set(Board *self, Piece Piece, Square square);
int board_piece_get(const Board *self, Square square);
@@ -49,9 +48,6 @@ U64 board_color_get(const Board *self, eColor color, Square target);
void board_color_pop(Board *self, eColor color, Square target);
void board_color_set(Board *self, eColor color, Square target);
-void board_castle_and(Board *self, int exp);
-void board_castle_pop(Board *self, eCastle castle);
-
Piece board_square_piece(const Board *self, Square square, eColor side);
int board_square_isAttack(const Board *self, Square square, eColor side);
int board_square_isOccupied(const Board *self, Square square);
@@ -59,6 +55,5 @@ int board_square_isOccupied(const Board *self, Square square);
Board *board_from_FEN(Board *board, const char *fen);
int board_isCheck(const Board *self);
void board_print(const Board *self);
-void board_side_switch(Board *self);
#endif
diff --git a/src/include/zobrist.h b/src/include/zobrist.h
@@ -6,4 +6,9 @@
void zobrist_init(void);
U64 zobrist_hash(const Board *board);
+U64 zobrist_key_side(void);
+U64 zobrist_key_castle(int exp);
+U64 zobrist_key_enpassant(Square square);
+U64 zobrist_key_piece(Piece piece, Square square);
+
#endif
diff --git a/src/moves/moves.c b/src/moves/moves.c
@@ -4,7 +4,9 @@
#include <cul/assert.h>
#include <cul/mem.h>
+#include "board.h"
#include "moves.h"
+#include "zobrist.h"
int move_cmp(Move a, Move b) { return *(uint32_t *)&a == *(uint32_t *)&b; }
@@ -128,10 +130,9 @@ MoveList *move_list_generate(MoveList *moves, const Board *board) {
if (board_enpassant(board) != no_sq &&
board_piece_attacks(board, piece, src) &
(C64(1) << board_enpassant(board)))
- move_list_add(
- moves, move_encode(src, board_enpassant(board), piece,
- board_square_piece(board, tgt, !color),
- 0, 0, 1, 0));
+ move_list_add(moves,
+ move_encode(src, board_enpassant(board), piece,
+ piece_get(PAWN, !color), 0, 0, 1, 0));
}
}
@@ -204,63 +205,85 @@ const int castling_rights[64] = {
};
// clang-format on
-int move_make(Move move, Board *board, int flag) {
- if (flag == 0) {
+void _piece_remove(Board *self, Piece piece, Square square) {
+ board_piece_pop(self, piece, square);
+ self->hash ^= zobrist_key_piece(piece, square);
+}
- Square source = move_source(move);
- Square target = move_target(move);
+void _piece_set(Board *self, Piece piece, Square square) {
+ board_piece_set(self, piece, square);
+ self->hash ^= zobrist_key_piece(piece, square);
+}
+
+void _piece_move(Board *self, Piece piece, Square source, Square target) {
+ _piece_remove(self, piece, source);
+ _piece_set(self, piece, target);
+}
+
+int move_make(Move move, Board *board, int flag) {
+ if (flag) {
+ if (move_capture(move)) return move_make(move, board, 0);
+ return 0;
+ } else {
Piece piece = move_piece(move);
eColor color = board_side(board);
+ Square source = move_source(move);
+ Square target = move_target(move);
+ Square ntarget = target + (color == WHITE ? -8 : +8);
- if (!move_capture(move))
- board_piece_move(board, piece, source, target);
- else
- board_piece_capture(board, piece, move_piece_capture(move), source,
- target);
-
- if (move_promote(move)) {
- board_piece_pop(board, piece, target);
- board_piece_set(board, move_piece_promote(move), target);
+ if (!move_capture(move)) {
+ if (move_promote(move)) {
+ _piece_remove(board, piece, source);
+ _piece_set(board, move_piece_promote(move), target);
+ } else {
+ _piece_move(board, piece, source, target);
+ }
+ } else {
+ if (move_enpassant(move)) {
+ _piece_move(board, piece, source, target);
+ _piece_remove(board, move_piece_capture(move), ntarget);
+ } else if (move_promote(move)) {
+ _piece_remove(board, piece, source);
+ _piece_remove(board, move_piece_capture(move), target);
+ _piece_set(board, move_piece_promote(move), target);
+ } else {
+ _piece_remove(board, piece, source);
+ _piece_remove(board, move_piece_capture(move), target);
+ _piece_set(board, piece, target);
+ }
}
- int ntarget = target + (color == WHITE ? -8 : +8);
- if (move_enpassant(move))
- board_piece_pop(board, piece_get(PAWN, !color), ntarget);
-
board_enpassant_set(board, move_double(move) ? ntarget : no_sq);
if (move_castle(move)) {
Piece Rook = piece_get(ROOK, board_side(board));
switch (target) {
case g1:
- board_piece_move(board, Rook, h1, f1);
+ _piece_move(board, Rook, h1, f1);
break;
case c1:
- board_piece_move(board, Rook, a1, d1);
+ _piece_move(board, Rook, a1, d1);
break;
case g8:
- board_piece_move(board, Rook, h8, f8);
+ _piece_move(board, Rook, h8, f8);
break;
case c8:
- board_piece_move(board, Rook, a8, d8);
+ _piece_move(board, Rook, a8, d8);
break;
default:
break;
}
}
+ board->hash ^= zobrist_key_castle(board_castle(board));
board_castle_and(board, castling_rights[source]);
board_castle_and(board, castling_rights[target]);
+ board->hash ^= zobrist_key_castle(board_castle(board));
if (!board_isCheck(board)) {
board_side_switch(board);
return 1;
- } else
- return 0;
- } else {
- if (move_capture(move))
- return move_make(move, board, 0);
- else
- return 0;
+ }
+ return 0;
}
}
diff --git a/src/perft/CMakeLists.txt b/src/perft/CMakeLists.txt
@@ -19,6 +19,7 @@ target_link_libraries(perft
PRIVATE piece
PRIVATE score
PRIVATE utils
+ PRIVATE random
)
target_link_libraries(perft PRIVATE "cul")
diff --git a/src/perft/perft.c b/src/perft/perft.c
@@ -11,6 +11,7 @@
#include "moves.h"
#include "perft.h"
#include "utils.h"
+#include "zobrist.h"
// FEN debug positions
#define tricky_position \
@@ -174,6 +175,9 @@ int main(int argc, char *argv[]) {
}
attacks_init();
+ zobrist_init();
+
+ board_print(board_from_FEN(NULL, fen));
PerftResult res = perft_test(fen, depth, thread_num);
perft_result_print(res);
}