[board] Write a bunch of tests to validate the flag methods on Move

I caught a bunch of bugs while implementing position::MoveBuilder in the flag
methods that Move exports. These tests caught many of them!
This commit is contained in:
Eryn Wells 2024-01-21 13:01:03 -08:00
parent f90ea2d1be
commit 72316ad5f5

View file

@ -169,11 +169,11 @@ impl Move {
}
pub fn is_quiet(&self) -> bool {
self.special() == 0b00
self.flags() == Kind::Quiet.discriminant()
}
pub fn is_double_push(&self) -> bool {
self.special() == 0b01
self.flags() == Kind::DoublePush.discriminant()
}
pub fn is_castle(&self) -> bool {
@ -181,7 +181,7 @@ impl Move {
}
pub fn castle(&self) -> Option<Castle> {
match self.special() {
match self.flags() {
0b0010 => Some(Castle::KingSide),
0b0011 => Some(Castle::QueenSide),
_ => None,
@ -193,7 +193,7 @@ impl Move {
}
pub fn is_en_passant(&self) -> bool {
(self.0 & 0b0101) == 0b0101
self.flags() == 0b0101
}
pub fn is_promotion(&self) -> bool {
@ -214,6 +214,11 @@ impl Move {
})
}
#[inline]
fn flags(&self) -> u16 {
self.0 & 0b1111
}
#[inline]
fn special(&self) -> u16 {
self.0 & 0b11
@ -240,8 +245,10 @@ impl MoveBuilder {
pub fn new(piece: Piece, from: Square, to: Square) -> Self {
let kind = match piece.shape() {
Shape::Pawn => {
let is_white_double_push = from.rank() == Rank::Two && to.rank() == Rank::Four;
let is_black_double_push = from.rank() == Rank::Seven && to.rank() == Rank::Five;
let from_rank = from.rank();
let to_rank = to.rank();
let is_white_double_push = from_rank == Rank::Two && to_rank == Rank::Four;
let is_black_double_push = from_rank == Rank::Seven && to_rank == Rank::Five;
if is_white_double_push || is_black_double_push {
Kind::DoublePush
} else {
@ -478,3 +485,82 @@ mod move_formatter {
test_algebraic_formatter!(long_bishop_capture, Long, White Bishop A2 x E6, Black Knight, "Ba2xe6");
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::piece;
macro_rules! assert_flag {
($move:expr, $left:expr, $right:expr) => {
assert_eq!($left, $right, "{:?}", $move)
};
}
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);
assert_flag!($move, $move.is_quiet(), $quiet);
assert_flag!($move, $move.is_double_push(), $double_push);
assert_flag!($move, $move.is_en_passant(), $en_passant);
assert_flag!($move, $move.is_capture(), $capture);
assert_flag!($move, $move.is_castle(), $castle);
assert_flag!($move, $move.is_promotion(), $promotion);
};
}
#[test]
fn move_flags_quiet() {
let mv = MoveBuilder::new(piece!(White Pawn), Square::A4, Square::A5).build();
assert_flags!(mv, true, false, false, false, false, false);
}
#[test]
fn move_flags_double_push() {
let mv = MoveBuilder::new(piece!(White Pawn), Square::C2, Square::C4).build();
assert_flags!(mv, false, true, false, false, false, false);
}
#[test]
fn move_flags_capture() {
let mv = MoveBuilder::new(piece!(White Pawn), Square::A4, Square::B5)
.capturing(piece!(Black Bishop on B5))
.build();
assert_flags!(mv, false, false, false, true, false, false);
}
#[test]
fn move_flags_en_passant_capture() {
let mv = MoveBuilder::new(piece!(White Pawn), Square::A5, Square::B6)
.capturing_en_passant(piece!(Black Pawn on B5))
.build();
assert_flags!(mv, false, false, true, true, false, false);
}
#[test]
fn move_flags_promotion() {
let mv = MoveBuilder::new(piece!(White Pawn), Square::H7, Square::H8)
.promoting_to(Shape::Queen)
.build();
assert_flags!(mv, false, false, false, false, false, true);
assert_eq!(mv.promotion(), Some(Shape::Queen));
}
#[test]
fn move_flags_capture_promotion() {
let mv = MoveBuilder::new(piece!(White Pawn), Square::H7, Square::G8)
.capturing(piece!(Black Knight on G8))
.promoting_to(Shape::Queen)
.build();
assert_flags!(mv, false, false, false, true, false, true);
assert_eq!(mv.promotion(), Some(Shape::Queen));
}
#[test]
fn move_flags_castle() {
let mv = MoveBuilder::new(piece!(Black King), Square::E8, Square::G8)
.castle(Castle::KingSide)
.build();
assert_flags!(mv, false, false, false, false, true, false);
}
}