diff --git a/position/src/move_generator/pawn.rs b/position/src/move_generator/pawn.rs index c6e7a5a..1aa7a4d 100644 --- a/position/src/move_generator/pawn.rs +++ b/position/src/move_generator/pawn.rs @@ -1,14 +1,22 @@ // Eryn Wells use super::{move_generator_declaration, MoveGeneratorInternal, MoveSet}; -use crate::Position; +use crate::{r#move::Move, MoveBuilder, Position}; use chessfriend_bitboard::BitBoard; use chessfriend_core::{Color, PlacedPiece, Rank, Shape, Square}; +use std::collections::BTreeMap; #[derive(Debug)] struct MoveIterator(usize, usize); -move_generator_declaration!(PawnMoveGenerator); +#[derive(Clone, Debug, Eq, PartialEq)] +pub(super) struct PawnMoveGenerator { + color: chessfriend_core::Color, + move_sets: BTreeMap, + en_passant_captures: Vec, +} + +move_generator_declaration!(PawnMoveGenerator, getters); impl MoveGeneratorInternal for PawnMoveGenerator { fn shape() -> Shape { @@ -31,7 +39,50 @@ impl MoveGeneratorInternal for PawnMoveGenerator { } impl PawnMoveGenerator { - fn pushes(position: &Position, piece: PlacedPiece) -> BitBoard { + pub(super) fn new( + position: &Position, + color: Color, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> Self { + let move_sets = if !capture_mask.is_empty() && !push_mask.is_empty() { + Self::move_sets(position, color, capture_mask, push_mask) + } else { + std::collections::BTreeMap::new() + }; + + Self { + color, + move_sets, + en_passant_captures: Vec::new(), + } + } + + fn move_sets( + position: &Position, + color: Color, + capture_mask: BitBoard, + push_mask: BitBoard, + ) -> BTreeMap { + let piece = Self::piece(color); + let mut moves_for_pieces = + BTreeMap::from_iter(position.bitboard_for_piece(piece).occupied_squares().map( + |square| { + let piece = PlacedPiece::new(piece, square); + let move_set = + Self::move_set_for_piece(position, &piece, capture_mask, push_mask); + (square, move_set) + }, + )); + + if position.has_en_passant_square() { + + } + + moves_for_pieces + } + + fn pushes(position: &Position, piece: &PlacedPiece) -> BitBoard { let color = piece.color(); let square = piece.square(); let bitboard: BitBoard = square.into(); @@ -59,16 +110,40 @@ impl PawnMoveGenerator { } } - fn attacks(position: &Position, piece: PlacedPiece) -> BitBoard { + fn attacks(position: &Position, piece: &PlacedPiece) -> BitBoard { let color = piece.color(); let opponent_pieces = position.bitboard_for_color(color.other()); - let en_passant_bitboard = match position.en_passant_square() { - Some(square) => >::into(square), - None => BitBoard::empty(), - }; - BitBoard::pawn_attacks(piece.square(), color) & (opponent_pieces | en_passant_bitboard) + BitBoard::pawn_attacks(piece.square(), color) & opponent_pieces + } + + fn en_passant_attack(position: &Position, piece: &PlacedPiece) -> Option { + match position.en_passant() { + Some(en_passant) => { + let en_passant_bitboard: BitBoard = en_passant.target_square().into(); + let capture = + BitBoard::pawn_attacks(piece.square(), piece.color()) & en_passant_bitboard; + + if capture.is_empty() { + return None; + } + + match position.piece_on_square(en_passant.capture_square()) { + Some(captured_piece) => Some( + MoveBuilder::new( + *piece.piece(), + piece.square(), + en_passant.target_square(), + ) + .capturing_en_passant(captured_piece) + .build(), + ), + None => None, + } + } + None => None, + } } }