diff options
| author | eug-vs <eugene@eug-vs.xyz> | 2023-01-25 03:12:20 +0300 | 
|---|---|---|
| committer | eug-vs <eugene@eug-vs.xyz> | 2023-01-25 03:12:20 +0300 | 
| commit | 46b862a25203cb492dd45ba1696a28338a42065b (patch) | |
| tree | 3a68d3e5e99e514a303a2842653cbbfa3dc5bf3b /src/board/mod.rs | |
| parent | 05e6d002225f561c9725b25ef7960bc10421f723 (diff) | |
| download | chessnost-46b862a25203cb492dd45ba1696a28338a42065b.tar.gz | |
feat: incrementally update zobrist hash
Diffstat (limited to 'src/board/mod.rs')
| -rw-r--r-- | src/board/mod.rs | 47 | 
1 files changed, 38 insertions, 9 deletions
diff --git a/src/board/mod.rs b/src/board/mod.rs index 18e5e7f..a8166a1 100644 --- a/src/board/mod.rs +++ b/src/board/mod.rs @@ -483,6 +483,7 @@ impl Board {              {                  Some((target_piece, _)) => {                      self.pieces[target_piece] ^= move_target_bb; +                    self.hash ^= self.zobrist_seed[target_piece * 12 + mov.target as usize];                      Some(PieceType::from(target_piece))                  },                  None => None, @@ -491,7 +492,8 @@ impl Board {          // En Passant captures diffirently          if mov.kind == MoveKind::EnPassant {              debug_assert!(captured_piece.is_none(), "No capture should be found at this point"); -            let captured_bb = Square::from_coords(mov.source.rank(), mov.target.file()).to_bitboard(); +            let captured_square = Square::from_coords(mov.source.rank(), mov.target.file()); +            let captured_bb = captured_square.to_bitboard();              captured_piece = match self.pieces                  .iter()                  .enumerate() @@ -499,6 +501,7 @@ impl Board {                  {                      Some((pawn_type, _)) => {                          self.pieces[pawn_type] ^= captured_bb; +                        self.hash ^= self.zobrist_seed[pawn_type * 12 + captured_square as usize];                          Some(PieceType::from(pawn_type))                      }                      None => panic!("Pawn captured by En Passant was not found"), @@ -514,9 +517,11 @@ impl Board {                  Some((source_piece, _)) => {                      self.pieces[source_piece] ^= move_source_bb;                      self.occupancy            ^= move_source_bb; +                    self.hash                 ^= self.zobrist_seed[source_piece * 12 + mov.source as usize];                      self.pieces[source_piece] |= move_target_bb;                      self.occupancy            |= move_target_bb; +                    self.hash                 ^= self.zobrist_seed[source_piece * 12 + mov.target as usize];                      PieceType::from(source_piece)                  },                  None => panic!("Move is malformed: source piece not found"), @@ -530,8 +535,11 @@ impl Board {                  6 => (7, 5),                  _ => panic!("Malformed castle, target square invalid: {:?}", mov),              }; -            let rook_source_bb = Square::from_coords(mov.target.rank(), rook_source_file).to_bitboard(); -            let rook_target_bb = Square::from_coords(mov.target.rank(), rook_target_file).to_bitboard(); +            let rook_source_square = Square::from_coords(mov.target.rank(), rook_source_file); +            let rook_source_bb = rook_source_square.to_bitboard(); + +            let rook_target_square = Square::from_coords(mov.target.rank(), rook_target_file); +            let rook_target_bb = rook_target_square.to_bitboard();              match self.pieces                  .iter() @@ -541,9 +549,11 @@ impl Board {                      Some((rook_type, _)) => {                          self.pieces[rook_type] ^= rook_source_bb;                          self.occupancy         ^= rook_source_bb; +                        self.hash              ^= self.zobrist_seed[rook_type * 12 + rook_source_square as usize];                          self.pieces[rook_type] |= rook_target_bb;                          self.occupancy         |= rook_target_bb; +                        self.hash              ^= self.zobrist_seed[rook_type * 12 + rook_target_square as usize];                      },                      None => panic!("Rook was not found when castling"),                  } @@ -551,6 +561,7 @@ impl Board {          // Double push should set En Passant target square          self.ep_target = if mov.kind == MoveKind::DoublePush { +            self.hash ^= self.zobrist_seed[64 * 12 + 4 + mov.source.file() as usize];              match mov.source.rank() {                  1 => Some(mov.source.nort_one()),                  6 => Some(mov.source.sout_one()), @@ -559,15 +570,24 @@ impl Board {          } else { None };          // Withdraw castling rights when moving rooks or king +        let source_color = Color::from_piece(source_piece) as usize;          match source_piece {              PieceType::King => { -                self.castling_rights[Color::from_piece(source_piece) as usize][CastlingSide::King as usize] = false; -                self.castling_rights[Color::from_piece(source_piece) as usize][CastlingSide::Queen as usize] = false; +                self.castling_rights[source_color][CastlingSide::King as usize] = false; +                self.castling_rights[source_color][CastlingSide::Queen as usize] = false; +                self.hash ^= self.zobrist_seed[64 * 12 + source_color * 2 + 0]; +                self.hash ^= self.zobrist_seed[64 * 12 + source_color * 2 + 1];              },              PieceType::Rook => {                  match mov.source.file() { -                    0 => self.castling_rights[Color::from_piece(source_piece) as usize][CastlingSide::Queen as usize] = false, -                    7 => self.castling_rights[Color::from_piece(source_piece) as usize][CastlingSide::King as usize] = false, +                    0 => { +                        self.castling_rights[Color::from_piece(source_piece) as usize][CastlingSide::Queen as usize] = false; +                        self.hash ^= self.zobrist_seed[64 * 12 + source_color * 2 + CastlingSide::Queen as usize]; +                    } +                    7 => { +                        self.castling_rights[Color::from_piece(source_piece) as usize][CastlingSide::King as usize] = false; +                        self.hash ^= self.zobrist_seed[64 * 12 + source_color * 2 + CastlingSide::King as usize]; +                    }                      _ => {},                  }              }, @@ -575,12 +595,20 @@ impl Board {          }          self.ply += 1; +        self.hash ^= self.zobrist_seed[780];          captured_piece      }      /// Completely reverse make_move as if it never happened -    pub fn unmake_move(&mut self, mov: Move, captured_piece: Option<PieceType>, previous_ep_target: Option<Square>, previous_castling_rights: [[bool; 2]; 2]) { +    pub fn unmake_move( +        &mut self, +        mov: Move, +        captured_piece: Option<PieceType>, +        previous_ep_target: Option<Square>, +        previous_castling_rights: [[bool; 2]; 2], +        previous_hash: u64, +    ) {          let move_source_bb = mov.source.to_bitboard();          let move_target_bb = mov.target.to_bitboard(); @@ -648,6 +676,7 @@ impl Board {          self.ep_target = previous_ep_target;          self.castling_rights = previous_castling_rights; +        self.hash = previous_hash;          self.ply -= 1;      } @@ -838,7 +867,7 @@ mod tests {          let captured_piece = board.make_move(mov);          board.print(); -        board.unmake_move(mov, captured_piece, None, board.castling_rights); +        board.unmake_move(mov, captured_piece, None, board.castling_rights, initial_board.hash);          board.print();          assert_eq!(board, initial_board, "Board state after unmake_move should be the same as before make_move");  |