2023-12-26 09:19:38 -07:00
|
|
|
// Eryn Wells <eryn@erynwells.me>
|
|
|
|
|
2023-12-26 11:25:27 -07:00
|
|
|
use super::Position;
|
2023-12-26 09:19:38 -07:00
|
|
|
use crate::piece::{Color, Piece, PlacedPiece, Shape};
|
2024-01-14 10:57:22 -08:00
|
|
|
use crate::BitBoard;
|
2023-12-26 11:25:27 -07:00
|
|
|
use crate::Square;
|
2023-12-26 09:19:38 -07:00
|
|
|
|
|
|
|
pub struct Pieces<'a> {
|
|
|
|
color: Color,
|
|
|
|
position: &'a Position,
|
|
|
|
|
|
|
|
current_shape: Option<Shape>,
|
|
|
|
|
2023-12-31 11:40:54 -08:00
|
|
|
shape_iterator: Box<dyn Iterator<Item = &'static Shape>>,
|
2023-12-26 09:19:38 -07:00
|
|
|
square_iterator: Option<Box<dyn Iterator<Item = Square>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
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<Self::Item> {
|
|
|
|
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<Shape> = None;
|
2024-01-06 16:34:05 -08:00
|
|
|
let mut next_nonempty_bitboard: Option<BitBoard> = None;
|
2023-12-26 09:19:38 -07:00
|
|
|
|
|
|
|
while let Some(shape) = self.shape_iterator.next() {
|
2023-12-31 11:40:54 -08:00
|
|
|
let piece = Piece::new(self.color, *shape);
|
2023-12-26 09:19:38 -07:00
|
|
|
|
2023-12-27 08:31:02 -07:00
|
|
|
let bitboard = self.position.bitboard_for_piece(piece);
|
2023-12-26 09:19:38 -07:00
|
|
|
if bitboard.is_empty() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
next_nonempty_bitboard = Some(bitboard);
|
2023-12-31 11:40:54 -08:00
|
|
|
current_shape = Some(*shape);
|
2023-12-26 09:19:38 -07:00
|
|
|
|
|
|
|
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<PlacedPiece> = 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};
|
2023-12-26 11:25:27 -07:00
|
|
|
use crate::Position;
|
|
|
|
use crate::Square;
|
|
|
|
use std::collections::HashSet;
|
2023-12-26 09:19:38 -07:00
|
|
|
|
2024-01-06 16:34:05 -08:00
|
|
|
fn place_piece_in_position(pos: &mut Position, piece: Piece, sq: Square) {
|
|
|
|
pos.place_piece(piece, sq)
|
2023-12-26 09:19:38 -07:00
|
|
|
.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() {
|
2024-01-06 16:34:05 -08:00
|
|
|
let sq = Square::E4;
|
2023-12-26 09:19:38 -07:00
|
|
|
|
|
|
|
let mut pos = Position::empty();
|
2024-01-06 16:34:05 -08:00
|
|
|
place_piece_in_position(&mut pos, Piece::new(Color::White, Shape::Queen), Square::E4);
|
2023-12-26 09:19:38 -07:00
|
|
|
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();
|
|
|
|
|
2024-01-06 16:34:05 -08:00
|
|
|
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);
|
2023-12-26 09:19:38 -07:00
|
|
|
|
|
|
|
println!("{:?}", &pos);
|
|
|
|
|
|
|
|
let expected_placed_pieces = HashSet::from([
|
2024-01-06 16:34:05 -08:00
|
|
|
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),
|
2023-12-26 09:19:38 -07:00
|
|
|
]);
|
|
|
|
|
|
|
|
let placed_pieces = HashSet::from_iter(pos.pieces(Color::White));
|
|
|
|
|
|
|
|
assert_eq!(placed_pieces, expected_placed_pieces);
|
|
|
|
}
|
|
|
|
}
|