Rework the Pawn move generator to correctly compute en passant moves
This commit is contained in:
parent
3b8b6b36e3
commit
c03a804c79
1 changed files with 84 additions and 9 deletions
|
@ -1,14 +1,22 @@
|
||||||
// Eryn Wells <eryn@erynwells.me>
|
// Eryn Wells <eryn@erynwells.me>
|
||||||
|
|
||||||
use super::{move_generator_declaration, MoveGeneratorInternal, MoveSet};
|
use super::{move_generator_declaration, MoveGeneratorInternal, MoveSet};
|
||||||
use crate::Position;
|
use crate::{r#move::Move, MoveBuilder, Position};
|
||||||
use chessfriend_bitboard::BitBoard;
|
use chessfriend_bitboard::BitBoard;
|
||||||
use chessfriend_core::{Color, PlacedPiece, Rank, Shape, Square};
|
use chessfriend_core::{Color, PlacedPiece, Rank, Shape, Square};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct MoveIterator(usize, usize);
|
struct MoveIterator(usize, usize);
|
||||||
|
|
||||||
move_generator_declaration!(PawnMoveGenerator);
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub(super) struct PawnMoveGenerator {
|
||||||
|
color: chessfriend_core::Color,
|
||||||
|
move_sets: BTreeMap<Square, MoveSet>,
|
||||||
|
en_passant_captures: Vec<Move>,
|
||||||
|
}
|
||||||
|
|
||||||
|
move_generator_declaration!(PawnMoveGenerator, getters);
|
||||||
|
|
||||||
impl MoveGeneratorInternal for PawnMoveGenerator {
|
impl MoveGeneratorInternal for PawnMoveGenerator {
|
||||||
fn shape() -> Shape {
|
fn shape() -> Shape {
|
||||||
|
@ -31,7 +39,50 @@ impl MoveGeneratorInternal for PawnMoveGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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<Square, MoveSet> {
|
||||||
|
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 color = piece.color();
|
||||||
let square = piece.square();
|
let square = piece.square();
|
||||||
let bitboard: BitBoard = square.into();
|
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 color = piece.color();
|
||||||
|
|
||||||
let opponent_pieces = position.bitboard_for_color(color.other());
|
let opponent_pieces = position.bitboard_for_color(color.other());
|
||||||
let en_passant_bitboard = match position.en_passant_square() {
|
|
||||||
Some(square) => <Square as Into<BitBoard>>::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<Move> {
|
||||||
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue