From 2106e05d5739cdbb817cc27e6d60cdcffa9baad9 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Wed, 28 May 2025 16:22:16 -0700 Subject: [PATCH] [moves] Implement AllPiecesMoveGenerator A generator that yields moves for all pieces on the board. This generator combines the shape-specific move generators developed in prior commits into a single iterator that yields all moves. Implement FusedIterator for all generators so AllPiecesMoveGenerator can avoid doing a bunch of extra work once each iterator has yielded None. --- moves/src/generators.rs | 2 ++ moves/src/generators/all.rs | 64 ++++++++++++++++++++++++++++++++++ moves/src/generators/king.rs | 7 ++++ moves/src/generators/knight.rs | 6 ++-- moves/src/generators/pawn.rs | 4 ++- moves/src/generators/slider.rs | 5 +++ 6 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 moves/src/generators/all.rs diff --git a/moves/src/generators.rs b/moves/src/generators.rs index a3b6fcf..e2c0b4d 100644 --- a/moves/src/generators.rs +++ b/moves/src/generators.rs @@ -1,5 +1,6 @@ // Eryn Wells +mod all; mod king; mod knight; mod pawn; @@ -8,6 +9,7 @@ mod slider; #[cfg(test)] mod testing; +pub use all::AllPiecesMoveGenerator; pub use king::KingMoveGenerator; pub use knight::KnightMoveGenerator; pub use pawn::PawnMoveGenerator; diff --git a/moves/src/generators/all.rs b/moves/src/generators/all.rs new file mode 100644 index 0000000..d11ffd0 --- /dev/null +++ b/moves/src/generators/all.rs @@ -0,0 +1,64 @@ +// Eryn Wells + +use super::{ + BishopMoveGenerator, GeneratedMove, KingMoveGenerator, KnightMoveGenerator, PawnMoveGenerator, + QueenMoveGenerator, RookMoveGenerator, +}; +use chessfriend_board::Board; +use chessfriend_core::Color; +use std::iter::{Fuse, FusedIterator}; + +#[must_use] +pub struct AllPiecesMoveGenerator { + pawn_move_generator: Fuse, + knight_move_generator: Fuse, + bishop_move_generator: Fuse, + rook_move_generator: Fuse, + queen_move_generator: Fuse, + king_move_generator: Fuse, +} + +impl AllPiecesMoveGenerator { + pub fn new(board: &Board, color: Option) -> Self { + Self { + pawn_move_generator: PawnMoveGenerator::new(board, color).fuse(), + knight_move_generator: KnightMoveGenerator::new(board, color).fuse(), + bishop_move_generator: BishopMoveGenerator::new(board, color).fuse(), + rook_move_generator: RookMoveGenerator::new(board, color).fuse(), + queen_move_generator: QueenMoveGenerator::new(board, color).fuse(), + king_move_generator: KingMoveGenerator::new(board, color).fuse(), + } + } +} + +impl Iterator for AllPiecesMoveGenerator { + type Item = GeneratedMove; + + fn next(&mut self) -> Option { + macro_rules! return_next_move { + ($generator:expr) => {{ + let next_move = $generator.next(); + if next_move.is_some() { + return next_move; + } + }}; + } + + // All of these iterators are fused, meaning they are guaranteed to + // always return None once they've returned None the first time. Fuse + // can optimize this so that the work done in each of the move + // generators' next() methods doesn't have to be repeated every time + // next() is called. + + return_next_move!(self.pawn_move_generator); + return_next_move!(self.knight_move_generator); + return_next_move!(self.bishop_move_generator); + return_next_move!(self.rook_move_generator); + return_next_move!(self.queen_move_generator); + return_next_move!(self.king_move_generator); + + None + } +} + +impl FusedIterator for AllPiecesMoveGenerator {} diff --git a/moves/src/generators/king.rs b/moves/src/generators/king.rs index b091b3d..aa7eea0 100644 --- a/moves/src/generators/king.rs +++ b/moves/src/generators/king.rs @@ -4,6 +4,7 @@ use crate::{GeneratedMove, Move}; use chessfriend_bitboard::{bit_scanner::TrailingBitScanner, BitBoard}; use chessfriend_board::{Board, CastleParameters}; use chessfriend_core::{Color, Square, Wing}; +use std::iter::FusedIterator; #[must_use] pub struct KingMoveGenerator { @@ -84,6 +85,8 @@ impl Iterator for KingMoveGenerator { } } +impl FusedIterator for KingMoveGenerator {} + #[derive(Clone, Debug)] struct KingIterator { origin: Square, @@ -98,6 +101,8 @@ impl Iterator for KingIterator { } } +impl FusedIterator for KingIterator {} + #[derive(Clone, Debug)] struct CastleIterator { kingside: Option<&'static CastleParameters>, @@ -132,6 +137,8 @@ impl Iterator for CastleIterator { } } +impl FusedIterator for CastleIterator {} + #[cfg(test)] mod tests { use super::*; diff --git a/moves/src/generators/knight.rs b/moves/src/generators/knight.rs index 4b5a696..ab8d235 100644 --- a/moves/src/generators/knight.rs +++ b/moves/src/generators/knight.rs @@ -1,11 +1,11 @@ // Eryn Wells -use crate::Move; - use super::GeneratedMove; +use crate::Move; use chessfriend_bitboard::{bit_scanner::TrailingBitScanner, BitBoard}; use chessfriend_board::Board; use chessfriend_core::{Color, Square}; +use std::iter::FusedIterator; #[must_use] pub struct KnightMoveGenerator { @@ -66,6 +66,8 @@ impl Iterator for KnightMoveGenerator { } } +impl FusedIterator for KnightMoveGenerator {} + #[cfg(test)] mod tests { use super::*; diff --git a/moves/src/generators/pawn.rs b/moves/src/generators/pawn.rs index b7fd5ae..f4974de 100644 --- a/moves/src/generators/pawn.rs +++ b/moves/src/generators/pawn.rs @@ -7,7 +7,7 @@ use crate::{Move, PromotionShape}; use chessfriend_bitboard::{bit_scanner::TrailingBitScanner, BitBoard}; use chessfriend_board::Board; use chessfriend_core::{Color, Direction, Rank, Square}; -use std::slice; +use std::{iter::FusedIterator, slice}; pub struct PawnMoveGenerator { color: Color, @@ -224,6 +224,8 @@ impl std::iter::Iterator for PawnMoveGenerator { } } +impl FusedIterator for PawnMoveGenerator {} + impl MoveType { fn next(self) -> Option { match self { diff --git a/moves/src/generators/slider.rs b/moves/src/generators/slider.rs index b40890e..cd704d7 100644 --- a/moves/src/generators/slider.rs +++ b/moves/src/generators/slider.rs @@ -16,6 +16,7 @@ use crate::Move; use chessfriend_bitboard::{bit_scanner::TrailingBitScanner, BitBoard}; use chessfriend_board::Board; use chessfriend_core::{Color, Slider, Square}; +use std::iter::FusedIterator; macro_rules! slider_move_generator { ($vis:vis $name:ident, $slider:ident) => { @@ -35,6 +36,8 @@ macro_rules! slider_move_generator { self.0.next() } } + + impl FusedIterator for $name {} }; } @@ -117,6 +120,8 @@ impl Iterator for SliderMoveGenerator { } } +impl FusedIterator for SliderMoveGenerator {} + #[derive(Clone, Debug)] struct SliderInfo { origin: Square,