Replace uses of types in r#move with types from the moves package types

This commit is contained in:
Eryn Wells 2024-02-25 09:52:40 -08:00
parent aaad991899
commit d668091d0d
16 changed files with 273 additions and 280 deletions

View file

@ -58,13 +58,14 @@ impl MoveGeneratorInternal for KingMoveGenerator {
#[cfg(test)]
mod tests {
use super::*;
use crate::{assert_move_list, position, test_position, Move, MoveBuilder, PositionBuilder};
use crate::{assert_move_list, position, test_position, testing::*, PositionBuilder};
use chessfriend_bitboard::bitboard;
use chessfriend_core::{piece, Color, Square};
use chessfriend_moves::{Builder as MoveBuilder, Castle, Move};
use std::collections::HashSet;
#[test]
fn one_king() {
fn one_king() -> TestResult {
let pos = position![White King on E4];
let generator = KingMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
@ -74,24 +75,27 @@ mod tests {
bitboard![E5, F5, F4, F3, E3, D3, D4, D5]
);
let builder = MoveBuilder::push(&piece!(White King on E4));
let expected_moves: HashSet<Move> = HashSet::from_iter([
MoveBuilder::new(piece!(White King), Square::E4, Square::D5).build(),
MoveBuilder::new(piece!(White King), Square::E4, Square::E5).build(),
MoveBuilder::new(piece!(White King), Square::E4, Square::F5).build(),
MoveBuilder::new(piece!(White King), Square::E4, Square::F4).build(),
MoveBuilder::new(piece!(White King), Square::E4, Square::F3).build(),
MoveBuilder::new(piece!(White King), Square::E4, Square::E3).build(),
MoveBuilder::new(piece!(White King), Square::E4, Square::D3).build(),
MoveBuilder::new(piece!(White King), Square::E4, Square::D4).build(),
builder.clone().to(Square::D5).build()?,
builder.clone().to(Square::E5).build()?,
builder.clone().to(Square::F5).build()?,
builder.clone().to(Square::F4).build()?,
builder.clone().to(Square::F3).build()?,
builder.clone().to(Square::E3).build()?,
builder.clone().to(Square::D3).build()?,
builder.clone().to(Square::D4).build()?,
]);
let generated_moves: HashSet<Move> = generator.iter().collect();
assert_move_list!(generated_moves, expected_moves, pos);
Ok(())
}
#[test]
fn one_king_corner() {
fn one_king_corner() -> TestResult {
let pos = position![White King on A1];
let generator = KingMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
@ -104,13 +108,14 @@ mod tests {
"Generated:\n{generated_bitboard}\nExpected:\n{expected_bitboard}"
);
let builder = MoveBuilder::push(&piece!(White King on A1));
let expected_moves = [
MoveBuilder::new(piece!(White King), Square::A1, Square::A2).build(),
MoveBuilder::new(piece!(White King), Square::A1, Square::B1).build(),
MoveBuilder::new(piece!(White King), Square::A1, Square::B2).build(),
builder.clone().to(Square::A2).build()?,
builder.clone().to(Square::B1).build()?,
builder.clone().to(Square::B2).build()?,
];
let mut generated_moves: HashSet<Move> = generator.iter().collect();
let mut generated_moves: HashSet<_> = generator.iter().collect();
for ex_move in expected_moves {
assert!(
@ -125,6 +130,8 @@ mod tests {
"Moves unexpectedly present: {:#?}",
generated_moves
);
Ok(())
}
#[test]
@ -161,16 +168,8 @@ mod tests {
let generated_moves: HashSet<Move> = generator.iter().collect();
let king = piece!(White King);
assert!(generated_moves.contains(
&MoveBuilder::new(king, Square::E1, Square::G1)
.castle(Castle::KingSide)
.build()
));
assert!(generated_moves.contains(
&MoveBuilder::new(king, Square::E1, Square::C1)
.castle(Castle::QueenSide)
.build()
));
assert!(generated_moves.contains(&MoveBuilder::castling(Castle::KingSide).build()));
assert!(generated_moves.contains(&MoveBuilder::castling(Castle::QueenSide).build()));
}
#[test]
@ -189,16 +188,8 @@ mod tests {
let generated_moves: HashSet<Move> = generator.iter().collect();
let king = piece!(White King);
assert!(generated_moves.contains(
&MoveBuilder::new(king, Square::E1, Square::G1)
.castle(Castle::KingSide)
.build()
));
assert!(!generated_moves.contains(
&MoveBuilder::new(king, Square::E1, Square::C1)
.castle(Castle::QueenSide)
.build()
));
assert!(generated_moves.contains(&MoveBuilder::castling(Castle::KingSide).build()));
assert!(!generated_moves.contains(&MoveBuilder::castling(Castle::QueenSide).build()));
}
#[test]
@ -217,15 +208,7 @@ mod tests {
let generated_moves: HashSet<Move> = generator.iter().collect();
let king = piece!(White King);
assert!(!generated_moves.contains(
&MoveBuilder::new(king, Square::E1, Square::G1)
.castle(Castle::KingSide)
.build()
));
assert!(generated_moves.contains(
&MoveBuilder::new(king, Square::E1, Square::C1)
.castle(Castle::QueenSide)
.build()
));
assert!(!generated_moves.contains(&MoveBuilder::castling(Castle::KingSide).build()));
assert!(generated_moves.contains(&MoveBuilder::castling(Castle::QueenSide).build()));
}
}

View file

@ -34,54 +34,35 @@ impl MoveGeneratorInternal for KnightMoveGenerator {
#[cfg(test)]
mod tests {
use super::*;
use crate::{position, Move, MoveBuilder};
use crate::{assert_move_list, position, testing::*};
use chessfriend_core::{piece, Color, Square};
use chessfriend_moves::Builder as MoveBuilder;
use std::collections::HashSet;
#[test]
fn one_knight() {
fn one_knight() -> TestResult {
let pos = position![
White Knight on E4,
];
let generator =
KnightMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
let generated_moves: HashSet<_> = generator.iter().collect();
/*
let bb = generator.bitboard();
assert_eq!(
bb,
BitBoard::new(
0b00000000_00000000_00000000_00111000_00101000_00111000_00000000_00000000
)
);
*/
let piece = piece!(White Knight on E4);
let expected_moves = HashSet::from_iter([
MoveBuilder::push(&piece).to(Square::C3).build()?,
MoveBuilder::push(&piece).to(Square::D2).build()?,
MoveBuilder::push(&piece).to(Square::F2).build()?,
MoveBuilder::push(&piece).to(Square::G3).build()?,
MoveBuilder::push(&piece).to(Square::C5).build()?,
MoveBuilder::push(&piece).to(Square::D6).build()?,
MoveBuilder::push(&piece).to(Square::G5).build()?,
MoveBuilder::push(&piece).to(Square::F6).build()?,
]);
let expected_moves = [
MoveBuilder::new(piece!(White Knight), Square::E4, Square::C3).build(),
MoveBuilder::new(piece!(White Knight), Square::E4, Square::D2).build(),
MoveBuilder::new(piece!(White Knight), Square::E4, Square::F2).build(),
MoveBuilder::new(piece!(White Knight), Square::E4, Square::G3).build(),
MoveBuilder::new(piece!(White Knight), Square::E4, Square::C5).build(),
MoveBuilder::new(piece!(White Knight), Square::E4, Square::D6).build(),
MoveBuilder::new(piece!(White Knight), Square::E4, Square::G5).build(),
MoveBuilder::new(piece!(White Knight), Square::E4, Square::F6).build(),
];
assert_move_list!(generated_moves, expected_moves, pos);
let mut generated_moves: HashSet<Move> = generator.iter().collect();
for ex_move in expected_moves {
assert!(
generated_moves.remove(&ex_move),
"{:#?} was not generated",
&ex_move
);
}
assert!(
generated_moves.is_empty(),
"Moves unexpectedly present: {:#?}",
generated_moves
);
Ok(())
}
}

View file

@ -1,7 +1,7 @@
// Eryn Wells <eryn@erynwells.me>
use chessfriend_bitboard::BitBoard;
use chessfriend_core::{Color, Piece, PlacedPiece, Shape, Square};
use chessfriend_core::{PlacedPiece, Square};
use chessfriend_moves::{Builder as MoveBuilder, Castle, Move};
/// A set of bitboards defining the moves for a single piece on the board.
@ -65,57 +65,34 @@ impl MoveSet {
}
pub(crate) fn moves(&self) -> impl Iterator<Item = Move> + '_ {
let piece = self.piece.piece();
let from_square = self.piece.square();
let piece = &self.piece;
self.bitboards
.quiet
.occupied_squares()
.map(move |to_square| MoveBuilder::new(*piece, from_square, to_square).build())
.filter_map(|to_square| MoveBuilder::push(&self.piece).to(to_square).build().ok())
.chain(
self.bitboards
.captures
.occupied_squares()
.map(move |to_square| {
MoveBuilder::new(*piece, from_square, to_square)
.capturing(PlacedPiece::new(
Piece::new(Color::White, Shape::Pawn),
to_square,
))
.build()
}),
.filter_map(|to_square| MoveBuilder::push(piece).to(to_square).build().ok()),
)
.chain(
if (self.special & 0b1) != 0 {
Some(())
let mv = MoveBuilder::castling(Castle::KingSide).build();
Some(mv)
} else {
None
}
.map(|()| {
MoveBuilder::new(
*piece,
from_square,
Castle::KingSide.target_squares(piece.color()).king,
)
.castle(Castle::KingSide)
.build()
}),
.into_iter(),
)
.chain(
if (self.special & 0b10) != 0 {
Some(())
Some(MoveBuilder::castling(Castle::QueenSide).build())
} else {
None
}
.map(|()| {
MoveBuilder::new(
*piece,
from_square,
Castle::QueenSide.target_squares(piece.color()).king,
)
.castle(Castle::QueenSide)
.build()
}),
.into_iter(),
)
}
}

View file

@ -1,9 +1,10 @@
// Eryn Wells <eryn@erynwells.me>
use super::{move_generator_declaration, MoveGeneratorInternal, MoveSet};
use crate::{r#move::Move, MoveBuilder, Position};
use crate::Position;
use chessfriend_bitboard::BitBoard;
use chessfriend_core::{Color, PlacedPiece, Rank, Shape, Square};
use chessfriend_moves::{Builder as MoveBuilder, Move};
use std::collections::BTreeMap;
#[derive(Debug)]
@ -65,7 +66,7 @@ impl PawnMoveGenerator {
push_mask: BitBoard,
) -> BTreeMap<Square, MoveSet> {
let piece = Self::piece(color);
let mut moves_for_pieces =
let moves_for_pieces =
BTreeMap::from_iter(position.bitboard_for_piece(piece).occupied_squares().map(
|square| {
let piece = PlacedPiece::new(piece, square);
@ -75,10 +76,6 @@ impl PawnMoveGenerator {
},
));
if position.has_en_passant_square() {
}
moves_for_pieces
}
@ -121,23 +118,21 @@ impl PawnMoveGenerator {
fn en_passant_attack(position: &Position, piece: &PlacedPiece) -> Option<Move> {
match position.en_passant() {
Some(en_passant) => {
let en_passant_bitboard: BitBoard = en_passant.target_square().into();
let target_square = en_passant.target_square();
let en_passant_bitboard: BitBoard = target_square.into();
let capture =
BitBoard::pawn_attacks(piece.square(), piece.color()) & en_passant_bitboard;
if capture.is_empty() {
return None;
}
match position.piece_on_square(en_passant.capture_square()) {
Some(captured_piece) => Some(
MoveBuilder::new(
*piece.piece(),
piece.square(),
en_passant.target_square(),
)
.capturing_en_passant(captured_piece)
.build(),
Some(_) => Some(
MoveBuilder::push(piece)
.capturing_en_passant_on(target_square)
.build()
.ok()?,
),
None => None,
}
@ -150,46 +145,48 @@ impl PawnMoveGenerator {
#[cfg(test)]
mod tests {
use super::*;
use crate::{assert_move_list, position::DiagramFormatter, test_position, Move, MoveBuilder};
use chessfriend_core::{piece, Color, Piece, Square};
use crate::{assert_move_list, position::DiagramFormatter, test_position, testing::*};
use chessfriend_core::{piece, Color, Square};
use chessfriend_moves::{Builder as MoveBuilder, Move};
use std::collections::HashSet;
#[test]
fn one_2square_push() {
fn one_double_push() -> TestResult {
let pos = test_position![White Pawn on E2];
let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
let pawn = piece!(White Pawn on E2);
let expected_moves = HashSet::from_iter([
MoveBuilder::new(piece!(White Pawn), Square::E2, Square::E3).build(),
MoveBuilder::new(piece!(White Pawn), Square::E2, Square::E4).build(),
MoveBuilder::push(&pawn).to(Square::E3).build()?,
MoveBuilder::double_push(pawn.square().file(), pawn.color()).build()?,
]);
let generated_moves: HashSet<Move> = generator.iter().collect();
let generated_moves: HashSet<_> = generator.iter().collect();
assert_eq!(generated_moves, expected_moves);
Ok(())
}
#[test]
fn one_1square_push() {
fn one_single_push() -> TestResult {
let pos = test_position![White Pawn on E3];
let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
let generated_moves: HashSet<_> = generator.iter().collect();
let expected_moves = HashSet::from_iter([MoveBuilder::new(
Piece::pawn(Color::White),
Square::E3,
Square::E4,
)
.build()]);
let generated_moves: HashSet<Move> = generator.iter().collect();
let expected_moves = HashSet::from_iter([MoveBuilder::push(&piece!(White Pawn on E3))
.to(Square::E4)
.build()?]);
assert_move_list!(generated_moves, expected_moves, pos);
Ok(())
}
#[test]
fn one_obstructed_2square_push() {
fn one_obstructed_2square_push() -> TestResult {
let pos = test_position![
White Pawn on E2,
White Knight on E4,
@ -199,16 +196,15 @@ mod tests {
let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
let expected_moves = HashSet::from_iter([MoveBuilder::new(
Piece::pawn(Color::White),
Square::E2,
Square::E3,
)
.build()]);
let expected_moves = HashSet::from_iter([MoveBuilder::push(&piece!(White Pawn on E2))
.to(Square::E3)
.build()?]);
let generated_moves: HashSet<Move> = generator.iter().collect();
let generated_moves: HashSet<_> = generator.iter().collect();
assert_move_list!(generated_moves, expected_moves, pos);
Ok(())
}
#[test]
@ -220,14 +216,14 @@ mod tests {
let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
let generated_moves: HashSet<Move> = generator.iter().collect();
let expected_moves: HashSet<Move> = HashSet::new();
let generated_moves: HashSet<_> = generator.iter().collect();
let expected_moves: HashSet<_> = HashSet::new();
assert_move_list!(generated_moves, expected_moves, pos);
}
#[test]
fn one_attack() {
fn one_attack() -> TestResult {
let pos = test_position![
White Pawn on E4,
White Bishop on E5,
@ -236,20 +232,19 @@ mod tests {
let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
let expected_moves =
HashSet::from_iter(
[MoveBuilder::new(piece!(White Pawn), Square::E4, Square::D5)
.capturing(piece!(Black Knight on D5))
.build()],
);
let expected_moves = HashSet::from_iter([MoveBuilder::push(&piece!(White Pawn on E4))
.capturing_on(Square::D5)
.build()?]);
let generated_moves: HashSet<Move> = generator.iter().collect();
let generated_moves: HashSet<_> = generator.iter().collect();
assert_eq!(generated_moves, expected_moves);
assert_move_list!(generated_moves, expected_moves, pos);
Ok(())
}
#[test]
fn one_double_attack() {
fn one_double_attack() -> TestResult {
let pos = test_position![
White Pawn on E4,
White Bishop on E5,
@ -259,21 +254,44 @@ mod tests {
let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
let builder = MoveBuilder::push(&piece!(White Pawn on E4));
let expected_moves = HashSet::from_iter([
MoveBuilder::new(piece!(White Pawn), Square::E4, Square::D5)
.capturing(piece!(Black Knight on D5))
.build(),
MoveBuilder::new(piece!(White Pawn), Square::E4, Square::F5)
.capturing(piece!(Black Queen on F5))
.build(),
builder.clone().capturing_on(Square::D5).build()?,
builder.clone().capturing_on(Square::F5).build()?,
]);
let generated_moves: HashSet<Move> = generator.iter().collect();
let generated_moves: HashSet<_> = generator.iter().collect();
assert_eq!(
generated_moves, expected_moves,
"generated: {:#?}\nexpected: {:#?}",
generated_moves, expected_moves
);
Ok(())
}
#[test]
fn one_en_passant_attack() -> TestResult {
let pos = test_position!(Black, [
White Pawn on D4,
Black Pawn on E4,
], D3);
let generator = PawnMoveGenerator::new(&pos, Color::White, BitBoard::FULL, BitBoard::FULL);
let generated_moves: HashSet<Move> = generator.iter().collect();
let builder = MoveBuilder::push(&piece!(Black Pawn on E4));
let expected_moves = HashSet::from_iter([
builder
.clone()
.capturing_en_passant_on(Square::D3)
.build()?,
builder.clone().to(Square::E3).build()?,
]);
assert_move_list!(generated_moves, expected_moves, pos);
Ok(())
}
}

View file

@ -6,15 +6,13 @@
//! [1]: https://peterellisjones.com
//! [2]: https://peterellisjones.com/posts/generating-legal-chess-moves-efficiently/
use crate::{
assert_move_list, formatted_move_list, move_generator::Moves, r#move::AlgebraicMoveFormatter,
test_position, Move, MoveBuilder,
};
use crate::{assert_move_list, formatted_move_list, test_position, testing::*};
use chessfriend_core::{piece, Square};
use chessfriend_moves::Builder as MoveBuilder;
use std::collections::HashSet;
#[test]
fn pseudo_legal_move_generation() -> Result<(), String> {
fn pseudo_legal_move_generation() -> TestResult {
let pos = test_position!(Black, [
Black King on E8,
White King on E1,
@ -24,7 +22,7 @@ fn pseudo_legal_move_generation() -> Result<(), String> {
let generated_moves = pos.moves();
let king_moves = generated_moves
.moves_for_piece(&piece!(Black King on E8))
.ok_or("No valid king moves")?;
.ok_or(TestError::NoLegalMoves)?;
assert!(!king_moves.can_move_to_square(Square::F8));
assert!(!king_moves.can_move_to_square(Square::F7));
@ -33,7 +31,7 @@ fn pseudo_legal_move_generation() -> Result<(), String> {
}
#[test]
fn gotcha_king_moves_away_from_a_checking_slider() -> Result<(), String> {
fn gotcha_king_moves_away_from_a_checking_slider() -> TestResult {
let pos = test_position!(Black, [
Black King on E7,
White King on E1,
@ -43,7 +41,7 @@ fn gotcha_king_moves_away_from_a_checking_slider() -> Result<(), String> {
let generated_moves = pos.moves();
let king_moves = generated_moves
.moves_for_piece(&piece!(Black King on E7))
.ok_or("No valid king moves")?;
.ok_or(TestError::NoLegalMoves)?;
assert!(!king_moves.can_move_to_square(Square::E8));
@ -51,7 +49,7 @@ fn gotcha_king_moves_away_from_a_checking_slider() -> Result<(), String> {
}
#[test]
fn check_evasions_1() {
fn check_evasions_1() -> TestResult {
let pos = test_position!(Black, [
Black King on E8,
White King on E1,
@ -60,11 +58,12 @@ fn check_evasions_1() {
let generated_moves = pos.moves();
let builder = MoveBuilder::push(&piece!(Black King on E8));
let expected_moves = HashSet::from_iter([
MoveBuilder::new(piece!(Black King), Square::E8, Square::D8).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::E7).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::F7).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::F8).build(),
builder.clone().to(Square::D8).build()?,
builder.clone().to(Square::E7).build()?,
builder.clone().to(Square::F7).build()?,
builder.clone().to(Square::F8).build()?,
]);
assert_move_list!(
@ -72,10 +71,12 @@ fn check_evasions_1() {
expected_moves,
pos
);
Ok(())
}
#[test]
fn check_evasions_double_check() {
fn check_evasions_double_check() -> TestResult {
let pos = test_position!(Black, [
Black King on E8,
Black Bishop on F6,
@ -86,11 +87,12 @@ fn check_evasions_double_check() {
let generated_moves = pos.moves();
let builder = MoveBuilder::push(&piece!(Black King on E8));
let expected_moves = HashSet::from_iter([
MoveBuilder::new(piece!(Black King), Square::E8, Square::D8).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::D7).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::F7).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::F8).build(),
builder.clone().to(Square::D8).build()?,
builder.clone().to(Square::D7).build()?,
builder.clone().to(Square::F7).build()?,
builder.clone().to(Square::F8).build()?,
]);
assert_move_list!(
@ -98,10 +100,12 @@ fn check_evasions_double_check() {
expected_moves,
pos
);
Ok(())
}
#[test]
fn single_check_with_blocker() {
fn single_check_with_blocker() -> TestResult {
let pos = test_position!(Black, [
Black King on E8,
Black Knight on G6,
@ -111,15 +115,15 @@ fn single_check_with_blocker() {
let generated_moves = pos.moves();
let king_builder = MoveBuilder::push(&piece!(Black King on E8));
let knight_builder = MoveBuilder::push(&piece!(Black Knight on G6));
let expected_moves = HashSet::from_iter([
MoveBuilder::new(piece!(Black King), Square::E8, Square::D8).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::D7).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::F7).build(),
MoveBuilder::new(piece!(Black King), Square::E8, Square::F8).build(),
MoveBuilder::new(piece!(Black Knight), Square::G6, Square::E7).build(),
MoveBuilder::new(piece!(Black Knight), Square::G6, Square::E5)
.capturing(piece!(White Rook on E5))
.build(),
king_builder.clone().to(Square::D8).build()?,
king_builder.clone().to(Square::D7).build()?,
king_builder.clone().to(Square::F7).build()?,
king_builder.clone().to(Square::F8).build()?,
knight_builder.clone().to(Square::E7).build()?,
knight_builder.clone().capturing_on(Square::E5).build()?,
]);
assert_move_list!(
@ -127,10 +131,12 @@ fn single_check_with_blocker() {
expected_moves,
pos
);
Ok(())
}
#[test]
fn en_passant_check_capture() {
fn en_passant_check_capture() -> TestResult {
let pos = test_position!(Black, [
Black King on C5,
Black Pawn on E4,
@ -143,17 +149,19 @@ fn en_passant_check_capture() {
assert!(
generated_moves.contains(
&MoveBuilder::new(piece!(Black Pawn), Square::E4, Square::D3)
.capturing_en_passant(piece!(White Pawn on D4))
.build()
&MoveBuilder::push(&piece!(Black Pawn on E4))
.capturing_en_passant_on(Square::D4)
.build()?
),
"Valid moves: {:?}",
formatted_move_list!(generated_moves, pos)
);
Ok(())
}
#[test]
fn en_passant_check_block() {
fn en_passant_check_block() -> TestResult {
let pos = test_position!(Black, [
Black King on B5,
Black Pawn on E4,
@ -167,13 +175,15 @@ fn en_passant_check_block() {
assert!(
generated_moves.contains(
&MoveBuilder::new(piece!(Black Pawn), Square::E4, Square::D3)
.capturing_en_passant(piece!(White Pawn on D4))
.build()
&MoveBuilder::push(&piece!(Black Pawn on E4))
.capturing_en_passant_on(Square::D4)
.build()?
),
"Valid moves: {:?}",
formatted_move_list!(generated_moves, pos)
);
Ok(())
}
#[test]
@ -204,7 +214,7 @@ fn pinned_pieces_rook_cannot_move_out_of_pin() -> Result<(), String> {
}
#[test]
fn en_passant_discovered_check() {
fn en_passant_discovered_check() -> TestResult {
let pos = test_position!(Black, [
Black King on A4,
Black Pawn on E4,
@ -214,13 +224,15 @@ fn en_passant_discovered_check() {
let generated_moves = pos.moves().iter().collect::<HashSet<_>>();
let unexpected_move = MoveBuilder::new(piece!(Black Pawn), Square::E4, Square::D3)
.capturing_en_passant(piece!(White Pawn on D4))
.build();
let unexpected_move = MoveBuilder::push(&piece!(Black Pawn on E4))
.capturing_en_passant_on(Square::D4)
.build()?;
assert!(
!generated_moves.contains(&unexpected_move),
"Valid moves: {:?}",
formatted_move_list!(generated_moves, pos)
);
Ok(())
}

View file

@ -1,36 +1,32 @@
// Eryn Wells <eryn@erynwells.me>
use crate::{position, r#move::AlgebraicMoveFormatter, Move, MoveBuilder};
use crate::{assert_move_list, test_position, testing::*};
use chessfriend_core::{piece, Square};
use chessfriend_moves::Builder as MoveBuilder;
use std::collections::HashSet;
#[test]
fn one_king() {
let pos = position![
fn one_king() -> TestResult {
let pos = test_position![
White King on D3,
Black King on H6,
];
let builder = MoveBuilder::push(&piece!(White King on D3));
let expected_moves = HashSet::from_iter([
MoveBuilder::new(piece!(White King), Square::D3, Square::D4).build(),
MoveBuilder::new(piece!(White King), Square::D3, Square::E4).build(),
MoveBuilder::new(piece!(White King), Square::D3, Square::E3).build(),
MoveBuilder::new(piece!(White King), Square::D3, Square::E2).build(),
MoveBuilder::new(piece!(White King), Square::D3, Square::D2).build(),
MoveBuilder::new(piece!(White King), Square::D3, Square::C2).build(),
MoveBuilder::new(piece!(White King), Square::D3, Square::C3).build(),
MoveBuilder::new(piece!(White King), Square::D3, Square::C4).build(),
builder.clone().to(Square::D4).build()?,
builder.clone().to(Square::E4).build()?,
builder.clone().to(Square::E3).build()?,
builder.clone().to(Square::E2).build()?,
builder.clone().to(Square::D2).build()?,
builder.clone().to(Square::C2).build()?,
builder.clone().to(Square::C3).build()?,
builder.clone().to(Square::C4).build()?,
]);
let generated_moves: HashSet<Move> = pos.moves().iter().collect();
let generated_moves: HashSet<_> = pos.moves().iter().collect();
assert_eq!(
generated_moves,
expected_moves,
"{:?}",
generated_moves
.symmetric_difference(&expected_moves)
.map(|m| format!("{}", AlgebraicMoveFormatter::new(&m, &pos)))
.collect::<Vec<String>>()
);
assert_move_list!(generated_moves, expected_moves, pos);
Ok(())
}