use chessfriend_core::Color; #[derive(Default)] pub enum AdvanceHalfMove { Reset, #[default] Advance, } #[derive(Clone, Copy, Debug, Default, Eq, PartialEq)] pub struct Clock { /// The player who's turn it is to move. pub(crate) active_color: Color, /// The number of completed turns. A turn finishes when every player has moved. pub(crate) full_move_number: u16, /// The number of moves by all players since the last pawn advance or capture. pub(crate) half_move_number: u16, } impl Clock { #[must_use] pub fn active_color(&self) -> Color { self.active_color } #[must_use] pub fn full_move_number(&self) -> u16 { self.full_move_number } #[must_use] pub fn half_move_number(&self) -> u16 { self.half_move_number } pub fn advance(&mut self, advance_half_move: &AdvanceHalfMove) { let next_color = self.active_color.next(); match self.active_color { Color::Black => self.full_move_number += 1, Color::White => {} } self.half_move_number = match advance_half_move { AdvanceHalfMove::Reset => 0, AdvanceHalfMove::Advance => self.half_move_number + 1, }; self.active_color = next_color; } } #[cfg(test)] mod tests { use super::*; #[test] fn default_state() { let clock = Clock::default(); assert_eq!(clock.active_color, Color::White); assert_eq!(clock.half_move_number, 0); assert_eq!(clock.full_move_number, 0); } #[test] fn advance() { let mut clock = Clock::default(); clock.advance(&AdvanceHalfMove::default()); assert_eq!(clock.active_color, Color::Black); assert_eq!(clock.half_move_number, 1); assert_eq!(clock.full_move_number, 0); clock.advance(&AdvanceHalfMove::default()); assert_eq!(clock.active_color, Color::White); assert_eq!(clock.half_move_number, 2); assert_eq!(clock.full_move_number, 1); clock.advance(&AdvanceHalfMove::default()); assert_eq!(clock.active_color, Color::Black); assert_eq!(clock.half_move_number, 3); assert_eq!(clock.full_move_number, 1); // The half move clock resets after a capture or pawn push. clock.advance(&AdvanceHalfMove::Reset); assert_eq!(clock.active_color, Color::White); assert_eq!(clock.half_move_number, 0); assert_eq!(clock.full_move_number, 2); } }