1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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"),
};
}
}
|