From a904e4a5bb2163c3bcfcb25a520878cbfc189365 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Mon, 30 Jun 2025 15:37:35 -0700 Subject: [PATCH] [bitboard, board] Replace ray_in_direction! macro with a function This is simpler than writing a macro, at the expense of some overhead for calling a function. But the Rust compiler might inline it anyway! To support this change, implement BitBoard::first_occupied_square_direction, which iterates a bitboard in a direction (i.e. leading or trailing) depending on the core::Direction value passed to it. --- bitboard/src/bitboard.rs | 12 ++++++++ board/src/sight.rs | 62 +++++++++++++++++++--------------------- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/bitboard/src/bitboard.rs b/bitboard/src/bitboard.rs index 1897de4..f896e57 100644 --- a/bitboard/src/bitboard.rs +++ b/bitboard/src/bitboard.rs @@ -243,6 +243,18 @@ impl BitBoard { TrailingBitScanner::new(self.0) } + #[must_use] + pub fn first_occupied_square_direction(&self, direction: Direction) -> Option { + match direction { + Direction::North | Direction::NorthEast | Direction::NorthWest | Direction::East => { + self.first_occupied_square_trailing() + } + Direction::SouthEast | Direction::South | Direction::SouthWest | Direction::West => { + self.first_occupied_square_leading() + } + } + } + #[must_use] pub fn first_occupied_square(&self, direction: &IterationDirection) -> Option { match direction { diff --git a/board/src/sight.rs b/board/src/sight.rs index 8e5cbc6..b8e366e 100644 --- a/board/src/sight.rs +++ b/board/src/sight.rs @@ -138,20 +138,6 @@ struct SightInfo { friendly_occupancy: BitBoard, } -macro_rules! ray_in_direction { - ($square:expr, $blockers:expr, $direction:ident, $first_occupied_square:tt) => {{ - let ray = BitBoard::ray($square, Direction::$direction); - let ray_blockers = ray & $blockers; - if let Some(first_occupied_square) = ray_blockers.$first_occupied_square() { - let remainder = BitBoard::ray(first_occupied_square, Direction::$direction); - let attack_ray = ray & !remainder; - attack_ray - } else { - ray - } - }}; -} - /// Compute sight of a white pawn. fn white_pawn_sight(info: &SightInfo, en_passant_square: BitBoard) -> BitBoard { let possible_squares = !info.friendly_occupancy | en_passant_square; @@ -175,15 +161,27 @@ fn knight_sight(info: &SightInfo) -> BitBoard { BitBoard::knight_moves(info.square) } +fn ray_in_direction(square: Square, blockers: BitBoard, direction: Direction) -> BitBoard { + let ray = BitBoard::ray(square, direction); + + let ray_blockers = ray & blockers; + if let Some(first_occupied_square) = ray_blockers.first_occupied_square_direction(direction) { + let remainder = BitBoard::ray(first_occupied_square, direction); + let attack_ray = ray & !remainder; + attack_ray + } else { + ray + } +} + fn bishop_sight(info: &SightInfo) -> BitBoard { let bishop = info.square; let occupancy = info.occupancy; - #[rustfmt::skip] - let sight = ray_in_direction!(bishop, occupancy, NorthEast, first_occupied_square_trailing) - | ray_in_direction!(bishop, occupancy, SouthEast, first_occupied_square_leading) - | ray_in_direction!(bishop, occupancy, SouthWest, first_occupied_square_leading) - | ray_in_direction!(bishop, occupancy, NorthWest, first_occupied_square_trailing); + let sight = ray_in_direction(bishop, occupancy, Direction::NorthEast) + | ray_in_direction(bishop, occupancy, Direction::SouthEast) + | ray_in_direction(bishop, occupancy, Direction::SouthWest) + | ray_in_direction(bishop, occupancy, Direction::NorthWest); sight } @@ -192,11 +190,10 @@ fn rook_sight(info: &SightInfo) -> BitBoard { let rook = info.square; let occupancy = info.occupancy; - #[rustfmt::skip] - let sight = ray_in_direction!(rook, occupancy, North, first_occupied_square_trailing) - | ray_in_direction!(rook, occupancy, East, first_occupied_square_trailing) - | ray_in_direction!(rook, occupancy, South, first_occupied_square_leading) - | ray_in_direction!(rook, occupancy, West, first_occupied_square_leading); + let sight = ray_in_direction(rook, occupancy, Direction::North) + | ray_in_direction(rook, occupancy, Direction::East) + | ray_in_direction(rook, occupancy, Direction::South) + | ray_in_direction(rook, occupancy, Direction::West); sight } @@ -205,15 +202,14 @@ fn queen_sight(info: &SightInfo) -> BitBoard { let queen = info.square; let occupancy = info.occupancy; - #[rustfmt::skip] - let sight = ray_in_direction!(queen, occupancy, NorthWest, first_occupied_square_trailing) - | ray_in_direction!(queen, occupancy, North, first_occupied_square_trailing) - | ray_in_direction!(queen, occupancy, NorthEast, first_occupied_square_trailing) - | ray_in_direction!(queen, occupancy, East, first_occupied_square_trailing) - | ray_in_direction!(queen, occupancy, SouthEast, first_occupied_square_leading) - | ray_in_direction!(queen, occupancy, South, first_occupied_square_leading) - | ray_in_direction!(queen, occupancy, SouthWest, first_occupied_square_leading) - | ray_in_direction!(queen, occupancy, West, first_occupied_square_leading); + let sight = ray_in_direction(queen, occupancy, Direction::NorthWest) + | ray_in_direction(queen, occupancy, Direction::North) + | ray_in_direction(queen, occupancy, Direction::NorthEast) + | ray_in_direction(queen, occupancy, Direction::East) + | ray_in_direction(queen, occupancy, Direction::SouthEast) + | ray_in_direction(queen, occupancy, Direction::South) + | ray_in_direction(queen, occupancy, Direction::SouthWest) + | ray_in_direction(queen, occupancy, Direction::West); sight }