Only one check-testing method, Board::is_in_check(), that tests if the current active player is in check. It doesn't make sense to test if the non-active player is in check.
166 lines
4.1 KiB
Rust
166 lines
4.1 KiB
Rust
// Eryn Wells <eryn@erynwells.me>
|
|
|
|
//! Move generator tests based on board positions described in [Peter Ellis
|
|
//! Jones][1]' excellent [blog post][2] on generated legal chess moves.
|
|
//!
|
|
//! [1]: https://peterellisjones.com
|
|
//! [2]: https://peterellisjones.com/posts/generating-legal-chess-moves-efficiently/
|
|
|
|
use chessfriend_core::Color;
|
|
use chessfriend_moves::{
|
|
Move, assert_move_list, assert_move_list_contains, assert_move_list_does_not_contain, ply,
|
|
};
|
|
use chessfriend_position::test_position;
|
|
use std::collections::HashSet;
|
|
|
|
#[test]
|
|
fn pseudo_legal_move_generation() {
|
|
let pos = test_position!(Black, [
|
|
Black King on E8,
|
|
White King on E1,
|
|
White Rook on F5,
|
|
]);
|
|
|
|
let king_moves: HashSet<_> = pos.all_legal_moves(Some(Color::Black)).collect();
|
|
|
|
assert_move_list_does_not_contain!(king_moves, [ply!(E8 - F8), ply!(E8 - F7)]);
|
|
}
|
|
|
|
#[test]
|
|
fn gotcha_king_moves_away_from_checking_slider() {
|
|
let position = test_position!(Black, [
|
|
Black King on E7,
|
|
White King on E1,
|
|
White Rook on E4,
|
|
]);
|
|
|
|
let king_moves: HashSet<Move> = position.all_legal_moves(None).map(Move::from).collect();
|
|
|
|
assert_move_list_does_not_contain!(king_moves, [ply!(E7 - E8)]);
|
|
}
|
|
|
|
#[test]
|
|
fn check_evasions_1() {
|
|
let pos = test_position!(Black, [
|
|
Black King on E8,
|
|
White King on E1,
|
|
White Knight on F6,
|
|
]);
|
|
|
|
let generated_moves = pos.all_legal_moves(Some(Color::Black));
|
|
|
|
assert_move_list!(
|
|
generated_moves,
|
|
[ply!(E8 - D8), ply!(E8 - E7), ply!(E8 - F7), ply!(E8 - F8),]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn check_evasions_double_check() {
|
|
let pos = test_position!(Black, [
|
|
Black King on E8,
|
|
Black Bishop on F6,
|
|
White King on E1,
|
|
White Knight on G7,
|
|
White Rook on E5,
|
|
]);
|
|
|
|
let generated_moves = pos.all_legal_moves(Some(Color::Black));
|
|
|
|
assert_move_list!(
|
|
generated_moves,
|
|
[ply!(E8 - D8), ply!(E8 - D7), ply!(E8 - F7), ply!(E8 - F8),]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn single_check_with_blocker() {
|
|
let pos = test_position!(Black, [
|
|
Black King on E8,
|
|
Black Knight on G6,
|
|
White King on E1,
|
|
White Rook on E5,
|
|
]);
|
|
|
|
let generated_moves = pos.all_legal_moves(Some(Color::Black));
|
|
|
|
assert_move_list!(
|
|
generated_moves,
|
|
[
|
|
// King moves
|
|
ply!(E8 - D8),
|
|
ply!(E8 - D7),
|
|
ply!(E8 - F7),
|
|
ply!(E8 - F8),
|
|
// Knight moves
|
|
ply!(G6 - E7),
|
|
ply!(G6 x E5),
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn en_passant_check_capture() {
|
|
let pos = test_position!(Black, [
|
|
Black King on C5,
|
|
Black Pawn on E4,
|
|
White Pawn on D4,
|
|
], D3);
|
|
|
|
assert!(pos.board().is_in_check());
|
|
|
|
let generated_moves: HashSet<_> = pos.all_legal_moves(Some(Color::Black)).collect();
|
|
|
|
assert_move_list_contains!(generated_moves, [ply!(E4 x D3 e.p.)]);
|
|
}
|
|
|
|
#[test]
|
|
fn en_passant_check_block() {
|
|
let pos = test_position!(Black, [
|
|
Black King on B5,
|
|
Black Pawn on E4,
|
|
White Pawn on D4,
|
|
White Queen on F1,
|
|
], D3);
|
|
|
|
assert!(pos.board().is_in_check());
|
|
|
|
let generated_moves: HashSet<_> = pos.all_legal_moves(Some(Color::Black)).collect();
|
|
|
|
assert_move_list_contains!(generated_moves, [ply!(E4 x D3 e.p.)]);
|
|
}
|
|
|
|
#[test]
|
|
fn pinned_pieces_rook_cannot_move_out_of_pin() {
|
|
let pos = test_position!(Black, [
|
|
Black King on E8,
|
|
Black Rook on E6,
|
|
White Queen on E3,
|
|
White King on C1,
|
|
]);
|
|
|
|
assert!(!pos.board().is_in_check());
|
|
|
|
let rook_moves: HashSet<_> = pos.all_legal_moves(None).collect();
|
|
|
|
assert_move_list_does_not_contain!(rook_moves, [ply!(E6 - D6), ply!(E6 - F6)]);
|
|
|
|
assert_move_list_contains!(
|
|
rook_moves,
|
|
[ply!(E6 x E3), ply!(E6 - E4), ply!(E6 - E5), ply!(E6 - E7)]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn en_passant_discovered_check() {
|
|
let pos = test_position!(Black, [
|
|
Black King on A4,
|
|
Black Pawn on E4,
|
|
White Pawn on D4,
|
|
White Queen on H4,
|
|
], D3);
|
|
|
|
let generated_moves: HashSet<_> = pos.all_legal_moves(Some(Color::Black)).collect();
|
|
|
|
assert_move_list_does_not_contain!(generated_moves, [ply!(E4 x D3 e.p.)]);
|
|
}
|