[moves] Knight move generator and tests
This commit is contained in:
parent
3f3842c7c8
commit
faca844733
3 changed files with 170 additions and 0 deletions
|
@ -1,10 +1,12 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
mod knight;
|
||||
mod pawn;
|
||||
|
||||
#[cfg(test)]
|
||||
mod testing;
|
||||
|
||||
pub use knight::KnightMoveGenerator;
|
||||
pub use pawn::PawnMoveGenerator;
|
||||
|
||||
use crate::Move;
|
||||
|
|
164
moves/src/generators/knight.rs
Normal file
164
moves/src/generators/knight.rs
Normal file
|
@ -0,0 +1,164 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use crate::Move;
|
||||
|
||||
use super::GeneratedMove;
|
||||
use chessfriend_bitboard::{bit_scanner::TrailingBitScanner, BitBoard};
|
||||
use chessfriend_board::Board;
|
||||
use chessfriend_core::{Color, Square};
|
||||
|
||||
#[must_use]
|
||||
pub struct KnightMoveGenerator {
|
||||
origin_iterator: TrailingBitScanner,
|
||||
target_iterator: Option<TrailingBitScanner>,
|
||||
current_origin: Option<Square>,
|
||||
friends: BitBoard,
|
||||
enemies: BitBoard,
|
||||
}
|
||||
|
||||
impl KnightMoveGenerator {
|
||||
pub fn new(board: &Board, color: Option<Color>) -> Self {
|
||||
let color = board.unwrap_color(color);
|
||||
|
||||
let knights = board.knights(color);
|
||||
let friends = board.friendly_occupancy(color);
|
||||
let enemies = board.enemies(color);
|
||||
|
||||
Self {
|
||||
origin_iterator: knights.occupied_squares_trailing(),
|
||||
target_iterator: None,
|
||||
current_origin: None,
|
||||
friends,
|
||||
enemies,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for KnightMoveGenerator {
|
||||
type Item = GeneratedMove;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.current_origin.is_none() {
|
||||
self.current_origin = self.origin_iterator.next();
|
||||
}
|
||||
|
||||
let origin = self.current_origin?;
|
||||
|
||||
let target_iterator = self.target_iterator.get_or_insert_with(|| {
|
||||
let knight_moves = BitBoard::knight_moves(origin);
|
||||
knight_moves.occupied_squares_trailing()
|
||||
});
|
||||
|
||||
if let Some(target) = target_iterator.next() {
|
||||
let target_bitboard: BitBoard = target.into();
|
||||
if (target_bitboard & self.friends).is_populated() {
|
||||
self.next()
|
||||
} else if (target_bitboard & self.enemies).is_populated() {
|
||||
Some(Move::capture(origin, target).into())
|
||||
} else {
|
||||
Some(Move::quiet(origin, target).into())
|
||||
}
|
||||
} else {
|
||||
self.current_origin = None;
|
||||
self.target_iterator = None;
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{assert_move_list, ply};
|
||||
use chessfriend_board::test_board;
|
||||
use chessfriend_core::Color;
|
||||
|
||||
#[test]
|
||||
fn white_f5_moves() {
|
||||
let board = test_board!(White Knight on F5);
|
||||
assert_move_list!(
|
||||
KnightMoveGenerator::new(&board, Some(Color::White)),
|
||||
[
|
||||
ply!(F5 - G7),
|
||||
ply!(F5 - H6),
|
||||
ply!(F5 - H4),
|
||||
ply!(F5 - G3),
|
||||
ply!(F5 - E3),
|
||||
ply!(F5 - D4),
|
||||
ply!(F5 - D6),
|
||||
ply!(F5 - E7),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn white_f5_and_c6_moves() {
|
||||
let board = test_board!(
|
||||
White Knight on C6,
|
||||
White Knight on F5,
|
||||
);
|
||||
assert_move_list!(
|
||||
KnightMoveGenerator::new(&board, Some(Color::White)),
|
||||
[
|
||||
ply!(C6 - D8),
|
||||
ply!(C6 - D8),
|
||||
ply!(C6 - E7),
|
||||
ply!(C6 - E5),
|
||||
ply!(C6 - D4),
|
||||
ply!(C6 - B4),
|
||||
ply!(C6 - A5),
|
||||
ply!(C6 - A7),
|
||||
ply!(C6 - B8),
|
||||
ply!(F5 - G7),
|
||||
ply!(F5 - H6),
|
||||
ply!(F5 - H4),
|
||||
ply!(F5 - G3),
|
||||
ply!(F5 - E3),
|
||||
ply!(F5 - D4),
|
||||
ply!(F5 - D6),
|
||||
ply!(F5 - E7),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn white_f5_moves_with_blockers() {
|
||||
let board = test_board!(
|
||||
White Knight on F5,
|
||||
White Queen on G3,
|
||||
White Bishop on D6,
|
||||
);
|
||||
assert_move_list!(
|
||||
KnightMoveGenerator::new(&board, Some(Color::White)),
|
||||
[
|
||||
ply!(F5 - G7),
|
||||
ply!(F5 - H6),
|
||||
ply!(F5 - H4),
|
||||
ply!(F5 - E3),
|
||||
ply!(F5 - D4),
|
||||
ply!(F5 - E7),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn white_f5_moves_with_captures() {
|
||||
let board = test_board!(
|
||||
White Knight on F5,
|
||||
White Queen on G3,
|
||||
White Bishop on D6,
|
||||
Black Queen on D4,
|
||||
);
|
||||
assert_move_list!(
|
||||
KnightMoveGenerator::new(&board, Some(Color::White)),
|
||||
[
|
||||
ply!(F5 - G7),
|
||||
ply!(F5 - H6),
|
||||
ply!(F5 - H4),
|
||||
ply!(F5 - E3),
|
||||
ply!(F5 - E7),
|
||||
ply!(F5 x D4),
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue