diff options
Diffstat (limited to 'src/board/zobrist.rs')
-rw-r--r-- | src/board/zobrist.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/board/zobrist.rs b/src/board/zobrist.rs new file mode 100644 index 0000000..e282074 --- /dev/null +++ b/src/board/zobrist.rs @@ -0,0 +1,79 @@ +use rand::{rngs::StdRng,SeedableRng,Rng}; + +use crate::{square::Square, bitboard::BitboardFns}; + +use super::{Board, Color, PieceType, CastlingSide}; + + +const TOTAL_PIECES: usize = 12; +const TOTAL_SQUARES: usize = 64; +const TOTAL_FILES: usize = 8; +const TOTAL_CASTLING_RIGHTS: usize = 4; +const ZOBRIST_SEED_SIZE: usize = TOTAL_SQUARES * TOTAL_PIECES + TOTAL_CASTLING_RIGHTS + TOTAL_FILES + 1; + +pub type ZobristSeed = [u64; ZOBRIST_SEED_SIZE]; + +pub trait Zobrist { + fn seed() -> ZobristSeed; + + /// Compute store zobrist hash of the current position + /// https://www.chessprogramming.org/Zobrist_Hashing + fn compute_hash(&mut self) -> (); + + fn zobrist_toggle_piece(&mut self, piece_type: PieceType, square: Square) -> (); + fn zobrist_toggle_castling_right(&mut self, color: Color, side: CastlingSide) -> (); + fn zobrist_toggle_ep_square(&mut self, ep_square: Square) -> (); + fn zobrist_toggle_color(&mut self) -> (); +} + +impl Zobrist for Board { + fn seed() -> ZobristSeed { + let mut rng = StdRng::seed_from_u64(228); + [(); ZOBRIST_SEED_SIZE].map(|_| rng.gen()) + } + + fn compute_hash(&mut self) -> () { + self.hash = 0; + + for piece_id in 0..self.piece_sets.len() { + for square in self.piece_sets[piece_id].serialize() { + self.zobrist_toggle_piece(PieceType::from(piece_id), square); + } + } + for color in [Color::White, Color::Black] { + for castle_side in [CastlingSide::King, CastlingSide::Queen] { + if self.castling_rights[color as usize][castle_side as usize] { + self.zobrist_toggle_castling_right(color, castle_side) + } + } + } + + match self.ep_target { + Some(square) => self.zobrist_toggle_ep_square(square), + None => {}, + } + + if self.color() == Color::Black { + self.zobrist_toggle_color(); + } + } + + fn zobrist_toggle_piece(&mut self, piece_type: PieceType, square: Square) -> () { + self.hash ^= self.zobrist_seed[piece_type as usize * TOTAL_SQUARES + square as usize]; + } + + fn zobrist_toggle_castling_right(&mut self, color: Color, side: CastlingSide) -> () { + self.hash ^= self.zobrist_seed[(TOTAL_PIECES * TOTAL_SQUARES) + color as usize * 2 + side as usize]; + } + + fn zobrist_toggle_ep_square(&mut self, ep_square: Square) -> () { + self.hash ^= self.zobrist_seed[(TOTAL_PIECES * TOTAL_SQUARES + TOTAL_CASTLING_RIGHTS) + ep_square.file() as usize]; + } + + fn zobrist_toggle_color(&mut self) -> () { + self.hash ^= match self.zobrist_seed.last() { + Some(x) => x, + None => panic!("Something is wrong with zobrist seed list"), + }; + } +} |