// Eryn Wells use chessfriend_bitboard::BitBoard; use chessfriend_core::{PlacedPiece, Square}; use chessfriend_moves::{Builder as MoveBuilder, Castle, Move}; /// A set of bitboards defining the moves for a single piece on the board. #[derive(Clone, Debug, Default, Eq, PartialEq)] struct BitBoardSet { quiet: BitBoard, captures: BitBoard, } /// A set of moves for a single piece on the board. #[derive(Clone, Debug, Eq, PartialEq)] pub(crate) struct MoveSet { piece: PlacedPiece, bitboards: BitBoardSet, special: u8, } impl MoveSet { pub(super) fn new(piece: PlacedPiece) -> MoveSet { MoveSet { piece, bitboards: BitBoardSet::default(), special: 0, } } pub(crate) fn can_move_to_square(&self, to: Square) -> bool { self.bitboard().is_set(to) } pub(crate) fn can_castle(&self, castle: Castle) -> bool { match castle { Castle::KingSide => (self.special & 0b1) != 0, Castle::QueenSide => (self.special & 0b10) != 0, } } pub(super) fn quiet_moves(mut self, bitboard: BitBoard) -> MoveSet { self.bitboards.quiet = bitboard; self } pub(super) fn capture_moves(mut self, bitboard: BitBoard) -> MoveSet { self.bitboards.captures = bitboard; self } pub(super) fn kingside_castle(&mut self) -> &mut MoveSet { self.special |= 0b1; self } pub(super) fn queenside_castle(&mut self) -> &mut MoveSet { self.special |= 0b10; self } /// Return a BitBoard representing all possible moves. pub(super) fn bitboard(&self) -> BitBoard { self.bitboards.captures | self.bitboards.quiet } pub(crate) fn moves(&self) -> impl Iterator + '_ { let piece = &self.piece; self.bitboards .quiet .occupied_squares() .filter_map(|to_square| MoveBuilder::push(&self.piece).to(to_square).build().ok()) .chain( self.bitboards .captures .occupied_squares() .filter_map(|to_square| MoveBuilder::push(piece).to(to_square).build().ok()), ) .chain( if (self.special & 0b1) != 0 { let mv = MoveBuilder::castling(Castle::KingSide).build(); Some(mv) } else { None } .into_iter(), ) .chain( if (self.special & 0b10) != 0 { Some(MoveBuilder::castling(Castle::QueenSide).build()) } else { None } .into_iter(), ) } }