stellar

Stellar - UCI Chess engine written in C++20
git clone git://git.dimitrijedobrota.com/stellar.git
Log | Files | Refs | README | LICENSE

commit 3ca8bda95f268b5177b3a0c22bf7bbcd21df775c
parent 317a3513ae4fca24f5ab9d34b38e198c396b5774
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Mon,  7 Aug 2023 12:31:05 +0200

Initialize Zobrist keys and generate hash

Diffstat:
Msrc/attacks/magic_generate.c | 3+--
Msrc/board/CMakeLists.txt | 1+
Msrc/board/board.c | 5+++++
Asrc/board/zobrist.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/engine/CMakeLists.txt | 1+
Msrc/engine/engine.c | 13+++++++++----
Msrc/include/board.h | 2++
Asrc/include/zobrist.h | 9+++++++++
8 files changed, 94 insertions(+), 6 deletions(-)

diff --git a/src/attacks/magic_generate.c b/src/attacks/magic_generate.c @@ -10,8 +10,7 @@ const char *FORMAT = "C64(0x%llx),\n"; U64 generate_magic_number() { - return random_get_U64() & random_get_U64() & - random_get_U64(); + return random_get_U64() & random_get_U64() & random_get_U64(); } U64 find_magic_number(Square square, int relevant_bits, int bishop) { diff --git a/src/board/CMakeLists.txt b/src/board/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(board OBJECT board.c + zobrist.c ) target_include_directories(board diff --git a/src/board/board.c b/src/board/board.c @@ -6,6 +6,7 @@ #include <cul/mem.h> #include "board.h" +#include "zobrist.h" Board *board_new(void) { Board *p; @@ -22,6 +23,8 @@ eCastle board_castle(const Board *self) { return self->castle; } eColor board_side(const Board *self) { return self->side; } U64 board_color(const Board *self, eColor color) { return self->color[color]; } U64 board_piece(const Board *self, ePiece piece) { return self->piece[piece]; } +U64 board_hash(const Board *self) { return self->hash; } + U64 board_occupancy(const Board *self) { return self->color[WHITE] | self->color[BLACK]; } @@ -177,6 +180,7 @@ Board *board_from_FEN(Board *board, const char *fen) { board->enpassant = coordinates_to_square(fen); } + board->hash = zobrist_hash(board); return board; } @@ -213,5 +217,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("\n"); } diff --git a/src/board/zobrist.c b/src/board/zobrist.c @@ -0,0 +1,66 @@ +#include "zobrist.h" +#include "board.h" +#include "piece.h" +#include "random.h" +#include "utils.h" + +U64 castle_keys[16]; +U64 enpassant_keys[64]; +U64 piece_keys[16][64]; +U64 side_key; + +void init_hash_keys() { + random_state_reset(); + + for (int piece = PAWN; piece <= KING; piece++) { + int piece_index_white = piece_index(piece_get(piece, WHITE)); + int piece_index_black = piece_index(piece_get(piece, BLACK)); + for (int square = 0; square < 64; square++) { + piece_keys[piece_index_white][square] = random_get_U64(); + piece_keys[piece_index_black][square] = random_get_U64(); + } + } + + for (int square = 0; square < 64; square++) { + enpassant_keys[square] = random_get_U64(); + } + + for (int castle = 0; castle < 16; castle++) { + castle_keys[castle] = random_get_U64(); + } + + side_key = random_get_U64(); +} + +void zobrist_init(void) { init_hash_keys(); } + +U64 zobrist_hash(const Board *board) { + U64 key_final = C64(0); + Square square; + + for (int piece = PAWN; piece <= KING; piece++) { + Piece piece_white = piece_get(piece, WHITE); + U64 bitboard_white = board_pieceSet(board, piece_white); + int piece_white_index = piece_index(piece_white); + + bitboard_for_each_bit(square, bitboard_white) { + key_final ^= piece_keys[piece_white_index][square]; + } + + Piece piece_black = piece_get(piece, BLACK); + U64 bitboard_black = board_pieceSet(board, piece_black); + int piece_black_index = piece_index(piece_black); + + bitboard_for_each_bit(square, bitboard_black) { + key_final ^= piece_keys[piece_black_index][square]; + } + } + + key_final ^= castle_keys[board_castle(board)]; + + if (board_side(board)) key_final ^= side_key; + if (board_enpassant(board) != no_sq) + key_final ^= enpassant_keys[board_enpassant(board)]; + + return key_final; +} diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt @@ -7,6 +7,7 @@ target_link_libraries(engine PRIVATE piece PRIVATE score PRIVATE utils + PRIVATE random ) target_link_libraries(engine PRIVATE "cul") diff --git a/src/engine/engine.c b/src/engine/engine.c @@ -9,6 +9,7 @@ #include "perft.h" #include "score.h" #include "utils.h" +#include "zobrist.h" #include <cul/assert.h> #include <cul/mem.h> @@ -455,7 +456,7 @@ Board *Instruction_parse(Instruction *self, Board *board) { } void uci_loop(void) { - Board *board = NULL; + Board board; Instruction *instruction; char input[200000]; @@ -469,18 +470,22 @@ void uci_loop(void) { if (!fgets(input, sizeof(input), stdin)) continue; instruction = Instruction_new(input); - if (!(board = Instruction_parse(instruction, board))) break; + if (!Instruction_parse(instruction, &board)) break; Instruction_free(&instruction); } Instruction_free(&instruction); - board_free(&board); } /* MAIN */ -int main(void) { +void init(void) { attacks_init(); + zobrist_init(); +} + +int main(void) { + init(); uci_loop(); return 0; } diff --git a/src/include/board.h b/src/include/board.h @@ -15,6 +15,7 @@ typedef struct Board Board; struct Board { U64 color[2]; U64 piece[6]; + U64 hash; eColor side; Square enpassant; eCastle castle; @@ -30,6 +31,7 @@ U64 board_piece(const Board *self, ePiece piece); eCastle board_castle(const Board *self); eColor board_side(const Board *self); Square board_enpassant(const Board *self); +U64 board_hash(const Board *self); void board_enpassant_set(Board *self, Square target); diff --git a/src/include/zobrist.h b/src/include/zobrist.h @@ -0,0 +1,9 @@ +#ifndef STELLAR_ZOBRIST_H +#define STELLAR_ZOBRIST_H + +#include "board.h" + +void zobrist_init(void); +U64 zobrist_hash(const Board *board); + +#endif