[position] Refactor sight routines
- Break out the actual routines into file-private helper functions - Declare traits for each piece type that call the corresponding helper function - Implement these traits on PlacedPiece The sight routines changed slightly such that they include the player's own pieces in the resulting BitBoard. The tests neeeded to be updated to account for this.
This commit is contained in:
parent
f0b9681cef
commit
069f94e8c2
1 changed files with 169 additions and 91 deletions
|
@ -1,5 +1,9 @@
|
|||
// Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
//! Defines routines for computing sight of a piece. Sight is the set of squares
|
||||
//! that a piece can see. In other words, it's the set of squares attacked or
|
||||
//! controled by a piece.
|
||||
|
||||
use crate::position::piece_sets::PieceBitBoards;
|
||||
use chessfriend_bitboard::BitBoard;
|
||||
use chessfriend_core::{Color, Direction, PlacedPiece, Shape, Square};
|
||||
|
@ -18,8 +22,84 @@ macro_rules! ray_in_direction {
|
|||
}};
|
||||
}
|
||||
|
||||
pub(crate) trait SightExt {
|
||||
fn sight(&self, pieces: &PieceBitBoards, en_passant_square: Option<Square>) -> BitBoard;
|
||||
/// Compute sight of a white pawn.
|
||||
fn _white_pawn_sight(
|
||||
pawn: &BitBoard,
|
||||
occupancy: &BitBoard,
|
||||
blockers: &BitBoard,
|
||||
en_passant_square: &BitBoard,
|
||||
) -> BitBoard {
|
||||
let possible_squares = !occupancy | blockers | en_passant_square;
|
||||
let pawn = pawn.shift_north_west_one() | pawn.shift_north_east_one();
|
||||
pawn & possible_squares
|
||||
}
|
||||
|
||||
fn _black_pawn_sight(
|
||||
pawn: &BitBoard,
|
||||
occupancy: &BitBoard,
|
||||
blockers: &BitBoard,
|
||||
en_passant_square: &BitBoard,
|
||||
) -> BitBoard {
|
||||
let possible_squares = !occupancy | blockers | en_passant_square;
|
||||
let pawn = pawn.shift_south_west_one() | pawn.shift_south_east_one();
|
||||
pawn & possible_squares
|
||||
}
|
||||
|
||||
fn _knight_sight(knight_square: Square, blockers: &BitBoard) -> BitBoard {
|
||||
BitBoard::knight_moves(knight_square) & !blockers
|
||||
}
|
||||
|
||||
fn _bishop_sight(bishop_square: Square, occupancy: &BitBoard) -> BitBoard {
|
||||
#[rustfmt::skip]
|
||||
let sight = ray_in_direction!(bishop_square, occupancy, NorthEast, occupied_squares_trailing)
|
||||
| ray_in_direction!(bishop_square, occupancy, NorthWest, occupied_squares_trailing)
|
||||
| ray_in_direction!(bishop_square, occupancy, SouthEast, occupied_squares)
|
||||
| ray_in_direction!(bishop_square, occupancy, SouthWest, occupied_squares);
|
||||
|
||||
sight
|
||||
}
|
||||
|
||||
fn _rook_sight(rook_square: Square, occupancy: &BitBoard) -> BitBoard {
|
||||
#[rustfmt::skip]
|
||||
let sight = ray_in_direction!(rook_square, occupancy, North, occupied_squares_trailing)
|
||||
| ray_in_direction!(rook_square, occupancy, East, occupied_squares_trailing)
|
||||
| ray_in_direction!(rook_square, occupancy, South, occupied_squares)
|
||||
| ray_in_direction!(rook_square, occupancy, West, occupied_squares);
|
||||
|
||||
sight
|
||||
}
|
||||
|
||||
fn _queen_sight(queen_square: Square, occupancy: &BitBoard) -> BitBoard {
|
||||
#[rustfmt::skip]
|
||||
let sight = ray_in_direction!(queen_square, occupancy, NorthWest, occupied_squares_trailing)
|
||||
| ray_in_direction!(queen_square, occupancy, North, occupied_squares_trailing)
|
||||
| ray_in_direction!(queen_square, occupancy, NorthEast, occupied_squares_trailing)
|
||||
| ray_in_direction!(queen_square, occupancy, East, occupied_squares_trailing)
|
||||
| ray_in_direction!(queen_square, occupancy, SouthEast, occupied_squares)
|
||||
| ray_in_direction!(queen_square, occupancy, South, occupied_squares)
|
||||
| ray_in_direction!(queen_square, occupancy, SouthWest, occupied_squares)
|
||||
| ray_in_direction!(queen_square, occupancy, West, occupied_squares);
|
||||
|
||||
sight
|
||||
}
|
||||
|
||||
fn _king_sight(king_square: Square, blockers: &BitBoard) -> BitBoard {
|
||||
BitBoard::king_moves(king_square) & !blockers
|
||||
}
|
||||
pub(crate) trait BishopSightExt {
|
||||
fn bishop_sight(&self, occupancy: &BitBoard) -> BitBoard;
|
||||
}
|
||||
|
||||
pub(crate) trait KingSightExt {
|
||||
fn king_sight(&self, pieces: &PieceBitBoards) -> BitBoard;
|
||||
}
|
||||
|
||||
pub(crate) trait KnightSightExt {
|
||||
fn knight_sight(&self, pieces: &PieceBitBoards) -> BitBoard;
|
||||
}
|
||||
|
||||
pub(crate) trait PawnSightExt {
|
||||
fn pawn_sight(&self, pieces: &PieceBitBoards, en_passant_square: Option<Square>) -> BitBoard;
|
||||
|
||||
fn white_pawn_sight(
|
||||
&self,
|
||||
|
@ -32,12 +112,19 @@ pub(crate) trait SightExt {
|
|||
pieces: &PieceBitBoards,
|
||||
en_passant_square: Option<Square>,
|
||||
) -> BitBoard;
|
||||
}
|
||||
pub(crate) trait QueenSightExt {
|
||||
fn queen_sight(&self, occupancy: &BitBoard) -> BitBoard;
|
||||
}
|
||||
|
||||
fn knight_sight(&self, pieces: &PieceBitBoards) -> BitBoard;
|
||||
fn bishop_sight(&self, pieces: &PieceBitBoards) -> BitBoard;
|
||||
fn rook_sight(&self, pieces: &PieceBitBoards) -> BitBoard;
|
||||
fn queen_sight(&self, pieces: &PieceBitBoards) -> BitBoard;
|
||||
fn king_sight(&self, pieces: &PieceBitBoards) -> BitBoard;
|
||||
pub(crate) trait RookSightExt {
|
||||
fn rook_sight(&self, occupancy: &BitBoard) -> BitBoard;
|
||||
}
|
||||
|
||||
pub(crate) trait SliderSightExt: BishopSightExt + QueenSightExt + RookSightExt {}
|
||||
|
||||
pub(crate) trait SightExt {
|
||||
fn sight(&self, pieces: &PieceBitBoards, en_passant_square: Option<Square>) -> BitBoard;
|
||||
}
|
||||
|
||||
pub(crate) trait SliderRayToSquareExt {
|
||||
|
@ -52,12 +139,33 @@ impl SightExt for PlacedPiece {
|
|||
Color::Black => self.black_pawn_sight(pieces, en_passant_square),
|
||||
},
|
||||
Shape::Knight => self.knight_sight(pieces),
|
||||
Shape::Bishop => self.bishop_sight(pieces),
|
||||
Shape::Rook => self.rook_sight(pieces),
|
||||
Shape::Queen => self.queen_sight(pieces),
|
||||
Shape::Bishop => self.bishop_sight(pieces.all_pieces()),
|
||||
Shape::Rook => self.rook_sight(pieces.all_pieces()),
|
||||
Shape::Queen => self.queen_sight(pieces.all_pieces()),
|
||||
Shape::King => self.king_sight(pieces),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KingSightExt for PlacedPiece {
|
||||
fn king_sight(&self, pieces: &PieceBitBoards) -> BitBoard {
|
||||
_king_sight(self.square(), pieces.all_pieces_of_color(self.color()))
|
||||
}
|
||||
}
|
||||
|
||||
impl KnightSightExt for PlacedPiece {
|
||||
fn knight_sight(&self, pieces: &PieceBitBoards) -> BitBoard {
|
||||
_knight_sight(self.square(), pieces.all_pieces_of_color(self.color()))
|
||||
}
|
||||
}
|
||||
|
||||
impl PawnSightExt for PlacedPiece {
|
||||
fn pawn_sight(&self, pieces: &PieceBitBoards, en_passant_square: Option<Square>) -> BitBoard {
|
||||
match self.color() {
|
||||
Color::White => self.white_pawn_sight(pieces, en_passant_square),
|
||||
Color::Black => self.black_pawn_sight(pieces, en_passant_square),
|
||||
}
|
||||
}
|
||||
|
||||
fn white_pawn_sight(
|
||||
&self,
|
||||
|
@ -65,16 +173,12 @@ impl SightExt for PlacedPiece {
|
|||
en_passant_square: Option<Square>,
|
||||
) -> BitBoard {
|
||||
let opponent = self.color().other();
|
||||
let pawn: BitBoard = self.square().into();
|
||||
let pawn = pawn.shift_north_west_one() | pawn.shift_north_east_one();
|
||||
|
||||
let mut possible_squares = pieces.empty_squares() | pieces.all_pieces_of_color(opponent);
|
||||
if let Some(en_passant) = en_passant_square {
|
||||
let en_passant_bitboard: BitBoard = en_passant.into();
|
||||
possible_squares |= en_passant_bitboard;
|
||||
}
|
||||
|
||||
pawn & possible_squares
|
||||
_white_pawn_sight(
|
||||
&self.square().into(),
|
||||
pieces.all_pieces(),
|
||||
pieces.all_pieces_of_color(opponent),
|
||||
&en_passant_square.into(),
|
||||
)
|
||||
}
|
||||
|
||||
fn black_pawn_sight(
|
||||
|
@ -83,79 +187,35 @@ impl SightExt for PlacedPiece {
|
|||
en_passant_square: Option<Square>,
|
||||
) -> BitBoard {
|
||||
let opponent = self.color().other();
|
||||
|
||||
let pawn: BitBoard = self.square().into();
|
||||
let pawn = pawn.shift_south_west_one() | pawn.shift_south_east_one();
|
||||
|
||||
let mut possible_squares = pieces.empty_squares() | pieces.all_pieces_of_color(opponent);
|
||||
if let Some(en_passant) = en_passant_square {
|
||||
possible_squares |= &en_passant.into();
|
||||
}
|
||||
|
||||
pawn & possible_squares
|
||||
}
|
||||
|
||||
fn knight_sight(&self, pieces: &PieceBitBoards) -> BitBoard {
|
||||
BitBoard::knight_moves(self.square()) & !pieces.all_pieces_of_color(self.color())
|
||||
}
|
||||
|
||||
fn bishop_sight(&self, pieces: &PieceBitBoards) -> BitBoard {
|
||||
let square = self.square();
|
||||
|
||||
let mut sight = BitBoard::empty();
|
||||
|
||||
let blockers = pieces.all_pieces();
|
||||
|
||||
sight |= ray_in_direction!(square, blockers, NorthEast, occupied_squares_trailing);
|
||||
sight |= ray_in_direction!(square, blockers, NorthWest, occupied_squares_trailing);
|
||||
sight |= ray_in_direction!(square, blockers, SouthEast, occupied_squares);
|
||||
sight |= ray_in_direction!(square, blockers, SouthWest, occupied_squares);
|
||||
|
||||
let friendly_pieces = pieces.all_pieces_of_color(self.color());
|
||||
sight & !friendly_pieces
|
||||
}
|
||||
|
||||
fn rook_sight(&self, pieces: &PieceBitBoards) -> BitBoard {
|
||||
let square = self.square();
|
||||
|
||||
let mut sight = BitBoard::empty();
|
||||
|
||||
let blockers = pieces.all_pieces();
|
||||
|
||||
sight |= ray_in_direction!(square, blockers, North, occupied_squares_trailing);
|
||||
sight |= ray_in_direction!(square, blockers, East, occupied_squares_trailing);
|
||||
sight |= ray_in_direction!(square, blockers, South, occupied_squares);
|
||||
sight |= ray_in_direction!(square, blockers, West, occupied_squares);
|
||||
|
||||
let friendly_pieces = pieces.all_pieces_of_color(self.color());
|
||||
sight & !friendly_pieces
|
||||
}
|
||||
|
||||
fn queen_sight(&self, pieces: &PieceBitBoards) -> BitBoard {
|
||||
let square = self.square();
|
||||
|
||||
let mut sight = BitBoard::empty();
|
||||
|
||||
let blockers = pieces.all_pieces();
|
||||
|
||||
sight |= ray_in_direction!(square, blockers, NorthWest, occupied_squares_trailing);
|
||||
sight |= ray_in_direction!(square, blockers, North, occupied_squares_trailing);
|
||||
sight |= ray_in_direction!(square, blockers, NorthEast, occupied_squares_trailing);
|
||||
sight |= ray_in_direction!(square, blockers, East, occupied_squares_trailing);
|
||||
sight |= ray_in_direction!(square, blockers, SouthEast, occupied_squares);
|
||||
sight |= ray_in_direction!(square, blockers, South, occupied_squares);
|
||||
sight |= ray_in_direction!(square, blockers, SouthWest, occupied_squares);
|
||||
sight |= ray_in_direction!(square, blockers, West, occupied_squares);
|
||||
|
||||
let friendly_pieces = pieces.all_pieces_of_color(self.color());
|
||||
sight & !friendly_pieces
|
||||
}
|
||||
|
||||
fn king_sight(&self, pieces: &PieceBitBoards) -> BitBoard {
|
||||
BitBoard::king_moves(self.square()) & !pieces.all_pieces_of_color(self.color())
|
||||
_black_pawn_sight(
|
||||
&self.square().into(),
|
||||
pieces.all_pieces(),
|
||||
pieces.all_pieces_of_color(opponent),
|
||||
&en_passant_square.into(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl BishopSightExt for PlacedPiece {
|
||||
fn bishop_sight(&self, occupancy: &BitBoard) -> BitBoard {
|
||||
_bishop_sight(self.square(), occupancy)
|
||||
}
|
||||
}
|
||||
|
||||
impl RookSightExt for PlacedPiece {
|
||||
fn rook_sight(&self, occupancy: &BitBoard) -> BitBoard {
|
||||
_rook_sight(self.square(), occupancy)
|
||||
}
|
||||
}
|
||||
|
||||
impl QueenSightExt for PlacedPiece {
|
||||
fn queen_sight(&self, occupancy: &BitBoard) -> BitBoard {
|
||||
_queen_sight(self.square(), occupancy)
|
||||
}
|
||||
}
|
||||
|
||||
impl SliderSightExt for PlacedPiece {}
|
||||
|
||||
impl SliderRayToSquareExt for Shape {
|
||||
fn ray_to_square(&self, origin: Square, target: Square) -> Option<BitBoard> {
|
||||
macro_rules! ray {
|
||||
|
@ -210,6 +270,24 @@ impl SliderRayToSquareExt for Shape {
|
|||
}
|
||||
}
|
||||
|
||||
impl BishopSightExt for Square {
|
||||
fn bishop_sight(&self, occupancy: &BitBoard) -> BitBoard {
|
||||
_bishop_sight(*self, occupancy)
|
||||
}
|
||||
}
|
||||
|
||||
impl QueenSightExt for Square {
|
||||
fn queen_sight(&self, occupancy: &BitBoard) -> BitBoard {
|
||||
_queen_sight(*self, occupancy)
|
||||
}
|
||||
}
|
||||
|
||||
impl RookSightExt for Square {
|
||||
fn rook_sight(&self, occupancy: &BitBoard) -> BitBoard {
|
||||
_rook_sight(*self, occupancy)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -345,7 +423,7 @@ mod tests {
|
|||
Black King on E7,
|
||||
],
|
||||
piece!(White Rook on E4),
|
||||
bitboard!(A4, B4, C4, D4, F4, G4, H4, E2, E3, E5, E6, E7)
|
||||
bitboard!(A4, B4, C4, D4, F4, G4, H4, E2, E3, E5, E6, E7, E1)
|
||||
);
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue