[position] Track seen board positions in a HashSet

As moves are made, keep track of the hashes of those board position. When moves
are unmade, pop seen hashes from the HashSet.

Reformat the imports in position.rs.
This commit is contained in:
Eryn Wells 2025-06-07 08:55:34 -07:00
parent c70cefc848
commit d2fc285af5

View file

@ -2,15 +2,6 @@
mod captures;
use chessfriend_moves::{
generators::{
AllPiecesMoveGenerator, BishopMoveGenerator, KingMoveGenerator, KnightMoveGenerator,
PawnMoveGenerator, QueenMoveGenerator, RookMoveGenerator,
},
GeneratedMove, MakeMove, MakeMoveError, Move, MoveRecord, UnmakeMove, UnmakeMoveError,
UnmakeMoveResult, ValidateMove,
};
use captures::CapturesList;
use chessfriend_bitboard::BitBoard;
use chessfriend_board::{
@ -18,7 +9,15 @@ use chessfriend_board::{
ZobristState,
};
use chessfriend_core::{Color, Piece, Shape, Square};
use std::{fmt, sync::Arc};
use chessfriend_moves::{
generators::{
AllPiecesMoveGenerator, BishopMoveGenerator, KingMoveGenerator, KnightMoveGenerator,
PawnMoveGenerator, QueenMoveGenerator, RookMoveGenerator,
},
GeneratedMove, MakeMove, MakeMoveError, Move, MoveRecord, UnmakeMove, UnmakeMoveError,
UnmakeMoveResult, ValidateMove,
};
use std::{collections::HashSet, fmt, sync::Arc};
#[must_use]
#[derive(Clone, Debug, Default, Eq)]
@ -26,6 +25,9 @@ pub struct Position {
pub board: Board,
pub(crate) moves: Vec<MoveRecord>,
pub(crate) captures: CapturesList,
/// A set of hashes of board positions seen throughout the move record.
boards_seen: HashSet<u64>,
}
impl Position {
@ -172,6 +174,13 @@ impl Position {
self.captures.push(record.color, captured_piece);
}
if let Some(hash) = self.board.zobrist_hash() {
// TODO: If the hash already exists here, it's a duplicate position
// and this move results in a draw. Find a way to indicate that,
// in either Board or Position.
self.boards_seen.insert(hash);
}
self.moves.push(record.clone());
Ok(())
@ -187,6 +196,8 @@ impl Position {
pub fn unmake_last_move(&mut self) -> UnmakeMoveResult {
let last_move_record = self.moves.pop().ok_or(UnmakeMoveError::NoMove)?;
let hash_before_unmake = self.board.zobrist_hash();
let unmake_result = self.board.unmake_move(&last_move_record);
if unmake_result.is_ok() {
@ -194,6 +205,10 @@ impl Position {
let popped_piece = self.captures.pop(last_move_record.color);
debug_assert_eq!(Some(capture), popped_piece);
}
if let Some(hash_before_unmake) = hash_before_unmake {
self.boards_seen.remove(&hash_before_unmake);
}
} else {
self.moves.push(last_move_record);
}