[board, explorer, moves] Clean up the castling rights API
Reorganize castling rights API on Board into methods named according to
conventions applied to other API.
Board::has_castling_right
Board::has_castling_right_active
Board::has_castling_right_unwrapped
    These all check if a color has the right to castle on a particular side
    (wing) of the board. The first takes an Option<Color>, the latter two
    operate on bare Colors: the active color, or an explicit Color.
Board::grant_castling_right
Board::grant_castling_right_active
Board::grant_castling_right_unwrapped
    Grant castling rights to a color. Color arguments follow the pattern above.
Board::revoke_castling_right
Board::revoke_castling_right_active
Board::revoke_castling_right_unwrapped
    Revoke castling rights from a color. Color arguments follow the pattern
    above.
The latter two groups of methods take a new CastleRightsOption type that
specifies either a single Wing or All.
Rework the implementation of CastleRights to take a CastleRightsOption. Update
the unit tests and make sure everything builds.
			
			
This commit is contained in:
		
							parent
							
								
									933924d37a
								
							
						
					
					
						commit
						4ce7e89cdb
					
				
					 8 changed files with 177 additions and 124 deletions
				
			
		|  | @ -1,13 +1,13 @@ | |||
| // Eryn Wells <eryn@erynwells.me>
 | ||||
| 
 | ||||
| use crate::{ | ||||
|     PieceSet, castle, | ||||
|     CastleRights, PieceSet, | ||||
|     display::DiagramFormatter, | ||||
|     piece_sets::{PlacePieceError, PlacePieceStrategy}, | ||||
|     zobrist::{ZobristHash, ZobristState}, | ||||
| }; | ||||
| use chessfriend_bitboard::BitBoard; | ||||
| use chessfriend_core::{Color, Piece, Shape, Square, Wing}; | ||||
| use chessfriend_core::{Color, Piece, Shape, Square}; | ||||
| use std::sync::Arc; | ||||
| 
 | ||||
