Add 'Direction::move_board'

Encapsulates the way to move a piece on a board, avoiding the need to
mask and shift by hand.
This commit is contained in:
Bruno BELANYI 2022-07-17 23:06:50 +02:00
parent b840bfc570
commit 924689ec02

View file

@ -1,3 +1,5 @@
use super::{Bitboard, Rank};
/// A direction on the board. Either along the rook, bishop, or knight directions
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Direction {
@ -20,3 +22,525 @@ pub enum Direction {
NorthEastEast,
NorthNorthEast,
}
impl Direction {
/// Move every piece on a board along the given direction. Do not wrap around the board.
#[inline(always)]
pub fn move_board(self, board: Bitboard) -> Bitboard {
// No need to filter for A/H ranks thanks to wrapping
match self {
Self::North => (board - Rank::Eighth.into_bitboard()) << 1,
Self::West => board >> 8,
Self::South => (board - Rank::First.into_bitboard()) >> 1,
Self::East => board << 8,
Self::NorthWest => (board - Rank::Eighth.into_bitboard()) >> 7,
Self::SouthWest => (board - Rank::First.into_bitboard()) >> 9,
Self::SouthEast => (board - Rank::First.into_bitboard()) << 7,
Self::NorthEast => (board - Rank::Eighth.into_bitboard()) << 9,
Self::NorthNorthWest => {
(board - Rank::Eighth.into_bitboard() - Rank::Seventh.into_bitboard()) >> 6
}
Self::NorthWestWest => (board - Rank::Eighth.into_bitboard()) >> 15,
Self::SouthWestWest => (board - Rank::First.into_bitboard()) >> 17,
Self::SouthSouthWest => {
(board - Rank::First.into_bitboard() - Rank::Second.into_bitboard()) >> 10
}
Self::SouthSouthEast => {
(board - Rank::First.into_bitboard() - Rank::Second.into_bitboard()) << 6
}
Self::SouthEastEast => (board - Rank::First.into_bitboard()) << 15,
Self::NorthEastEast => (board - Rank::Eighth.into_bitboard()) << 17,
Self::NorthNorthEast => {
(board - Rank::Eighth.into_bitboard() - Rank::Seventh.into_bitboard()) << 10
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::board::Square;
#[test]
fn north() {
assert_eq!(
Direction::North.move_board(Square::A1.into_bitboard()),
Square::A2.into_bitboard()
);
assert_eq!(
Direction::North.move_board(Square::A2.into_bitboard()),
Square::A3.into_bitboard()
);
assert_eq!(
Direction::North.move_board(Square::A7.into_bitboard()),
Square::A8.into_bitboard()
);
assert_eq!(
Direction::North.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY
);
}
#[test]
fn west() {
assert_eq!(
Direction::West.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::West.move_board(Square::B1.into_bitboard()),
Square::A1.into_bitboard()
);
assert_eq!(
Direction::West.move_board(Square::G1.into_bitboard()),
Square::F1.into_bitboard()
);
assert_eq!(
Direction::West.move_board(Square::H1.into_bitboard()),
Square::G1.into_bitboard()
);
}
#[test]
fn south() {
assert_eq!(
Direction::South.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::South.move_board(Square::A2.into_bitboard()),
Square::A1.into_bitboard()
);
assert_eq!(
Direction::South.move_board(Square::A7.into_bitboard()),
Square::A6.into_bitboard()
);
assert_eq!(
Direction::South.move_board(Square::A8.into_bitboard()),
Square::A7.into_bitboard()
);
}
#[test]
fn east() {
assert_eq!(
Direction::East.move_board(Square::A1.into_bitboard()),
Square::B1.into_bitboard()
);
assert_eq!(
Direction::East.move_board(Square::B1.into_bitboard()),
Square::C1.into_bitboard()
);
assert_eq!(
Direction::East.move_board(Square::G1.into_bitboard()),
Square::H1.into_bitboard()
);
assert_eq!(
Direction::East.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY
);
}
#[test]
fn north_west() {
assert_eq!(
Direction::NorthWest.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::NorthWest.move_board(Square::B1.into_bitboard()),
Square::A2.into_bitboard()
);
assert_eq!(
Direction::NorthWest.move_board(Square::H1.into_bitboard()),
Square::G2.into_bitboard()
);
assert_eq!(
Direction::NorthWest.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::NorthWest.move_board(Square::B8.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::NorthWest.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY
);
}
#[test]
fn south_west() {
assert_eq!(
Direction::SouthWest.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::SouthWest.move_board(Square::B1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::SouthWest.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::SouthWest.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::SouthWest.move_board(Square::B8.into_bitboard()),
Square::A7.into_bitboard()
);
assert_eq!(
Direction::SouthWest.move_board(Square::H8.into_bitboard()),
Square::G7.into_bitboard()
);
}
#[test]
fn south_east() {
assert_eq!(
Direction::SouthEast.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::SouthEast.move_board(Square::B1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::SouthEast.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::SouthEast.move_board(Square::A8.into_bitboard()),
Square::B7.into_bitboard()
);
assert_eq!(
Direction::SouthEast.move_board(Square::B8.into_bitboard()),
Square::C7.into_bitboard()
);
assert_eq!(
Direction::SouthEast.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY
);
}
#[test]
fn north_east() {
assert_eq!(
Direction::NorthEast.move_board(Square::A1.into_bitboard()),
Square::B2.into_bitboard()
);
assert_eq!(
Direction::NorthEast.move_board(Square::B1.into_bitboard()),
Square::C2.into_bitboard()
);
assert_eq!(
Direction::NorthEast.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::NorthEast.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::NorthEast.move_board(Square::B8.into_bitboard()),
Bitboard::EMPTY
);
assert_eq!(
Direction::NorthEast.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY
);
}
#[test]
fn north_north_west() {
assert_eq!(
Direction::NorthNorthWest.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthNorthWest.move_board(Square::B2.into_bitboard()),
Square::A4.into_bitboard()
);
assert_eq!(
Direction::NorthNorthWest.move_board(Square::H1.into_bitboard()),
Square::G3.into_bitboard()
);
assert_eq!(
Direction::NorthNorthWest.move_board(Square::G2.into_bitboard()),
Square::F4.into_bitboard()
);
assert_eq!(
Direction::NorthNorthWest.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthNorthWest.move_board(Square::B7.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthNorthWest.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthNorthWest.move_board(Square::G7.into_bitboard()),
Bitboard::EMPTY,
);
}
#[test]
fn north_west_west() {
assert_eq!(
Direction::NorthWestWest.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthWestWest.move_board(Square::B2.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthWestWest.move_board(Square::H1.into_bitboard()),
Square::F2.into_bitboard()
);
assert_eq!(
Direction::NorthWestWest.move_board(Square::G2.into_bitboard()),
Square::E3.into_bitboard()
);
assert_eq!(
Direction::NorthWestWest.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthWestWest.move_board(Square::B7.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthWestWest.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthWestWest.move_board(Square::G7.into_bitboard()),
Square::E8.into_bitboard()
);
}
#[test]
fn south_west_west() {
assert_eq!(
Direction::SouthWestWest.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthWestWest.move_board(Square::B2.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthWestWest.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthWestWest.move_board(Square::G2.into_bitboard()),
Square::E1.into_bitboard()
);
assert_eq!(
Direction::SouthWestWest.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthWestWest.move_board(Square::B7.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthWestWest.move_board(Square::H8.into_bitboard()),
Square::F7.into_bitboard()
);
assert_eq!(
Direction::SouthWestWest.move_board(Square::G7.into_bitboard()),
Square::E6.into_bitboard()
);
}
#[test]
fn south_south_west() {
assert_eq!(
Direction::SouthSouthWest.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthWest.move_board(Square::B2.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthWest.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthWest.move_board(Square::G2.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthWest.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthWest.move_board(Square::B7.into_bitboard()),
Square::A5.into_bitboard()
);
assert_eq!(
Direction::SouthSouthWest.move_board(Square::H8.into_bitboard()),
Square::G6.into_bitboard()
);
assert_eq!(
Direction::SouthSouthWest.move_board(Square::G7.into_bitboard()),
Square::F5.into_bitboard()
);
}
#[test]
fn south_south_east() {
assert_eq!(
Direction::SouthSouthEast.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthEast.move_board(Square::B2.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthEast.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthEast.move_board(Square::G2.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthEast.move_board(Square::A8.into_bitboard()),
Square::B6.into_bitboard()
);
assert_eq!(
Direction::SouthSouthEast.move_board(Square::B7.into_bitboard()),
Square::C5.into_bitboard()
);
assert_eq!(
Direction::SouthSouthEast.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthSouthEast.move_board(Square::G7.into_bitboard()),
Square::H5.into_bitboard()
);
}
#[test]
fn south_east_east() {
assert_eq!(
Direction::SouthEastEast.move_board(Square::A1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthEastEast.move_board(Square::B2.into_bitboard()),
Square::D1.into_bitboard()
);
assert_eq!(
Direction::SouthEastEast.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthEastEast.move_board(Square::G2.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthEastEast.move_board(Square::A8.into_bitboard()),
Square::C7.into_bitboard()
);
assert_eq!(
Direction::SouthEastEast.move_board(Square::B7.into_bitboard()),
Square::D6.into_bitboard()
);
assert_eq!(
Direction::SouthEastEast.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::SouthEastEast.move_board(Square::G7.into_bitboard()),
Bitboard::EMPTY,
);
}
#[test]
fn north_east_east() {
assert_eq!(
Direction::NorthEastEast.move_board(Square::A1.into_bitboard()),
Square::C2.into_bitboard()
);
assert_eq!(
Direction::NorthEastEast.move_board(Square::B2.into_bitboard()),
Square::D3.into_bitboard()
);
assert_eq!(
Direction::NorthEastEast.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthEastEast.move_board(Square::G2.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthEastEast.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthEastEast.move_board(Square::B7.into_bitboard()),
Square::D8.into_bitboard()
);
assert_eq!(
Direction::NorthEastEast.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthEastEast.move_board(Square::G7.into_bitboard()),
Bitboard::EMPTY,
);
}
#[test]
fn north_north_east() {
assert_eq!(
Direction::NorthNorthEast.move_board(Square::A1.into_bitboard()),
Square::B3.into_bitboard()
);
assert_eq!(
Direction::NorthNorthEast.move_board(Square::B2.into_bitboard()),
Square::C4.into_bitboard()
);
assert_eq!(
Direction::NorthNorthEast.move_board(Square::H1.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthNorthEast.move_board(Square::G2.into_bitboard()),
Square::H4.into_bitboard()
);
assert_eq!(
Direction::NorthNorthEast.move_board(Square::A8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthNorthEast.move_board(Square::B7.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthNorthEast.move_board(Square::H8.into_bitboard()),
Bitboard::EMPTY,
);
assert_eq!(
Direction::NorthNorthEast.move_board(Square::G7.into_bitboard()),
Bitboard::EMPTY,
);
}
}