[board, core, moves, position] Implement castling

Implement a new method on Position that evaluates whether the active color can castle
on a given wing of the board. Then, implement making a castling move in the position.

Make a new Wing enum in the core crate to specify kingside or queenside. Replace the
Castle enum from the board crate with this one. This caused a lot of churn...

Along the way fix a bunch of tests.

Note: there's still no way to actually make a castling move in explorer.
This commit is contained in:
Eryn Wells 2025-05-19 16:50:30 -07:00
parent 6816e350eb
commit 0c1863acb9
18 changed files with 499 additions and 258 deletions

View file

@ -1,7 +1,6 @@
// Eryn Wells <eryn@erynwells.me>
use chessfriend_board::castle::Castle;
use chessfriend_core::{piece, Color, File, Shape, Square};
use chessfriend_core::{piece, Color, File, Shape, Square, Wing};
use chessfriend_moves::{testing::*, Builder, PromotionShape};
macro_rules! assert_flag {
@ -58,51 +57,50 @@ fn move_flags_capture() -> TestResult {
#[test]
fn move_flags_en_passant_capture() -> TestResult {
let mv = unsafe {
Builder::new()
.from(Square::A4)
.capturing_en_passant_on(Square::B3)
.build_unchecked()
};
let ply = Builder::new()
.from(Square::A4)
.capturing_en_passant_on(Square::B3)
.build()?;
assert_flags!(mv, false, false, true, true, false, false);
assert_eq!(mv.origin_square(), Square::A4);
assert_eq!(mv.target_square(), Square::B3);
assert_eq!(mv.capture_square(), Some(Square::B4));
assert!(ply.is_en_passant());
assert_eq!(ply.origin_square(), Square::A4);
assert_eq!(ply.target_square(), Square::B3);
assert_eq!(ply.capture_square(), Some(Square::B4));
Ok(())
}
#[test]
fn move_flags_promotion() -> TestResult {
let mv = Builder::push(&piece!(White Pawn on H7))
let ply = Builder::push(&piece!(White Pawn on H7))
.to(Square::H8)
.promoting_to(PromotionShape::Queen)
.build()?;
assert_flags!(mv, false, false, false, false, false, true);
assert_eq!(mv.promotion(), Some(Shape::Queen));
assert!(ply.is_promotion());
assert_eq!(ply.promotion(), Some(Shape::Queen));
Ok(())
}
#[test]
fn move_flags_capture_promotion() -> TestResult {
let mv = Builder::push(&piece!(White Pawn on H7))
let ply = Builder::push(&piece!(White Pawn on H7))
.to(Square::H8)
.capturing_piece(&piece!(Black Knight on G8))
.promoting_to(PromotionShape::Queen)
.build()?;
assert_flags!(mv, false, false, false, true, false, true);
assert_eq!(mv.promotion(), Some(Shape::Queen));
assert!(ply.is_capture());
assert!(ply.is_promotion());
assert_eq!(ply.promotion(), Some(Shape::Queen));
Ok(())
}
#[test]
fn move_flags_castle() -> TestResult {
let mv = Builder::castling(Color::White, Castle::KingSide).build()?;
let mv = Builder::castling(Color::White, Wing::KingSide).build()?;
assert_flags!(mv, false, false, false, false, true, false);