From 9815a63ebbf8e59ca3368aa702759ccbdeefc7b7 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Wed, 11 Jun 2025 08:15:06 -0700 Subject: [PATCH] [explorer] Print some question marks if a move is generated without target/origin squares The move I observed in my testing was a castling move, which doesn't set target and origin squares because those are provided by the castling parameters struct from the board crate. Fix the missing squares on castle moves by looking up castling parameters and populating them. This requires Move::castle() to take a Color in addition to the Wing. Update all the call sites. --- board/src/castle/parameters.rs | 2 +- explorer/src/main.rs | 8 ++++++-- moves/src/generators/king.rs | 6 ++++-- moves/src/make_move.rs | 4 ++-- moves/src/moves.rs | 12 +++++++++--- moves/src/unmake_move.rs | 11 +++++------ 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/board/src/castle/parameters.rs b/board/src/castle/parameters.rs index 54c3512..1052ab6 100644 --- a/board/src/castle/parameters.rs +++ b/board/src/castle/parameters.rs @@ -82,7 +82,7 @@ impl Parameters { ]; #[must_use] - pub fn get(color: Color, wing: Wing) -> &'static Parameters { + pub const fn get(color: Color, wing: Wing) -> &'static Parameters { &Self::BY_COLOR[color as usize][wing as usize] } } diff --git a/explorer/src/main.rs b/explorer/src/main.rs index 2e7a545..5b5c6ed 100644 --- a/explorer/src/main.rs +++ b/explorer/src/main.rs @@ -234,8 +234,12 @@ fn do_moves_command( let formatted_moves: Vec = moves .iter() .map(|ply| { - let piece = state.position.get_piece(ply.origin()).unwrap(); - format!("{piece}{ply}") + let origin = ply.origin(); + if let Some(piece) = state.position.get_piece(origin) { + format!("{piece}{ply}") + } else { + format!("{ply}??") + } }) .collect(); diff --git a/moves/src/generators/king.rs b/moves/src/generators/king.rs index aa7eea0..864c07d 100644 --- a/moves/src/generators/king.rs +++ b/moves/src/generators/king.rs @@ -105,6 +105,7 @@ impl FusedIterator for KingIterator {} #[derive(Clone, Debug)] struct CastleIterator { + color: Color, kingside: Option<&'static CastleParameters>, queenside: Option<&'static CastleParameters>, } @@ -115,6 +116,7 @@ impl CastleIterator { let queenside = board.color_can_castle(Wing::QueenSide, Some(color)).ok(); Self { + color, kingside, queenside, } @@ -126,11 +128,11 @@ impl Iterator for CastleIterator { fn next(&mut self) -> Option { if let Some(_parameters) = self.kingside.take() { - return Some(Move::castle(Wing::KingSide).into()); + return Some(Move::castle(self.color, Wing::KingSide).into()); } if let Some(_parameters) = self.queenside.take() { - return Some(Move::castle(Wing::QueenSide).into()); + return Some(Move::castle(self.color, Wing::QueenSide).into()); } None diff --git a/moves/src/make_move.rs b/moves/src/make_move.rs index 59a881e..bfb7d46 100644 --- a/moves/src/make_move.rs +++ b/moves/src/make_move.rs @@ -520,7 +520,7 @@ mod tests { White King on E1, ]; - let ply = Move::castle(Wing::KingSide); + let ply = Move::castle(Color::White, Wing::KingSide); board.make_move(ply, ValidateMove::Yes)?; assert_eq!(board.active_color(), Color::Black); @@ -540,7 +540,7 @@ mod tests { White Rook on A1, ]; - let ply = Move::castle(Wing::QueenSide); + let ply = Move::castle(Color::White, Wing::QueenSide); board.make_move(ply, ValidateMove::Yes)?; assert_eq!(board.active_color(), Color::Black); diff --git a/moves/src/moves.rs b/moves/src/moves.rs index c1fda0c..31226b5 100644 --- a/moves/src/moves.rs +++ b/moves/src/moves.rs @@ -2,7 +2,8 @@ use crate::defs::{Kind, PromotionShape}; use chessfriend_bitboard::BitBoard; -use chessfriend_core::{Rank, Shape, Square, Wing}; +use chessfriend_board::CastleParameters; +use chessfriend_core::{Color, Rank, Shape, Square, Wing}; use std::fmt; #[macro_export] @@ -109,12 +110,17 @@ impl Move { } #[must_use] - pub fn castle(wing: Wing) -> Self { + pub fn castle(color: Color, wing: Wing) -> Self { let flag_bits = match wing { Wing::KingSide => Kind::KingSideCastle, Wing::QueenSide => Kind::QueenSideCastle, } as u16; - Move(flag_bits) + + let parameters = CastleParameters::get(color, wing); + let origin = parameters.origin.king; + let target = parameters.target.king; + + Move(origin_bits(origin) | target_bits(target) | flag_bits) } } diff --git a/moves/src/unmake_move.rs b/moves/src/unmake_move.rs index 7fd3fec..2c6ebed 100644 --- a/moves/src/unmake_move.rs +++ b/moves/src/unmake_move.rs @@ -398,7 +398,7 @@ mod tests { let original_castling_rights = board.castling_rights(); - let ply = Move::castle(Wing::KingSide); + let ply = Move::castle(Color::White, Wing::KingSide); let record = board.make_move(ply, ValidateMove::Yes)?; // Verify castle was made @@ -430,7 +430,7 @@ mod tests { let original_castling_rights = board.castling_rights(); - let ply = Move::castle(Wing::QueenSide); + let ply = Move::castle(Color::White, Wing::QueenSide); let record = board.make_move(ply, ValidateMove::Yes)?; // Verify castle was made @@ -455,15 +455,14 @@ mod tests { #[test] fn unmake_black_kingside_castle() -> TestResult { - let mut board = test_board![ + let mut board = test_board!(Black, [ Black King on E8, Black Rook on H8, - ]; - board.set_active_color(Color::Black); + ]); let original_castling_rights = board.castling_rights(); - let ply = Move::castle(Wing::KingSide); + let ply = Move::castle(Color::Black, Wing::KingSide); let record = board.make_move(ply, ValidateMove::Yes)?; // Verify castle was made