From c7b954400475a65f3ba8cd040a7a5217bef4f7cb Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Tue, 17 Jun 2025 16:18:48 -0700 Subject: [PATCH] [moves] Revoke castling rights when King and Rook make moves of their starting squares When the King moves, revoke all rights for the moving player. When the rook moves, revoke castling rights for that side of the board, if it's moving off its starting square. --- moves/src/make_move.rs | 55 +++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/moves/src/make_move.rs b/moves/src/make_move.rs index 38b03cf..7b8fd33 100644 --- a/moves/src/make_move.rs +++ b/moves/src/make_move.rs @@ -2,10 +2,10 @@ use crate::{Move, MoveRecord}; use chessfriend_board::{ - castle::CastleEvaluationError, movement::Movement, Board, BoardProvider, PlacePieceError, - PlacePieceStrategy, + Board, BoardProvider, CastleParameters, PlacePieceError, PlacePieceStrategy, + castle::CastleEvaluationError, movement::Movement, }; -use chessfriend_core::{Color, Piece, Rank, Square, Wing}; +use chessfriend_core::{Color, Piece, Rank, Shape, Square, Wing}; use thiserror::Error; pub type MakeMoveResult = Result; @@ -83,6 +83,8 @@ trait MakeMoveInternal { fn advance_board_state( &mut self, + ply: &Move, + piece_moved: &Piece, en_passant_target: Option, half_move_clock: HalfMoveClock, ); @@ -151,7 +153,7 @@ impl MakeMoveInternal for T { let record = MoveRecord::new(board, ply, None); - self.advance_board_state(None, HalfMoveClock::Advance); + self.advance_board_state(&ply, &piece, None, HalfMoveClock::Advance); Ok(record) } @@ -179,7 +181,12 @@ impl MakeMoveInternal for T { _ => unreachable!(), }; - self.advance_board_state(Some(en_passant_target), HalfMoveClock::Advance); + self.advance_board_state( + &ply, + &piece, + Some(en_passant_target), + HalfMoveClock::Advance, + ); Ok(record) } @@ -221,7 +228,7 @@ impl MakeMoveInternal for T { let record = MoveRecord::new(board, ply, Some(captured_piece)); - self.advance_board_state(None, HalfMoveClock::Reset); + self.advance_board_state(&ply, &piece, None, HalfMoveClock::Reset); Ok(record) } @@ -246,7 +253,7 @@ impl MakeMoveInternal for T { board.revoke_castling_right_unwrapped(active_color, wing); - self.advance_board_state(None, HalfMoveClock::Advance); + self.advance_board_state(&ply, &king, None, HalfMoveClock::Advance); Ok(record) } @@ -280,28 +287,52 @@ impl MakeMoveInternal for T { let record = MoveRecord::new(board, ply, None); - self.advance_board_state(None, HalfMoveClock::Reset); + self.advance_board_state(&ply, &piece, None, HalfMoveClock::Reset); Ok(record) } fn advance_board_state( &mut self, + ply: &Move, + piece_moved: &Piece, en_passant_target: Option, half_move_clock: HalfMoveClock, ) { let board = self.board_mut(); - match half_move_clock { - HalfMoveClock::Reset => board.half_move_clock = 0, - HalfMoveClock::Advance => board.half_move_clock += 1, + board.set_en_passant_target_option(en_passant_target); + + match piece_moved.shape { + Shape::Rook => { + let origin = ply.origin_square(); + + if board.color_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); + } + } + + let queenside_parameters = + CastleParameters::get(board.active_color(), Wing::QueenSide); + if origin == queenside_parameters.origin.rook { + board.revoke_castling_right(None, Wing::QueenSide); + } + } + Shape::King => board.revoke_all_castling_rights(), + _ => {} } let previous_active_color = board.active_color(); let active_color = previous_active_color.next(); board.set_active_color(active_color); - board.set_en_passant_target_option(en_passant_target); + match half_move_clock { + HalfMoveClock::Reset => board.half_move_clock = 0, + HalfMoveClock::Advance => board.half_move_clock += 1, + } if active_color == Color::White { board.full_move_number += 1;