aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2023-02-21 13:26:18 +0300
committereug-vs <eugene@eug-vs.xyz>2023-02-21 13:26:18 +0300
commit0d5c2eb1666d3038fa87895cc98eadc673c54a3a (patch)
treea8a3ae3d618bfb33c214b990b3206cb158b1c527
parent08e27cdb8aa546833927b678d0a0d3ade1e91ef0 (diff)
downloadchessnost-0d5c2eb1666d3038fa87895cc98eadc673c54a3a.tar.gz
refactor: separate zobrist module
-rw-r--r--src/board/io.rs9
-rw-r--r--src/board/mod.rs43
-rw-r--r--src/board/zobrist.rs79
3 files changed, 88 insertions, 43 deletions
diff --git a/src/board/io.rs b/src/board/io.rs
index cb73c52..b5cd95e 100644
--- a/src/board/io.rs
+++ b/src/board/io.rs
@@ -1,9 +1,8 @@
use std::io::{stdin, stdout, Write};
-use rand::{rngs::StdRng,SeedableRng,Rng};
use crate::{bitboard::Bitboard, attacks::Attacks, moves::Move, square::Square};
-use super::{Board, PieceType, ttable::TTABLE_SIZE};
+use super::{Board, PieceType, ttable::TTABLE_SIZE, zobrist::Zobrist};
const PIECE_CHARS: [&str; 12] = [
"♟︎", "♞", "♝", "♜", "♛", "♚",
@@ -91,8 +90,6 @@ impl IO for Board {
}
}
- let mut rng = StdRng::seed_from_u64(228);
- let zobrist_seed = [(); 781].map(|_| rng.gen());
let mut board = Self {
piece_sets,
@@ -103,10 +100,10 @@ impl IO for Board {
ep_target: None, // TODO: parse from FEN
hash: 0,
transposition_table: vec![None; TTABLE_SIZE as usize],
- zobrist_seed,
+ zobrist_seed: Board::seed(),
};
board.update_occupancy();
- board.update_zobrist_hash();
+ board.compute_hash();
board
}
diff --git a/src/board/mod.rs b/src/board/mod.rs
index f7016d3..854ce0e 100644
--- a/src/board/mod.rs
+++ b/src/board/mod.rs
@@ -1,10 +1,12 @@
use crate::{bitboard::{Bitboard, BitboardFns}, moves::{Move, MoveKind}, attacks::Attacks, square::Square, board::io::IO};
-use self::ttable::{TranspositionTable, TTABLE_SIZE};
+use self::{ttable::{TranspositionTable, TTABLE_SIZE}, zobrist::ZobristSeed};
pub mod io;
+mod zobrist;
mod engine;
mod ttable;
+#[derive(Debug, Clone, Copy)]
pub enum CastlingSide {
King,
Queen,
@@ -26,7 +28,7 @@ pub struct Board {
// TODO: remove
transposition_table: TranspositionTable,
- zobrist_seed: [u64; 781],
+ zobrist_seed: ZobristSeed,
attacks: Attacks,
}
@@ -99,39 +101,6 @@ impl Board {
self.pieces_by_color(color).iter().fold(0, |acc, bitboard| acc | bitboard)
}
- /// Compute and store zobrist hash of the current position
- /// https://www.chessprogramming.org/Zobrist_Hashing
- fn update_zobrist_hash(&mut self) {
- self.hash = 0;
-
- if self.color() == Color::Black {
- self.hash ^= match self.zobrist_seed.last() {
- Some(x) => x,
- None => panic!("Something is wrong with zobrist seed list"),
- };
- }
-
- for (piece_id, bitboard) in self.piece_sets.iter().enumerate() {
- for square in bitboard.serialize() {
- self.hash ^= self.zobrist_seed[piece_id * 64 + square as usize];
- }
- }
-
- for color in 0..2 {
- for castle_side in 0..2 {
- if self.castling_rights[color][castle_side] {
- self.hash ^= self.zobrist_seed[(12 * 64) + color * 2 + castle_side];
- }
- }
- }
-
- match self.ep_target {
- Some(square) => {
- self.hash ^= self.zobrist_seed[(12 * 64 + 4) + square.file() as usize];
- },
- None => {},
- }
- }
fn ep_bitboard(&self) -> Bitboard {
@@ -731,7 +700,7 @@ impl Color {
#[cfg(test)]
mod tests {
use super::*;
- use crate::{bitboard::BitboardFns, square::Square};
+ use crate::{bitboard::BitboardFns, square::Square, board::zobrist::Zobrist};
#[test]
fn square_enum() {
@@ -813,7 +782,7 @@ mod tests {
board.print();
let hash = board.hash;
- board.update_zobrist_hash();
+ board.compute_hash();
assert_eq!(hash, board.hash, "Hash should be correctly updated after move");
assert!(board.piece_sets[PieceType::PawnBlack as usize] & Square::F7.to_bitboard() == 0);
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"),
+ };
+ }
+}