[position] Implement generating pawn moves by looking up bitboards in the Library
This enables a bunch of clean up! Remove the MoveGenerationParameters and MoveList types from move_generator::pawn. Implement BitBoard::pawn_pushes to look up pawn pushes by square and color.
This commit is contained in:
parent
77f419ad3b
commit
ea74b214da
3 changed files with 48 additions and 72 deletions
|
@ -1,27 +1,13 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
use super::{move_generator_declaration, MoveGeneratorInternal, MoveSet};
|
||||
use crate::{Move, MoveBuilder, Position};
|
||||
use crate::{MoveBuilder, Position};
|
||||
use chessfriend_bitboard::BitBoard;
|
||||
use chessfriend_core::{Color, Piece, PlacedPiece, Shape, Square};
|
||||
|
||||
enum MoveList {
|
||||
Quiet = 0,
|
||||
Promotions = 1,
|
||||
Captures = 2,
|
||||
}
|
||||
use chessfriend_core::{Color, Piece, PlacedPiece, Square};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MoveIterator(usize, usize);
|
||||
|
||||
struct MoveGenerationParameters {
|
||||
starting_rank: BitBoard,
|
||||
promotion_rank: BitBoard,
|
||||
push_shift: fn(&BitBoard) -> BitBoard,
|
||||
left_capture_shift: fn(&BitBoard) -> BitBoard,
|
||||
right_capture_shift: fn(&BitBoard) -> BitBoard,
|
||||
}
|
||||
|
||||
move_generator_declaration!(PawnMoveGenerator);
|
||||
|
||||
impl MoveGeneratorInternal for PawnMoveGenerator {
|
||||
|
@ -31,12 +17,9 @@ impl MoveGeneratorInternal for PawnMoveGenerator {
|
|||
|
||||
fn move_set_for_piece(position: &Position, placed_piece: PlacedPiece) -> MoveSet {
|
||||
let from_square = placed_piece.square();
|
||||
let parameters = Self::move_generation_parameters(placed_piece.color());
|
||||
|
||||
let opposing_pieces = position.opposing_pieces();
|
||||
|
||||
let captures_bitboard = Self::attacks(position, placed_piece, ¶meters);
|
||||
let quiet_moves_bitboard = Self::pushes(position, placed_piece, ¶meters);
|
||||
let captures_bitboard = Self::attacks(position, placed_piece);
|
||||
let quiet_moves_bitboard = Self::pushes(position, placed_piece);
|
||||
|
||||
let quiet_moves = quiet_moves_bitboard.occupied_squares().map(|to_square| {
|
||||
MoveBuilder::new(*placed_piece.piece(), from_square, to_square).build()
|
||||
|
@ -55,67 +38,34 @@ impl MoveGeneratorInternal for PawnMoveGenerator {
|
|||
}
|
||||
|
||||
impl PawnMoveGenerator {
|
||||
fn move_generation_parameters(color: Color) -> MoveGenerationParameters {
|
||||
match color {
|
||||
Color::White => MoveGenerationParameters {
|
||||
starting_rank: BitBoard::rank(1),
|
||||
promotion_rank: BitBoard::rank(7),
|
||||
push_shift: BitBoard::shift_north_one,
|
||||
left_capture_shift: BitBoard::shift_north_west_one,
|
||||
right_capture_shift: BitBoard::shift_north_east_one,
|
||||
},
|
||||
Color::Black => MoveGenerationParameters {
|
||||
starting_rank: BitBoard::rank(6),
|
||||
promotion_rank: BitBoard::rank(0),
|
||||
push_shift: BitBoard::shift_south_one,
|
||||
left_capture_shift: BitBoard::shift_south_east_one,
|
||||
right_capture_shift: BitBoard::shift_south_west_one,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn pushes(
|
||||
position: &Position,
|
||||
piece: PlacedPiece,
|
||||
parameters: &MoveGenerationParameters,
|
||||
) -> BitBoard {
|
||||
fn pushes(position: &Position, piece: PlacedPiece) -> BitBoard {
|
||||
let empty_squares = position.empty_squares();
|
||||
let from_square: BitBoard = piece.square().into();
|
||||
|
||||
(parameters.push_shift)(&from_square) & empty_squares
|
||||
BitBoard::pawn_pushes(piece.square(), piece.color()) & empty_squares
|
||||
}
|
||||
|
||||
fn attacks(
|
||||
position: &Position,
|
||||
piece: PlacedPiece,
|
||||
parameters: &MoveGenerationParameters,
|
||||
) -> BitBoard {
|
||||
fn attacks(position: &Position, piece: PlacedPiece) -> BitBoard {
|
||||
let color = piece.color();
|
||||
|
||||
let opponent_pieces = position.bitboard_for_color(color.other());
|
||||
let en_passant_square = position
|
||||
.en_passant_square()
|
||||
.map(|square| <Square as Into<BitBoard>>::into(square))
|
||||
.unwrap_or(BitBoard::empty());
|
||||
let en_passant_bitboard = match position.en_passant_square() {
|
||||
Some(square) => <Square as Into<BitBoard>>::into(square),
|
||||
None => BitBoard::empty(),
|
||||
};
|
||||
|
||||
let from_square: BitBoard = piece.square().into();
|
||||
|
||||
((parameters.left_capture_shift)(&from_square)
|
||||
| (parameters.right_capture_shift)(&from_square))
|
||||
& (opponent_pieces | en_passant_square)
|
||||
BitBoard::pawn_attacks(piece.square(), color) & (opponent_pieces | en_passant_bitboard)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{position, position::DiagramFormatter};
|
||||
use crate::{position::DiagramFormatter, test_position, Move};
|
||||
use chessfriend_core::{piece, Square};
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[test]
|
||||
fn one_2square_push() {
|
||||
let pos = position![White Pawn on E2];
|
||||
let pos = test_position![White Pawn on E2];
|
||||
|
||||
let generator = PawnMoveGenerator::new(&pos, Color::White);
|
||||
|
||||
|
@ -131,7 +81,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn one_1square_push() {
|
||||
let mut pos = position![White Pawn on E3];
|
||||
let pos = test_position![White Pawn on E3];
|
||||
|
||||
let generator = PawnMoveGenerator::new(&pos, Color::White);
|
||||
|
||||
|
@ -149,7 +99,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn one_obstructed_2square_push() {
|
||||
let pos = position![
|
||||
let pos = test_position![
|
||||
White Pawn on E2,
|
||||
White Knight on E4,
|
||||
];
|
||||
|
@ -172,11 +122,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn one_obstructed_1square_push() {
|
||||
let mut pos = position![
|
||||
let pos = test_position![
|
||||
White Pawn on E2,
|
||||
White Knight on E3,
|
||||
];
|
||||
println!("{}", DiagramFormatter::new(&pos));
|
||||
|
||||
let generator = PawnMoveGenerator::new(&pos, Color::White);
|
||||
|
||||
|
@ -187,12 +136,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn one_attack() {
|
||||
let pos = position![
|
||||
let pos = test_position![
|
||||
White Pawn on E4,
|
||||
White Bishop on E5,
|
||||
Black Knight on D5,
|
||||
];
|
||||
println!("{}", DiagramFormatter::new(&pos));
|
||||
|
||||
let generator = PawnMoveGenerator::new(&pos, Color::White);
|
||||
|
||||
|
@ -210,13 +158,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn one_double_attack() {
|
||||
let pos = position![
|
||||
let pos = test_position![
|
||||
White Pawn on E4,
|
||||
White Bishop on E5,
|
||||
Black Knight on D5,
|
||||
Black Queen on F5,
|
||||
];
|
||||
println!("{}", DiagramFormatter::new(&pos));
|
||||
|
||||
let generator = PawnMoveGenerator::new(&pos, Color::White);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue