commit 3be4123c8c5cbdadfab02532d2bfcb9bdb173083
parent b9f9ac98b25274ffa436386189298cc72c885dc2
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Fri, 11 Aug 2023 18:19:08 +0200
Constexpr random and zobrist hashing init
Diffstat:
13 files changed, 143 insertions(+), 146 deletions(-)
diff --git a/src/board/CMakeLists.txt b/src/board/CMakeLists.txt
@@ -1,6 +1,5 @@
add_library(board OBJECT
board.cpp
- zobrist.cpp
)
target_include_directories(board
diff --git a/src/board/board.cpp b/src/board/board.cpp
@@ -83,13 +83,13 @@ void Board::and_castle(uint8_t right) {
void Board::switch_side(void) {
side = (side == Color::BLACK) ? Color::WHITE : Color::BLACK;
- hash ^= zobrist_key_side();
+ hash ^= Zobrist::key_side();
}
void Board::set_enpassant(Square target) {
- if (enpassant != Square::no_sq) hash ^= zobrist_key_enpassant(enpassant);
+ if (enpassant != Square::no_sq) hash ^= Zobrist::key_enpassant(enpassant);
- if (target != Square::no_sq) hash ^= zobrist_key_enpassant(target);
+ if (target != Square::no_sq) hash ^= Zobrist::key_enpassant(target);
enpassant = target;
}
@@ -184,7 +184,7 @@ Board::Board(const std::string &fen) {
}
if (fen[++i] != '-') enpassant = square_from_coordinates(fen.data() + i);
- hash = zobrist_hash(*this);
+ hash = Zobrist::hash(*this);
}
std::ostream &operator<<(std::ostream &os, const Board &board) {
diff --git a/src/board/zobrist.cpp b/src/board/zobrist.cpp
@@ -1,80 +0,0 @@
-#include "zobrist.hpp"
-#include "piece.hpp"
-#include "random.hpp"
-#include "utils_cpp.hpp"
-
-U64 castle_keys[16];
-U64 enpassant_keys[64];
-U64 piece_keys[12][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[to_underlying(square)];
-}
-U64 zobrist_key_piece(const piece::Piece &piece, Square square) {
- return piece_keys[piece.index][to_underlying(square)];
-}
-
-void init_hash_keys() {
- random_state_reset();
-
- for (piece::Type type : piece::TypeIter()) {
- int piece_index_white = piece::get(type, Color::WHITE).index;
- int piece_index_black = piece::get(type, Color::BLACK).index;
- 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);
- uint8_t square;
-
- for (piece::Type type : piece::TypeIter()) {
- const piece::Piece &piece_white = piece::get(type, Color::WHITE);
- int piece_white_index = piece_white.index;
- U64 bitboard_white = board.get_bitboard_piece(piece_white);
-
- bitboard_for_each_bit(square, bitboard_white) {
- key_final ^= piece_keys[piece_white_index][square];
- }
-
- const piece::Piece &piece_black = piece::get(type, Color::BLACK);
- int piece_black_index = piece_black.index;
- U64 bitboard_black = board.get_bitboard_piece(piece_black);
-
- bitboard_for_each_bit(square, bitboard_black) {
- key_final ^= piece_keys[piece_black_index][square];
- }
- }
-
- key_final ^= castle_keys[board.get_castle()];
-
- if (board.get_side() == Color::BLACK) key_final ^= side_key;
- if (board.get_enpassant() != Square::no_sq)
- key_final ^= enpassant_keys[to_underlying(board.get_enpassant())];
-
- return key_final;
-}
diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt
@@ -7,7 +7,6 @@ add_executable(engine
target_link_libraries(engine
PRIVATE board
PRIVATE moves
- PRIVATE random
)
target_link_libraries(engine PRIVATE "cul")
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
@@ -497,12 +497,7 @@ void uci_loop(void) {
/* MAIN */
-void init(void) {
- zobrist_init();
-}
-
int main(void) {
- init();
uci_loop();
return 0;
}
diff --git a/src/include/board.hpp b/src/include/board.hpp
@@ -40,7 +40,6 @@ class Board {
U64 get_bitboard_piece_attacks(piece::Type piece, Color color, Square square) const;
U64 get_bitboard_piece_attacks(const piece::Piece &piece, Square square) const;
- // exception if not found
Color get_square_piece_color(Square square) const;
piece::Type get_square_piece_type(Square square) const;
const piece::Piece *get_square_piece(Square square) const;
@@ -76,6 +75,4 @@ class Board {
uint8_t castle = 0;
};
-const piece::Piece &board_square_piece(const Board *self, Square square, Color side);
-
#endif
diff --git a/src/include/random.hpp b/src/include/random.hpp
@@ -3,8 +3,45 @@
#include "utils_cpp.hpp"
-void random_state_reset();
-U32 random_get_U32();
-U64 random_get_U64();
+class Random {
+ public:
+ constexpr Random(void) {
+ }
+ constexpr Random(U64 seed) : state(seed) {
+ }
+
+ constexpr U64 operator()(void) {
+ return get_U64();
+ }
+
+ constexpr void reset(void) {
+ state = seed;
+ }
+
+ constexpr U32 get_U32(void) {
+ U32 number = state;
+
+ number ^= number << 13;
+ number ^= number >> 17;
+ number ^= number << 5;
+
+ return state = number;
+ }
+
+ constexpr U64 get_U64(void) {
+ U64 n1, n2, n3, n4;
+
+ n1 = (U64)(get_U32()) & C64(0xFFFF);
+ n2 = (U64)(get_U32()) & C64(0xFFFF);
+ n3 = (U64)(get_U32()) & C64(0xFFFF);
+ n4 = (U64)(get_U32()) & C64(0xFFFF);
+
+ return n1 | (n2 << 16) | (n3 << 32) | (n4 << 48);
+ }
+
+ private:
+ static inline constexpr const U32 seed = C32(1804289383);
+ U32 state = seed;
+};
#endif
diff --git a/src/include/zobrist.hpp b/src/include/zobrist.hpp
@@ -2,13 +2,101 @@
#define STELLAR_ZOBRIST_H
#include "board.hpp"
+#include "piece.hpp"
+#include "random.hpp"
-void zobrist_init(void);
-U64 zobrist_hash(const Board &board);
+#include <algorithm>
+#include <array>
+#include <random>
-U64 zobrist_key_side(void);
-U64 zobrist_key_castle(int exp);
-U64 zobrist_key_enpassant(Square square);
-U64 zobrist_key_piece(const piece::Piece &piece, Square square);
+class Zobrist {
+ public:
+ Zobrist() = delete;
+
+ static inline constexpr U64 key_side(void) {
+ return keys_side;
+ }
+
+ static inline constexpr U64 key_castle(int exp) {
+ return keys_castle[exp];
+ }
+
+ static inline constexpr U64 key_enpassant(Square square) {
+ return keys_enpassant[to_underlying(square)];
+ }
+
+ static inline constexpr U64 key_piece(const piece::Piece &piece, Square square) {
+ return keys_piece[piece.index][to_underlying(square)];
+ }
+
+ static inline U64 hash(const Board &board) {
+ U64 key_final = C64(0);
+ uint8_t square;
+
+ for (piece::Type type : piece::TypeIter()) {
+ const piece::Piece &piece_white = piece::get(type, Color::WHITE);
+ int piece_white_index = piece_white.index;
+ U64 bitboard_white = board.get_bitboard_piece(piece_white);
+
+ bitboard_for_each_bit(square, bitboard_white) {
+ key_final ^= keys_piece[piece_white_index][square];
+ }
+
+ const piece::Piece &piece_black = piece::get(type, Color::BLACK);
+ int piece_black_index = piece_black.index;
+ U64 bitboard_black = board.get_bitboard_piece(piece_black);
+
+ bitboard_for_each_bit(square, bitboard_black) {
+ key_final ^= keys_piece[piece_black_index][square];
+ }
+ }
+
+ key_final ^= keys_castle[board.get_castle()];
+
+ if (board.get_side() == Color::BLACK) key_final ^= keys_side;
+ if (board.get_enpassant() != Square::no_sq)
+ key_final ^= keys_enpassant[to_underlying(board.get_enpassant())];
+
+ return key_final;
+ }
+
+ private:
+ typedef std::array<std::array<U64, 64>, 12> key_piece_array;
+ static inline constexpr const key_piece_array keys_piece = []() constexpr -> key_piece_array {
+ key_piece_array key_piece;
+ Random gen(C64(1804289383));
+ for (piece::Type type : piece::TypeIter()) {
+ int piece_index_white = piece::get(type, Color::WHITE).index;
+ int piece_index_black = piece::get(type, Color::BLACK).index;
+ for (int square = 0; square < 64; square++) {
+ key_piece[piece_index_white][square] = gen();
+ key_piece[piece_index_black][square] = gen();
+ }
+ }
+ return key_piece;
+ }();
+
+ typedef std::array<U64, 64> key_enpassant_array;
+ static inline constexpr const key_enpassant_array keys_enpassant = []() constexpr -> key_enpassant_array {
+ key_enpassant_array key_enpassant;
+ Random gen(C32(337245213));
+ for (int castle = 0; castle < 64; castle++) {
+ key_enpassant[castle] = gen();
+ }
+ return key_enpassant;
+ }();
+
+ typedef std::array<U64, 16> key_castle_array;
+ static inline constexpr const key_castle_array keys_castle = []() constexpr -> key_castle_array {
+ key_castle_array key_castle;
+ Random gen(C32(3642040919));
+ for (int castle = 0; castle < 16; castle++) {
+ key_castle[castle] = gen();
+ }
+ return key_castle;
+ }();
+
+ static inline constexpr const U64 keys_side = Random(C32(1699391443))();
+};
#endif
diff --git a/src/moves/moves_make.cpp b/src/moves/moves_make.cpp
@@ -17,12 +17,12 @@ const int castling_rights[64] = {
void _piece_remove(Board &board, const piece::Piece &piece, Square square) {
board.pop_piece(piece, square);
- board.xor_hash(zobrist_key_piece(piece, square));
+ board.xor_hash(Zobrist::key_piece(piece, square));
}
void _piece_set(Board &board, const piece::Piece &piece, Square square) {
board.set_piece(piece, square);
- board.xor_hash(zobrist_key_piece(piece, square));
+ board.xor_hash(Zobrist::key_piece(piece, square));
}
void _piece_move(Board &board, const piece::Piece &piece, Square source, Square target) {
@@ -74,10 +74,10 @@ int move_make(Move move, Board &board, int flag) {
if (target == Square::c8) _piece_move(board, rook_black, Square::a8, Square::d8);
}
- board.xor_hash(zobrist_key_castle(board.get_castle()));
+ board.xor_hash(Zobrist::key_castle(board.get_castle()));
board.and_castle(castling_rights[move_source(move)]);
board.and_castle(castling_rights[move_target(move)]);
- board.xor_hash(zobrist_key_castle(board.get_castle()));
+ board.xor_hash(Zobrist::key_castle(board.get_castle()));
if (!board.is_check()) {
board.switch_side();
diff --git a/src/perft/CMakeLists.txt b/src/perft/CMakeLists.txt
@@ -8,7 +8,6 @@ endif()
target_link_libraries(perft
PRIVATE board
PRIVATE moves
- PRIVATE random
)
target_link_libraries(perft PRIVATE "cul")
diff --git a/src/perft/perft.cpp b/src/perft/perft.cpp
@@ -1,3 +1,4 @@
+#include <iomanip>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
@@ -99,7 +100,6 @@ void *perft_thread(void *arg) {
copy = board;
if (!move_make(move, copy, 0)) continue;
- // std::cout << copy << std::endl;
if (shared->depth != 1) {
perft_driver(copy, shared->depth - 1, &result);
@@ -158,8 +158,6 @@ int main(int argc, char *argv[]) {
}
}
- zobrist_init();
-
PerftResult res = perft_test(fen, depth, thread_num);
perft_result_print(res);
}
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
@@ -1,7 +0,0 @@
-add_library(random OBJECT
- random.cpp
-)
-
-target_include_directories(random
- PUBLIC "${PROJECT_SOURCE_DIR}/src/include"
-)
diff --git a/src/utils/random.cpp b/src/utils/random.cpp
@@ -1,28 +0,0 @@
-#include "random.hpp"
-
-U32 state = C32(1804289383);
-
-void random_state_reset() {
- state = C32(1804289383);
-}
-
-U32 random_get_U32() {
- U32 number = state;
-
- number ^= number << 13;
- number ^= number >> 17;
- number ^= number << 5;
-
- return state = number;
-}
-
-U64 random_get_U64() {
- U64 n1, n2, n3, n4;
-
- n1 = (U64)(random_get_U32()) & C64(0xFFFF);
- n2 = (U64)(random_get_U32()) & C64(0xFFFF);
- n3 = (U64)(random_get_U32()) & C64(0xFFFF);
- n4 = (U64)(random_get_U32()) & C64(0xFFFF);
-
- return n1 | (n2 << 16) | (n3 << 32) | (n4 << 48);
-}