| pub type HalfMoveClock = u32; | ||||
|  | @ -17,7 +17,7 @@ pub type FullMoveClock = u32; | |||
| pub struct Board { | ||||
|     active_color: Color, | ||||
|     pieces: PieceSet, | ||||
|     castling_rights: castle::Rights, | ||||
|     castling_rights: CastleRights, | ||||
|     en_passant_target: Option<Square>, | ||||
|     pub half_move_clock: HalfMoveClock, | ||||
|     pub full_move_number: FullMoveClock, | ||||
|  | @ -92,59 +92,27 @@ impl Board { | |||
| 
 | ||||
| impl Board { | ||||
|     #[must_use] | ||||
|     pub fn castling_rights(&self) -> castle::Rights { | ||||
|         self.castling_rights | ||||
|     pub fn castling_rights(&self) -> &CastleRights { | ||||
|         &self.castling_rights | ||||
|     } | ||||
| 
 | ||||
|     pub fn set_castling_rights(&mut self, rights: castle::Rights) { | ||||
|     pub(crate) fn castling_rights_mut(&mut self) -> &mut CastleRights { | ||||
|         &mut self.castling_rights | ||||
|     } | ||||
| 
 | ||||
|     /// Replace castling rights with new rights wholesale.
 | ||||
|     pub fn set_castling_rights(&mut self, rights: CastleRights) { | ||||
|         if rights == self.castling_rights { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         let old_rights = self.castling_rights; | ||||
|         self.castling_rights = rights; | ||||
| 
 | ||||
|         self.update_zobrist_hash_castling_rights(old_rights); | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn active_color_has_castling_right(&self, wing: Wing) -> bool { | ||||
|         self.color_has_castling_right_unwrapped(self.active_color, wing) | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn color_has_castling_right(&self, color: Option<Color>, wing: Wing) -> bool { | ||||
|         self.color_has_castling_right_unwrapped(self.unwrap_color(color), wing) | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn color_has_castling_right_unwrapped(&self, color: Color, wing: Wing) -> bool { | ||||
|         self.castling_rights.color_has_right(color, wing) | ||||
|     } | ||||
| 
 | ||||
|     pub fn grant_castling_right(&mut self, color: Color, wing: Wing) { | ||||
|         let old_rights = self.castling_rights; | ||||
|         self.castling_rights.grant(color, wing); | ||||
|         self.update_zobrist_hash_castling_rights(old_rights); | ||||
|     } | ||||
| 
 | ||||
|     pub fn revoke_all_castling_rights(&mut self) { | ||||
|         let old_rights = self.castling_rights; | ||||
|         self.castling_rights.revoke_all(); | ||||
|         self.update_zobrist_hash_castling_rights(old_rights); | ||||
|     } | ||||
| 
 | ||||
|     pub fn revoke_castling_right(&mut self, color: Option<Color>, wing: Wing) { | ||||
|         let color = self.unwrap_color(color); | ||||
|         self.revoke_castling_right_unwrapped(color, wing); | ||||
|     } | ||||
| 
 | ||||
|     pub fn revoke_castling_right_unwrapped(&mut self, color: Color, wing: Wing) { | ||||
|         let old_rights = self.castling_rights; | ||||
|         self.castling_rights.revoke(color, wing); | ||||
|         self.update_zobrist_hash_castling_rights(old_rights); | ||||
|     } | ||||
| 
 | ||||
|     fn update_zobrist_hash_castling_rights(&mut self, old_rights: castle::Rights) { | ||||
|     pub(crate) fn update_zobrist_hash_castling_rights(&mut self, old_rights: CastleRights) { | ||||
|         let new_rights = self.castling_rights; | ||||
|         if old_rights == new_rights { | ||||
|             return; | ||||
|  | @ -154,6 +122,18 @@ impl Board { | |||
|             zobrist.update_modifying_castling_rights(new_rights, old_rights); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) fn castling_king(&self, square: Square) -> Option<Piece> { | ||||
|         let active_color = self.active_color(); | ||||
|         self.get_piece(square) | ||||
|             .filter(|piece| piece.color == active_color && piece.is_king()) | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) fn castling_rook(&self, square: Square) -> Option<Piece> { | ||||
|         let active_color = self.active_color(); | ||||
|         self.get_piece(square) | ||||
|             .filter(|piece| piece.color == active_color && piece.is_rook()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Board { | ||||
|  |  | |||
|  | @ -4,10 +4,10 @@ mod parameters; | |||
| mod rights; | ||||
| 
 | ||||
| pub use parameters::Parameters; | ||||
| pub use rights::Rights; | ||||
| pub use rights::{CastleRightsOption, Rights}; | ||||
| 
 | ||||
| use crate::{Board, CastleParameters}; | ||||
| use chessfriend_core::{Color, Piece, Square, Wing}; | ||||
| use chessfriend_core::{Color, Wing}; | ||||
| use thiserror::Error; | ||||
| 
 | ||||
| #[derive(Clone, Copy, Debug, Error, Eq, PartialEq)] | ||||
|  | @ -46,7 +46,7 @@ impl Board { | |||
| 
 | ||||
|         let color = self.unwrap_color(color); | ||||
| 
 | ||||
|         if !self.color_has_castling_right_unwrapped(color, wing) { | ||||
|         if !self.has_castling_right_unwrapped(color, wing.into()) { | ||||
|             return Err(CastleEvaluationError::NoRights { color, wing }); | ||||
|         } | ||||
| 
 | ||||
|  | @ -76,17 +76,60 @@ impl Board { | |||
| 
 | ||||
|         Ok(parameters) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|     pub(crate) fn castling_king(&self, square: Square) -> Option<Piece> { | ||||
|         let active_color = self.active_color(); | ||||
|         self.get_piece(square) | ||||
|             .filter(|piece| piece.color == active_color && piece.is_king()) | ||||
| impl Board { | ||||
|     #[must_use] | ||||
|     pub fn has_castling_right(&self, color: Option<Color>, wing: Wing) -> bool { | ||||
|         self.has_castling_right_unwrapped(self.unwrap_color(color), wing) | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) fn castling_rook(&self, square: Square) -> Option<Piece> { | ||||
|         let active_color = self.active_color(); | ||||
|         self.get_piece(square) | ||||
|             .filter(|piece| piece.color == active_color && piece.is_rook()) | ||||
|     #[must_use] | ||||
|     pub fn has_castling_right_active(&self, wing: Wing) -> bool { | ||||
|         self.has_castling_right_unwrapped(self.active_color(), wing) | ||||
|     } | ||||
| 
 | ||||
|     #[must_use] | ||||
|     pub fn has_castling_right_unwrapped(&self, color: Color, wing: Wing) -> bool { | ||||
|         self.castling_rights().get(color, wing.into()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Board { | ||||
|     pub fn grant_castling_rights(&mut self, color: Option<Color>, rights: CastleRightsOption) { | ||||
|         let color = self.unwrap_color(color); | ||||
|         self.grant_castling_rights_unwrapped(color, rights); | ||||
|     } | ||||
| 
 | ||||
|     pub fn grant_castling_rights_active(&mut self, rights: CastleRightsOption) { | ||||
|         self.grant_castling_rights_unwrapped(self.active_color(), rights); | ||||
|     } | ||||
| 
 | ||||
|     pub fn grant_castling_rights_unwrapped(&mut self, color: Color, rights: CastleRightsOption) { | ||||
|         let old_rights = *self.castling_rights(); | ||||
|         self.castling_rights_mut().grant(color, rights); | ||||
|         self.update_zobrist_hash_castling_rights(old_rights); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Board { | ||||
|     pub fn revoke_all_castling_rights(&mut self) { | ||||
|         self.castling_rights_mut().revoke_all(); | ||||
|     } | ||||
| 
 | ||||
|     pub fn revoke_castling_rights(&mut self, color: Option<Color>, rights: CastleRightsOption) { | ||||
|         let color = self.unwrap_color(color); | ||||
|         self.revoke_castling_rights_unwrapped(color, rights); | ||||
|     } | ||||
| 
 | ||||
|     pub fn revoke_castling_rights_active(&mut self, rights: CastleRightsOption) { | ||||
|         self.revoke_castling_rights_unwrapped(self.active_color(), rights); | ||||
|     } | ||||
| 
 | ||||
|     pub fn revoke_castling_rights_unwrapped(&mut self, color: Color, rights: CastleRightsOption) { | ||||
|         let old_rights = *self.castling_rights(); | ||||
|         self.castling_rights_mut().revoke(color, rights); | ||||
|         self.update_zobrist_hash_castling_rights(old_rights); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -104,8 +147,8 @@ mod tests { | |||
|             White Rook on H1 | ||||
|         ); | ||||
| 
 | ||||
|         assert!(board.color_has_castling_right_unwrapped(Color::White, Wing::KingSide)); | ||||
|         assert!(board.color_has_castling_right_unwrapped(Color::White, Wing::QueenSide)); | ||||
|         assert!(board.has_castling_right_unwrapped(Color::White, Wing::KingSide)); | ||||
|         assert!(board.has_castling_right_unwrapped(Color::White, Wing::QueenSide)); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|  |  | |||
|  | @ -1,6 +1,14 @@ | |||
| // Eryn Wells <eryn@erynwells.me>
 | ||||
| 
 | ||||
| use chessfriend_core::{Color, Wing}; | ||||
| use std::fmt; | ||||
| 
 | ||||
| #[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||||
| pub enum CastleRightsOption { | ||||
|     Wing(Wing), | ||||
|     All, | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Copy, Eq, Hash, PartialEq)] | ||||
| pub struct Rights(u8); | ||||
| 
 | ||||
|  | @ -12,16 +20,16 @@ impl Rights { | |||
|     /// as long as they have not moved their king, or the rook on that side of
 | ||||
|     /// the board.
 | ||||
|     #[must_use] | ||||
|     pub fn color_has_right(self, color: Color, wing: Wing) -> bool { | ||||
|         (self.0 & (1 << Self::flag_offset(color, wing))) != 0 | ||||
|     pub fn get(self, color: Color, option: CastleRightsOption) -> bool { | ||||
|         (self.0 & Self::flags(color, option)) != 0 | ||||
|     } | ||||
| 
 | ||||
|     pub fn grant(&mut self, color: Color, wing: Wing) { | ||||
|         self.0 |= 1 << Self::flag_offset(color, wing); | ||||
|     pub fn grant(&mut self, color: Color, option: CastleRightsOption) { | ||||
|         self.0 |= Self::flags(color, option); | ||||
|     } | ||||
| 
 | ||||
|     pub fn revoke(&mut self, color: Color, wing: Wing) { | ||||
|         self.0 &= !(1 << Self::flag_offset(color, wing)); | ||||
|     pub fn revoke(&mut self, color: Color, option: CastleRightsOption) { | ||||
|         self.0 &= !Self::flags(color, option); | ||||
|     } | ||||
| 
 | ||||
|     /// Revoke castling rights for all colors and all sides of the board.
 | ||||
|  | @ -31,14 +39,14 @@ impl Rights { | |||
| } | ||||
| 
 | ||||
| impl Rights { | ||||
|     pub(crate) fn as_index(&self) -> usize { | ||||
|     pub(crate) fn as_index(self) -> usize { | ||||
|         self.0 as usize | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Rights { | ||||
|     fn flag_offset(color: Color, wing: Wing) -> usize { | ||||
|         ((color as usize) << 1) + wing as usize | ||||
|     const fn flags(color: Color, option: CastleRightsOption) -> u8 { | ||||
|         option.as_flags() << (color as u8 * 2) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -54,36 +62,55 @@ impl Default for Rights { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl CastleRightsOption { | ||||
|     #[must_use] | ||||
|     pub const fn as_flags(self) -> u8 { | ||||
|         match self { | ||||
|             Self::Wing(wing) => 1 << (wing as u8), | ||||
|             Self::All => (1 << Wing::KingSide as u8) | (1 << Wing::QueenSide as u8), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<Wing> for CastleRightsOption { | ||||
|     fn from(value: Wing) -> Self { | ||||
|         Self::Wing(value) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     use super::*; | ||||
| 
 | ||||
|     #[test] | ||||
|     fn bitfield_offsets() { | ||||
|         assert_eq!(Rights::flag_offset(Color::White, Wing::KingSide), 0); | ||||
|         assert_eq!(Rights::flag_offset(Color::White, Wing::QueenSide), 1); | ||||
|         assert_eq!(Rights::flag_offset(Color::Black, Wing::KingSide), 2); | ||||
|         assert_eq!(Rights::flag_offset(Color::Black, Wing::QueenSide), 3); | ||||
|         assert_eq!(Rights::flags(Color::White, Wing::KingSide.into()), 1); | ||||
|         assert_eq!(Rights::flags(Color::White, Wing::QueenSide.into()), 1 << 1); | ||||
|         assert_eq!(Rights::flags(Color::Black, Wing::KingSide.into()), 1 << 2); | ||||
|         assert_eq!(Rights::flags(Color::Black, Wing::QueenSide.into()), 1 << 3); | ||||
| 
 | ||||
|         assert_eq!(Rights::flags(Color::White, CastleRightsOption::All), 0b11); | ||||
|         assert_eq!(Rights::flags(Color::Black, CastleRightsOption::All), 0b1100); | ||||
|     } | ||||
| 
 | ||||
|     #[test] | ||||
|     fn default_rights() { | ||||
|         let mut rights = Rights::default(); | ||||
|         assert!(rights.color_has_right(Color::White, Wing::KingSide)); | ||||
|         assert!(rights.color_has_right(Color::White, Wing::QueenSide)); | ||||
|         assert!(rights.color_has_right(Color::Black, Wing::KingSide)); | ||||
|         assert!(rights.color_has_right(Color::Black, Wing::QueenSide)); | ||||
|         assert!(rights.get(Color::White, Wing::KingSide.into())); | ||||
|         assert!(rights.get(Color::White, Wing::QueenSide.into())); | ||||
|         assert!(rights.get(Color::Black, Wing::KingSide.into())); | ||||
|         assert!(rights.get(Color::Black, Wing::QueenSide.into())); | ||||
| 
 | ||||
|         rights.revoke(Color::White, Wing::QueenSide); | ||||
|         assert!(rights.color_has_right(Color::White, Wing::KingSide)); | ||||
|         assert!(!rights.color_has_right(Color::White, Wing::QueenSide)); | ||||
|         assert!(rights.color_has_right(Color::Black, Wing::KingSide)); | ||||
|         assert!(rights.color_has_right(Color::Black, Wing::QueenSide)); | ||||
|         rights.revoke(Color::White, Wing::QueenSide.into()); | ||||
|         assert!(rights.get(Color::White, Wing::KingSide.into())); | ||||
|         assert!(!rights.get(Color::White, Wing::QueenSide.into())); | ||||
|         assert!(rights.get(Color::Black, Wing::KingSide.into())); | ||||
|         assert!(rights.get(Color::Black, Wing::QueenSide.into())); | ||||
| 
 | ||||
|         rights.grant(Color::White, Wing::QueenSide); | ||||
|         assert!(rights.color_has_right(Color::White, Wing::KingSide)); | ||||
|         assert!(rights.color_has_right(Color::White, Wing::QueenSide)); | ||||
|         assert!(rights.color_has_right(Color::Black, Wing::KingSide)); | ||||
|         assert!(rights.color_has_right(Color::Black, Wing::QueenSide)); | ||||
|         rights.grant(Color::White, Wing::QueenSide.into()); | ||||
|         assert!(rights.get(Color::White, Wing::KingSide.into())); | ||||
|         assert!(rights.get(Color::White, Wing::QueenSide.into())); | ||||
|         assert!(rights.get(Color::Black, Wing::KingSide.into())); | ||||
|         assert!(rights.get(Color::Black, Wing::QueenSide.into())); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -24,12 +24,16 @@ pub enum ToFenStrError { | |||
| pub enum FromFenStrError { | ||||
|     #[error("missing {0} field")] | ||||
|     MissingField(Field), | ||||
| 
 | ||||
|     #[error("missing piece placement")] | ||||
|     MissingPlacement, | ||||
| 
 | ||||
|     #[error("invalid value")] | ||||
|     InvalidValue, | ||||
| 
 | ||||
|     #[error("{0}")] | ||||
|     ParseIntError(#[from] std::num::ParseIntError), | ||||
| 
 | ||||
|     #[error("{0}")] | ||||
|     ParseSquareError(#[from] ParseSquareError), | ||||
| } | ||||
|  | @ -122,12 +126,12 @@ impl ToFenStr for Board { | |||
|             (Color::Black, Wing::KingSide), | ||||
|             (Color::Black, Wing::QueenSide), | ||||
|         ] | ||||
|         .map(|(color, castle)| { | ||||
|             if !self.color_has_castling_right_unwrapped(color, castle) { | ||||
|         .map(|(color, wing)| { | ||||
|             if !self.has_castling_right_unwrapped(color, wing) { | ||||
|                 return ""; | ||||
|             } | ||||
| 
 | ||||
|             match (color, castle) { | ||||
|             match (color, wing) { | ||||
|                 (Color::White, Wing::KingSide) => "K", | ||||
|                 (Color::White, Wing::QueenSide) => "Q", | ||||
|                 (Color::Black, Wing::KingSide) => "k", | ||||
|  | @ -226,19 +230,23 @@ impl FromFenStr for Board { | |||
|         )?; | ||||
|         board.set_active_color(active_color); | ||||
| 
 | ||||
|         let color_wing_from_char = |ch| match ch { | ||||
|             'K' => Some((Color::White, Wing::KingSide)), | ||||
|             'Q' => Some((Color::White, Wing::QueenSide)), | ||||
|             'k' => Some((Color::Black, Wing::KingSide)), | ||||
|             'q' => Some((Color::Black, Wing::QueenSide)), | ||||
|             _ => None, | ||||
|         }; | ||||
| 
 | ||||
|         let castling_rights = fields | ||||
|             .next() | ||||
|             .ok_or(FromFenStrError::MissingField(Field::CastlingRights))?; | ||||
|         board.revoke_all_castling_rights(); | ||||
|         if castling_rights != "-" { | ||||
|             for ch in castling_rights.chars() { | ||||
|                 match ch { | ||||
|                     'K' => board.grant_castling_right(Color::White, Wing::KingSide), | ||||
|                     'Q' => board.grant_castling_right(Color::White, Wing::QueenSide), | ||||
|                     'k' => board.grant_castling_right(Color::Black, Wing::KingSide), | ||||
|                     'q' => board.grant_castling_right(Color::Black, Wing::QueenSide), | ||||
|                     _ => return Err(FromFenStrError::InvalidValue), | ||||
|                 }; | ||||
|                 let (color, wing) = | ||||
|                     color_wing_from_char(ch).ok_or(FromFenStrError::InvalidValue)?; | ||||
|                 board.grant_castling_rights_unwrapped(color, wing.into()); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,16 +1,11 @@ | |||
| // Eryn Wells <eryn@erynwells.me>
 | ||||
| 
 | ||||
| use chessfriend_board::castle::CastleEvaluationError; | ||||
| use chessfriend_board::{Board, fen::FromFenStr}; | ||||
| use chessfriend_board::{CastleParameters, ZobristState}; | ||||
| use chessfriend_core::random::RandomNumberGenerator; | ||||
| use chessfriend_core::{Color, Piece, Shape, Square, Wing}; | ||||
| use chessfriend_moves::algebraic::AlgebraicMoveComponents; | ||||
| use chessfriend_moves::{GeneratedMove, ValidateMove}; | ||||
| use chessfriend_board::{Board, ZobristState, fen::FromFenStr}; | ||||
| use chessfriend_core::{Color, Piece, Shape, Square, Wing, random::RandomNumberGenerator}; | ||||
| use chessfriend_moves::{GeneratedMove, ValidateMove, algebraic::AlgebraicMoveComponents}; | ||||
| use chessfriend_position::{PlacePieceStrategy, Position, fen::ToFenStr}; | ||||
| use clap::{Arg, Command, value_parser}; | ||||
| use rustyline::DefaultEditor; | ||||
| use rustyline::error::ReadlineError; | ||||
| use rustyline::{DefaultEditor, error::ReadlineError}; | ||||
| use std::sync::Arc; | ||||
| use thiserror::Error; | ||||
| 
 | ||||
|  | @ -202,7 +197,7 @@ fn do_flags_command(state: &mut State, _matches: &clap::ArgMatches) -> CommandRe | |||
|         (Color::Black, Wing::KingSide), | ||||
|         (Color::Black, Wing::QueenSide), | ||||
|     ] { | ||||
|         let has_right = board.color_has_castling_right_unwrapped(color, wing); | ||||
|         let has_right = board.has_castling_right_unwrapped(color, wing.into()); | ||||
|         let can_castle = board.color_can_castle(wing, Some(color)); | ||||
| 
 | ||||
|         let can_castle_message = match can_castle { | ||||
|  |  | |||
|  | @ -3,7 +3,8 @@ | |||
| use crate::{Move, MoveRecord}; | ||||
| use chessfriend_board::{ | ||||
|     Board, BoardProvider, CastleParameters, PlacePieceError, PlacePieceStrategy, | ||||
|     castle::CastleEvaluationError, movement::Movement, | ||||
|     castle::{CastleEvaluationError, CastleRightsOption}, | ||||
|     movement::Movement, | ||||
| }; | ||||
| use chessfriend_core::{Color, Piece, Rank, Shape, Square, Wing}; | ||||
| use thiserror::Error; | ||||
|  | @ -251,7 +252,7 @@ impl<T: BoardProvider> MakeMoveInternal for T { | |||
|         // original board state is preserved.
 | ||||
|         let record = MoveRecord::new(board, ply, None); | ||||
| 
 | ||||
|         board.revoke_castling_right_unwrapped(active_color, wing); | ||||
|         board.revoke_castling_rights_active(wing.into()); | ||||
| 
 | ||||
|         self.advance_board_state(&ply, &king, None, HalfMoveClock::Advance); | ||||
| 
 | ||||
|  | @ -307,23 +308,22 @@ impl<T: BoardProvider> MakeMoveInternal for T { | |||
|             Shape::Rook => { | ||||
|                 let origin = ply.origin_square(); | ||||
| 
 | ||||
|                 if board.color_has_castling_right(None, Wing::KingSide) { | ||||
|                 if board.has_castling_right(None, Wing::KingSide) { | ||||
|                     let kingside_parameters = | ||||
|                         CastleParameters::get(board.active_color(), Wing::KingSide); | ||||
|                     if origin == kingside_parameters.origin.rook { | ||||
|                         board.revoke_castling_right(None, Wing::KingSide); | ||||
|                         board.revoke_castling_rights(None, Wing::KingSide.into()); | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 let queenside_parameters = | ||||
|                     CastleParameters::get(board.active_color(), Wing::QueenSide); | ||||
|                 if origin == queenside_parameters.origin.rook { | ||||
|                     board.revoke_castling_right(None, Wing::QueenSide); | ||||
|                     board.revoke_castling_rights(None, Wing::QueenSide.into()); | ||||
|                 } | ||||
|             } | ||||
|             Shape::King => { | ||||
|                 board.revoke_castling_right(None, Wing::KingSide); | ||||
|                 board.revoke_castling_right(None, Wing::QueenSide); | ||||
|                 board.revoke_castling_rights(None, CastleRightsOption::All); | ||||
|             } | ||||
|             _ => {} | ||||
|         } | ||||
|  | @ -562,7 +562,7 @@ mod tests { | |||
|         assert_eq!(board.get_piece(Square::H1), None); | ||||
|         assert_eq!(board.get_piece(Square::G1), Some(piece!(White King))); | ||||
|         assert_eq!(board.get_piece(Square::F1), Some(piece!(White Rook))); | ||||
|         assert!(!board.color_has_castling_right_unwrapped(Color::White, Wing::KingSide)); | ||||
|         assert!(!board.has_castling_right_unwrapped(Color::White, Wing::KingSide)); | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
|  | @ -582,7 +582,7 @@ mod tests { | |||
|         assert_eq!(board.get_piece(Square::A1), None); | ||||
|         assert_eq!(board.get_piece(Square::C1), Some(piece!(White King))); | ||||
|         assert_eq!(board.get_piece(Square::D1), Some(piece!(White Rook))); | ||||
|         assert!(!board.color_has_castling_right_unwrapped(Color::White, Wing::QueenSide)); | ||||
|         assert!(!board.has_castling_right_unwrapped(Color::White, Wing::QueenSide)); | ||||
| 
 | ||||
|         Ok(()) | ||||
|     } | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| // Eryn Wells <eryn@erynwells.me>
 | ||||
| 
 | ||||
| use crate::Move; | ||||
| use chessfriend_board::{board::HalfMoveClock, Board, CastleRights}; | ||||
| use chessfriend_board::{Board, CastleRights, board::HalfMoveClock}; | ||||
| use chessfriend_core::{Color, Piece, Square}; | ||||
| 
 | ||||
| /// A record of a move made on a board. This struct contains all the information
 | ||||
|  | @ -35,7 +35,7 @@ impl MoveRecord { | |||
|             color: board.active_color(), | ||||
|             ply, | ||||
|             en_passant_target: board.en_passant_target(), | ||||
|             castling_rights: board.castling_rights(), | ||||
|             castling_rights: *board.castling_rights(), | ||||
|             half_move_clock: board.half_move_clock, | ||||
|             captured_piece: capture, | ||||
|         } | ||||
|  |  | |||
|  | @ -396,7 +396,7 @@ mod tests { | |||
|             White Rook on H1, | ||||
|         ]; | ||||
| 
 | ||||
|         let original_castling_rights = board.castling_rights(); | ||||
|         let original_castling_rights = *board.castling_rights(); | ||||
| 
 | ||||
|         let ply = Move::castle(Color::White, Wing::KingSide); | ||||
|         let record = board.make_move(ply, ValidateMove::Yes)?; | ||||
|  | @ -406,7 +406,7 @@ mod tests { | |||
|         assert_eq!(board.get_piece(Square::H1), None); | ||||
|         assert_eq!(board.get_piece(Square::G1), Some(piece!(White King))); | ||||
|         assert_eq!(board.get_piece(Square::F1), Some(piece!(White Rook))); | ||||
|         assert!(!board.color_has_castling_right_unwrapped(Color::White, Wing::KingSide)); | ||||
|         assert!(!board.has_castling_right_unwrapped(Color::White, Wing::KingSide)); | ||||
| 
 | ||||
|         board.unmake_move(&record)?; | ||||
| 
 | ||||
|  | @ -415,7 +415,7 @@ mod tests { | |||
|         assert_eq!(board.get_piece(Square::H1), Some(piece!(White Rook))); | ||||
|         assert_eq!(board.get_piece(Square::G1), None); | ||||
|         assert_eq!(board.get_piece(Square::F1), None); | ||||
|         assert_eq!(board.castling_rights(), original_castling_rights); | ||||
|         assert_eq!(*board.castling_rights(), original_castling_rights); | ||||
|         assert_eq!(board.active_color(), Color::White); | ||||
| 
 | ||||
|         Ok(()) | ||||
|  | @ -428,7 +428,7 @@ mod tests { | |||
|             White Rook on A1, | ||||
|         ]; | ||||
| 
 | ||||
|         let original_castling_rights = board.castling_rights(); | ||||
|         let original_castling_rights = *board.castling_rights(); | ||||
| 
 | ||||
|         let ply = Move::castle(Color::White, Wing::QueenSide); | ||||
|         let record = board.make_move(ply, ValidateMove::Yes)?; | ||||
|  | @ -438,7 +438,7 @@ mod tests { | |||
|         assert_eq!(board.get_piece(Square::A1), None); | ||||
|         assert_eq!(board.get_piece(Square::C1), Some(piece!(White King))); | ||||
|         assert_eq!(board.get_piece(Square::D1), Some(piece!(White Rook))); | ||||
|         assert!(!board.color_has_castling_right_unwrapped(Color::White, Wing::QueenSide)); | ||||
|         assert!(!board.has_castling_right_unwrapped(Color::White, Wing::QueenSide)); | ||||
| 
 | ||||
|         board.unmake_move(&record)?; | ||||
| 
 | ||||
|  | @ -447,7 +447,7 @@ mod tests { | |||
|         assert_eq!(board.get_piece(Square::A1), Some(piece!(White Rook))); | ||||
|         assert_eq!(board.get_piece(Square::C1), None); | ||||
|         assert_eq!(board.get_piece(Square::D1), None); | ||||
|         assert_eq!(board.castling_rights(), original_castling_rights); | ||||
|         assert_eq!(*board.castling_rights(), original_castling_rights); | ||||
|         assert_eq!(board.active_color(), Color::White); | ||||
| 
 | ||||
|         Ok(()) | ||||
|  | @ -460,7 +460,7 @@ mod tests { | |||
|             Black Rook on H8, | ||||
|         ]); | ||||
| 
 | ||||
|         let original_castling_rights = board.castling_rights(); | ||||
|         let original_castling_rights = *board.castling_rights(); | ||||
| 
 | ||||
|         let ply = Move::castle(Color::Black, Wing::KingSide); | ||||
|         let record = board.make_move(ply, ValidateMove::Yes)?; | ||||
|  | @ -478,7 +478,7 @@ mod tests { | |||
|         assert_eq!(board.get_piece(Square::H8), Some(piece!(Black Rook))); | ||||
|         assert_eq!(board.get_piece(Square::G8), None); | ||||
|         assert_eq!(board.get_piece(Square::F8), None); | ||||
|         assert_eq!(board.castling_rights(), original_castling_rights); | ||||
|         assert_eq!(*board.castling_rights(), original_castling_rights); | ||||
|         assert_eq!(board.active_color(), Color::Black); | ||||
| 
 | ||||
|         Ok(()) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue