// Eryn Wells use super::Position; use crate::piece::{Color, Piece, PlacedPiece, Shape}; use crate::BitBoard; use crate::Square; pub struct Pieces<'a> { color: Color, position: &'a Position, current_shape: Option, shape_iterator: Box>, square_iterator: Option>>, } impl<'a> Pieces<'a> { pub(crate) fn new(position: &Position, color: Color) -> Pieces { Pieces { color, position, current_shape: None, shape_iterator: Box::new(Shape::iter()), square_iterator: None, } } } impl<'a> Iterator for Pieces<'a> { type Item = PlacedPiece; fn next(&mut self) -> Option { if let Some(square_iterator) = &mut self.square_iterator { if let (Some(square), Some(shape)) = (square_iterator.next(), self.current_shape) { return Some(PlacedPiece::new(Piece::new(self.color, shape), square)); } } let mut current_shape: Option = None; let mut next_nonempty_bitboard: Option = None; while let Some(shape) = self.shape_iterator.next() { let piece = Piece::new(self.color, *shape); let bitboard = self.position.bitboard_for_piece(piece); if bitboard.is_empty() { continue; } next_nonempty_bitboard = Some(bitboard); current_shape = Some(*shape); break; } if let (Some(bitboard), Some(shape)) = (next_nonempty_bitboard, current_shape) { let mut square_iterator = bitboard.occupied_squares(); let mut next_placed_piece: Option = None; if let Some(square) = square_iterator.next() { next_placed_piece = Some(PlacedPiece::new(Piece::new(self.color, shape), square)); } self.square_iterator = Some(Box::new(square_iterator)); self.current_shape = Some(shape); return next_placed_piece; } None } } #[cfg(test)] mod tests { use super::*; use crate::piece::{Color, Piece, Shape}; use crate::Position; use crate::Square; use std::collections::HashSet; fn place_piece_in_position(pos: &mut Position, piece: Piece, sq: Square) { pos.place_piece(piece, sq) .expect("Unable to place {piece:?} queen on {sq}"); } #[test] fn empty() { let pos = Position::empty(); let mut pieces = pos.pieces(Color::White); assert_eq!(pieces.next(), None); } #[test] fn one() { let sq = Square::E4; let mut pos = Position::empty(); place_piece_in_position(&mut pos, Piece::new(Color::White, Shape::Queen), Square::E4); println!("{:?}", &pos); let mut pieces = pos.pieces(Color::White); assert_eq!( pieces.next(), Some(PlacedPiece::new(Piece::new(Color::White, Shape::Queen), sq)) ); assert_eq!(pieces.next(), None); } #[test] fn multiple_pieces() { let mut pos = Position::empty(); place_piece_in_position(&mut pos, Piece::new(Color::White, Shape::Queen), Square::E4); place_piece_in_position(&mut pos, Piece::new(Color::White, Shape::King), Square::E1); place_piece_in_position(&mut pos, Piece::new(Color::White, Shape::Pawn), Square::B2); place_piece_in_position(&mut pos, Piece::new(Color::White, Shape::Pawn), Square::C2); println!("{:?}", &pos); let expected_placed_pieces = HashSet::from([ PlacedPiece::new(Piece::new(Color::White, Shape::Queen), Square::E4), PlacedPiece::new(Piece::new(Color::White, Shape::King), Square::E1), PlacedPiece::new(Piece::new(Color::White, Shape::Pawn), Square::B2), PlacedPiece::new(Piece::new(Color::White, Shape::Pawn), Square::C2), ]); let placed_pieces = HashSet::from_iter(pos.pieces(Color::White)); assert_eq!(placed_pieces, expected_placed_pieces); } }