[board, moves, position] Make the Peter Ellis Jones gotcha unit tests work
Move this file over to position/tests. That makes it an integration test, technically. Update it to comply with the current API conventions. This is a pretty radical change from when I first wrote these! In the process of running these tests, I found a bug in my PawnMoveGenerator where it was generating the origin squares for en passant captures incorrectly. Fix those bugs and write two new tests to exercise those code paths. One of the test_board! variants was setting .active_color instead of using the setter. This is a build failure. Fix it. Move the assert_move_list! macro to the moves crate. This is a more natural home for it. Additionally, add assert_move_list_contains! and assert_move_list_does_not_contain! to generate assertions that a collection of moves (anything that implements .contains()) has or doesn't have a set of moves. Also remove formatted_move_list!, which is no longer used. All that done, make the tests pass!
This commit is contained in:
parent
d7f426697d
commit
651c982ead
11 changed files with 316 additions and 315 deletions
|
@ -6,9 +6,6 @@ mod knight;
|
|||
mod pawn;
|
||||
mod slider;
|
||||
|
||||
#[cfg(test)]
|
||||
mod testing;
|
||||
|
||||
pub use all::AllPiecesMoveGenerator;
|
||||
pub use king::KingMoveGenerator;
|
||||
pub use knight::KnightMoveGenerator;
|
||||
|
@ -28,6 +25,11 @@ impl GeneratedMove {
|
|||
pub fn origin(&self) -> Square {
|
||||
self.ply.origin_square()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn target(&self) -> Square {
|
||||
self.ply.target_square()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for GeneratedMove {
|
||||
|
|
|
@ -120,16 +120,16 @@ impl PawnMoveGenerator {
|
|||
MoveType::EnPassant => match self.color {
|
||||
Color::White => {
|
||||
if (self.en_passant & self.left_captures).is_populated() {
|
||||
target.neighbor(Direction::NorthWest, None)
|
||||
target.neighbor(Direction::SouthEast, None)
|
||||
} else {
|
||||
target.neighbor(Direction::NorthEast, None)
|
||||
target.neighbor(Direction::SouthWest, None)
|
||||
}
|
||||
}
|
||||
Color::Black => {
|
||||
if (self.en_passant & self.left_captures).is_populated() {
|
||||
target.neighbor(Direction::SouthEast, None)
|
||||
target.neighbor(Direction::NorthWest, None)
|
||||
} else {
|
||||
target.neighbor(Direction::SouthWest, None)
|
||||
target.neighbor(Direction::NorthEast, None)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -241,7 +241,7 @@ impl MoveType {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::Move;
|
||||
use crate::{assert_move_list, ply, Move};
|
||||
use chessfriend_board::test_board;
|
||||
use chessfriend_core::{Color, Square};
|
||||
use std::collections::HashSet;
|
||||
|
@ -485,4 +485,28 @@ mod tests {
|
|||
.into()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn black_e4_captures_d4_en_passant() {
|
||||
let board = test_board!(Black, [
|
||||
White Pawn on D4,
|
||||
Black Pawn on E4
|
||||
], D3);
|
||||
|
||||
let generated_moves = PawnMoveGenerator::new(&board, None);
|
||||
|
||||
assert_move_list!(generated_moves, [ply!(E4 - E3), ply!(E4 x D3 e.p.),]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn white_e5_captures_f5_en_passant() {
|
||||
let board = test_board!(White, [
|
||||
White Pawn on E5,
|
||||
Black Pawn on F5
|
||||
], F6);
|
||||
|
||||
let generated_moves = PawnMoveGenerator::new(&board, None);
|
||||
|
||||
assert_move_list!(generated_moves, [ply!(E5 - E6), ply!(E5 x F6 e.p.),]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_move_list {
|
||||
($generator:expr, [ $($expected:expr),* $(,)? ]) => {
|
||||
{
|
||||
let generated_moves: std::collections::HashSet<$crate::GeneratedMove> = $generator.collect();
|
||||
let expected_moves: std::collections::HashSet<$crate::GeneratedMove> = [
|
||||
$($expected.into(),)*
|
||||
].into();
|
||||
|
||||
assert_eq!(
|
||||
generated_moves,
|
||||
expected_moves,
|
||||
"\n\tMatching: {:?}\n\tGenerated, not expected: {:?}\n\tExpected, not generated: {:?}",
|
||||
generated_moves
|
||||
.intersection(&expected_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
generated_moves
|
||||
.difference(&expected_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
expected_moves
|
||||
.difference(&generated_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -5,6 +5,7 @@ pub mod testing;
|
|||
|
||||
mod builder;
|
||||
mod defs;
|
||||
mod macros;
|
||||
mod make_move;
|
||||
mod moves;
|
||||
mod record;
|
||||
|
|
77
moves/src/macros.rs
Normal file
77
moves/src/macros.rs
Normal file
|
@ -0,0 +1,77 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_move_list {
|
||||
($generator:expr, [ $($expected:expr),* $(,)? ]) => {
|
||||
{
|
||||
let generated_moves: std::collections::HashSet<$crate::GeneratedMove> = $generator.collect();
|
||||
let expected_moves: std::collections::HashSet<$crate::GeneratedMove> = [
|
||||
$($expected.into(),)*
|
||||
].into();
|
||||
|
||||
assert_eq!(
|
||||
generated_moves,
|
||||
expected_moves,
|
||||
"\n\tMatching: {:?}\n\tGenerated, not expected: {:?}\n\tExpected, not generated: {:?}",
|
||||
generated_moves
|
||||
.intersection(&expected_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
generated_moves
|
||||
.difference(&expected_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
expected_moves
|
||||
.difference(&generated_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
);
|
||||
}
|
||||
};
|
||||
($generator:expr, $expected:expr) => {
|
||||
{
|
||||
use std::collections::HashSet;
|
||||
|
||||
let generated_moves: HashSet<$crate::GeneratedMove> = $generator.collect();
|
||||
let expected_moves: HashSet<$crate::GeneratedMove> = $expected.collect();
|
||||
|
||||
assert_eq!(
|
||||
generated_moves,
|
||||
expected_moves,
|
||||
"\n\tMatching: {:?}\n\tGenerated, not expected: {:?}\n\tExpected, not generated: {:?}",
|
||||
generated_moves
|
||||
.intersection(&expected_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
generated_moves
|
||||
.difference(&expected_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
expected_moves
|
||||
.difference(&generated_moves)
|
||||
.map(|mv| format!("{}", mv))
|
||||
.collect::<Vec<String>>(),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_move_list_contains {
|
||||
($generated_moves:expr, [ $($expected:expr),* $(,)? ]) => {
|
||||
$(
|
||||
assert!($generated_moves.contains(&$expected.into()));
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! assert_move_list_does_not_contain {
|
||||
($generated_moves:expr, [ $($expected:expr),* $(,)? ]) => {
|
||||
{
|
||||
$(
|
||||
assert!(!$generated_moves.contains(&$expected.into()));
|
||||
)*
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue