diff --git a/src/board/chess_board/error.rs b/src/board/chess_board/error.rs index e6ef030..4265de0 100644 --- a/src/board/chess_board/error.rs +++ b/src/board/chess_board/error.rs @@ -21,6 +21,8 @@ pub enum InvalidError { OverlappingColors, /// The pre-computed combined occupancy boards does not match the other boards. ErroneousCombinedOccupancy, + /// Half-move clock is higher than total number of plies. + HalfMoveClockTooHigh, } impl std::fmt::Display for InvalidError { @@ -42,6 +44,7 @@ impl std::fmt::Display for InvalidError { Self::ErroneousCombinedOccupancy => { "The pre-computed combined occupancy boards does not match the other boards." } + Self::HalfMoveClockTooHigh => "Half-move clock is higher than total number of plies.", }; write!(f, "{}", error_msg) } diff --git a/src/board/chess_board/mod.rs b/src/board/chess_board/mod.rs index 99d6df6..879aba6 100644 --- a/src/board/chess_board/mod.rs +++ b/src/board/chess_board/mod.rs @@ -208,6 +208,11 @@ impl ChessBoard { /// Validate the state of the board. Return Err([InvalidError]) if an issue is found. pub fn validate(&self) -> Result<(), InvalidError> { + // Make sure the clocks are in agreement. + if u32::from(self.half_move_clock()) > self.total_plies() { + return Err(InvalidError::HalfMoveClockTooHigh); + } + // Don't overlap pieces. for piece in Piece::iter() { #[allow(clippy::collapsible_if)] @@ -423,6 +428,18 @@ mod test { assert!(default_position.is_valid()); } + #[test] + fn invalid_half_moves_clock() { + let res = { + let mut builder = ChessBoardBuilder::new(); + builder[Square::E1] = Some((Piece::King, Color::White)); + builder[Square::E8] = Some((Piece::King, Color::Black)); + builder.with_half_move_clock(10); + TryInto::::try_into(builder) + }; + assert_eq!(res.err().unwrap(), InvalidError::HalfMoveClockTooHigh); + } + #[test] fn invalid_overlapping_pieces() { let position = ChessBoard {