Add white castling for both wings. Found some bugs in how king sight is computed while writing these. In order for the king to perform the castle, the Movement bitboard needs to return the two squares the king can castle to. That means anytime movement is calculated for the king, the (relatively expensive) castling evaluation needs to happen. Write two new helper static functions to create a Move for castling and promotion moves. Since structs cannot have any functions with the same name, the two methods that return properties related to those moves (Move::castle and Move::promotion) need to be renamed. They're now called Move::castle_wing and Move::promotion_shape.
108 lines
2.9 KiB
Rust
108 lines
2.9 KiB
Rust
// Eryn Wells <eryn@erynwells.me>
|
|
|
|
use chessfriend_core::{piece, Color, File, Shape, Square, Wing};
|
|
use chessfriend_moves::{testing::*, Builder, PromotionShape};
|
|
|
|
macro_rules! assert_flag {
|
|
($move:expr, $left:expr, $right:expr, $desc:expr) => {
|
|
assert_eq!($left, $right, "{:?} -> {}", $move, stringify!($desc))
|
|
};
|
|
}
|
|
|
|
macro_rules! assert_flags {
|
|
($move:expr, $quiet:expr, $double_push:expr, $en_passant:expr, $capture:expr, $castle:expr, $promotion:expr) => {
|
|
assert_flag!($move, $move.is_quiet(), $quiet, "is_quiet");
|
|
assert_flag!(
|
|
$move,
|
|
$move.is_double_push(),
|
|
$double_push,
|
|
"is_double_push"
|
|
);
|
|
assert_flag!($move, $move.is_en_passant(), $en_passant, "is_en_passant");
|
|
assert_flag!($move, $move.is_capture(), $capture, "is_capture");
|
|
assert_flag!($move, $move.is_castle(), $castle, "is_castle");
|
|
assert_flag!($move, $move.is_promotion(), $promotion, "is_promotion");
|
|
};
|
|
}
|
|
|
|
#[test]
|
|
fn move_flags_quiet() -> TestResult {
|
|
let mv = Builder::push(&piece!(White Pawn on A4))
|
|
.to(Square::A5)
|
|
.build()?;
|
|
assert_flags!(mv, true, false, false, false, false, false);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn move_flags_double_push() -> TestResult {
|
|
let mv = Builder::double_push(File::C, Color::White).build()?;
|
|
assert_flags!(mv, false, true, false, false, false, false);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn move_flags_capture() -> TestResult {
|
|
let mv = Builder::new()
|
|
.from(Square::A4)
|
|
.capturing_on(Square::B5)
|
|
.build()?;
|
|
|
|
assert_flags!(mv, false, false, false, true, false, false);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn move_flags_en_passant_capture() -> TestResult {
|
|
let ply = Builder::new()
|
|
.from(Square::A4)
|
|
.capturing_en_passant_on(Square::B3)
|
|
.build()?;
|
|
|
|
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 ply = Builder::push(&piece!(White Pawn on H7))
|
|
.to(Square::H8)
|
|
.promoting_to(PromotionShape::Queen)
|
|
.build()?;
|
|
|
|
assert!(ply.is_promotion());
|
|
assert_eq!(ply.promotion_shape(), Some(Shape::Queen));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn move_flags_capture_promotion() -> TestResult {
|
|
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!(ply.is_capture());
|
|
assert!(ply.is_promotion());
|
|
assert_eq!(ply.promotion_shape(), Some(Shape::Queen));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn move_flags_castle() -> TestResult {
|
|
let mv = Builder::castling(Color::White, Wing::KingSide).build()?;
|
|
|
|
assert_flags!(mv, false, false, false, false, true, false);
|
|
|
|
Ok(())
|
|
}
|