From d2fc285af58c40b0a5cdd2fa02175d838f63b37a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 7 Jun 2025 08:55:34 -0700 Subject: [PATCH] [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. --- position/src/position.rs | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/position/src/position.rs b/position/src/position.rs index e674b81..17f36eb 100644 --- a/position/src/position.rs +++ b/position/src/position.rs @@ -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, pub(crate) captures: CapturesList, + + /// A set of hashes of board positions seen throughout the move record. + boards_seen: HashSet, } 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); }