[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.
This commit is contained in:
Eryn Wells 2025-05-28 16:22:16 -07:00
parent 19c6c6701a
commit 2106e05d57
6 changed files with 85 additions and 3 deletions

View file

@ -1,5 +1,6 @@
// Eryn Wells <eryn@erynwells.me>
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;

View file

@ -0,0 +1,64 @@
// Eryn Wells <eryn@erynwells.me>
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<PawnMoveGenerator>,
knight_move_generator: Fuse<KnightMoveGenerator>,
bishop_move_generator: Fuse<BishopMoveGenerator>,
rook_move_generator: Fuse<RookMoveGenerator>,
queen_move_generator: Fuse<QueenMoveGenerator>,
king_move_generator: Fuse<KingMoveGenerator>,
}
impl AllPiecesMoveGenerator {
pub fn new(board: &Board, color: Option<Color>) -> 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<Self::Item> {
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<T>
// 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 {}

View file

@ -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::*;

View file

@ -1,11 +1,11 @@
// Eryn Wells <eryn@erynwells.me>
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::*;

View file

@ -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<Self> {
match self {

View file

@ -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,