[position] Implement SliderRayToSquareExt on Shape instead of PlacedPiece

Add an origin square argument to its one method ::ray_to_square(). Pushing this
implementation down a layer means I don't have to care about the color of the
piece.
This commit is contained in:
Eryn Wells 2024-02-02 07:29:43 -08:00
parent c8faad799e
commit ac07a8d6cf

View file

@ -41,7 +41,7 @@ pub(crate) trait SightExt {
} }
pub(crate) trait SliderRayToSquareExt { pub(crate) trait SliderRayToSquareExt {
fn ray_to_square(&self, square: Square) -> Option<BitBoard>; fn ray_to_square(&self, origin: Square, target: Square) -> Option<BitBoard>;
} }
impl SightExt for PlacedPiece { impl SightExt for PlacedPiece {
@ -156,8 +156,8 @@ impl SightExt for PlacedPiece {
} }
} }
impl SliderRayToSquareExt for PlacedPiece { impl SliderRayToSquareExt for Shape {
fn ray_to_square(&self, target: Square) -> Option<BitBoard> { fn ray_to_square(&self, origin: Square, target: Square) -> Option<BitBoard> {
macro_rules! ray { macro_rules! ray {
($square:expr, $direction:ident) => { ($square:expr, $direction:ident) => {
( (
@ -167,35 +167,34 @@ impl SliderRayToSquareExt for PlacedPiece {
}; };
} }
let square = self.square();
let target_bitboard: BitBoard = target.into(); let target_bitboard: BitBoard = target.into();
let ray_and_direction = match self.shape() { let ray_and_direction = match self {
Shape::Bishop => [ Shape::Bishop => [
ray!(square, NorthEast), ray!(origin, NorthEast),
ray!(square, SouthEast), ray!(origin, SouthEast),
ray!(square, SouthWest), ray!(origin, SouthWest),
ray!(square, NorthWest), ray!(origin, NorthWest),
] ]
.into_iter() .into_iter()
.find(|(&ray, _)| !(target_bitboard & ray).is_empty()), .find(|(&ray, _)| !(target_bitboard & ray).is_empty()),
Shape::Rook => [ Shape::Rook => [
ray!(square, North), ray!(origin, North),
ray!(square, East), ray!(origin, East),
ray!(square, South), ray!(origin, South),
ray!(square, West), ray!(origin, West),
] ]
.into_iter() .into_iter()
.find(|(&ray, _)| !(target_bitboard & ray).is_empty()), .find(|(&ray, _)| !(target_bitboard & ray).is_empty()),
Shape::Queen => [ Shape::Queen => [
ray!(square, North), ray!(origin, North),
ray!(square, NorthEast), ray!(origin, NorthEast),
ray!(square, East), ray!(origin, East),
ray!(square, SouthEast), ray!(origin, SouthEast),
ray!(square, South), ray!(origin, South),
ray!(square, SouthWest), ray!(origin, SouthWest),
ray!(square, West), ray!(origin, West),
ray!(square, NorthWest), ray!(origin, NorthWest),
] ]
.into_iter() .into_iter()
.find(|(&ray, _)| !(target_bitboard & ray).is_empty()), .find(|(&ray, _)| !(target_bitboard & ray).is_empty()),
@ -203,21 +202,8 @@ impl SliderRayToSquareExt for PlacedPiece {
}; };
if let Some((ray, direction)) = ray_and_direction { if let Some((ray, direction)) = ray_and_direction {
let first_occupied_square = match direction { let remainder = BitBoard::ray(target, direction);
Direction::East return Some(ray & !remainder);
| Direction::NorthWest
| Direction::NorthEast
| Direction::North => ray.first_occupied_square_trailing(),
Direction::West
| Direction::SouthWest
| Direction::SouthEast
| Direction::South => ray.first_occupied_square(),
};
if let Some(occupied_square) = first_occupied_square {
let remainder = BitBoard::ray(target, direction);
return Some(ray & !remainder);
}
} }
None None
@ -248,8 +234,8 @@ mod tests {
#[test] #[test]
fn pawns_and_knights_cannot_make_rays() { fn pawns_and_knights_cannot_make_rays() {
assert_eq!(piece!(White Pawn on F7).ray_to_square(Square::E8), None); assert_eq!(Shape::Pawn.ray_to_square(Square::F7, Square::E8), None);
assert_eq!(piece!(White Knight on F6).ray_to_square(Square::E8), None); assert_eq!(Shape::Knight.ray_to_square(Square::F6, Square::E8), None);
} }
mod pawn { mod pawn {
@ -334,7 +320,7 @@ mod tests {
#[test] #[test]
fn ray_to_square() { fn ray_to_square() {
let generated_ray = piece!(White Bishop on C5).ray_to_square(Square::E7); let generated_ray = Shape::Bishop.ray_to_square(Square::C5, Square::E7);
let expected_ray = bitboard![D6, E7]; let expected_ray = bitboard![D6, E7];
assert_eq!(generated_ray, Some(expected_ray)); assert_eq!(generated_ray, Some(expected_ray));
} }
@ -363,19 +349,19 @@ mod tests {
#[test] #[test]
fn ray_to_square() { fn ray_to_square() {
let generated_ray = piece!(White Rook on C2).ray_to_square(Square::C6); let generated_ray = Shape::Rook.ray_to_square(Square::C2, Square::C6);
let expected_ray = bitboard![C3, C4, C5, C6]; let expected_ray = bitboard![C3, C4, C5, C6];
assert_eq!(generated_ray, Some(expected_ray)); assert_eq!(generated_ray, Some(expected_ray));
let generated_ray = piece!(White Rook on D2).ray_to_square(Square::H2); let generated_ray = Shape::Rook.ray_to_square(Square::D2, Square::H2);
let expected_ray = bitboard![E2, F2, G2, H2]; let expected_ray = bitboard![E2, F2, G2, H2];
assert_eq!(generated_ray, Some(expected_ray)); assert_eq!(generated_ray, Some(expected_ray));
let generated_ray = piece!(White Rook on G6).ray_to_square(Square::B6); let generated_ray = Shape::Rook.ray_to_square(Square::G6, Square::B6);
let expected_ray = bitboard![B6, C6, D6, E6, F6]; let expected_ray = bitboard![B6, C6, D6, E6, F6];
assert_eq!(generated_ray, Some(expected_ray)); assert_eq!(generated_ray, Some(expected_ray));
let generated_ray = piece!(White Rook on A6).ray_to_square(Square::A3); let generated_ray = Shape::Rook.ray_to_square(Square::A6, Square::A3);
let expected_ray = bitboard![A5, A4, A3]; let expected_ray = bitboard![A5, A4, A3];
assert_eq!(generated_ray, Some(expected_ray)); assert_eq!(generated_ray, Some(expected_ray));
} }