[board] Get king moves from the bitboard library
This commit is contained in:
		
							parent
							
								
									b95c34f51e
								
							
						
					
					
						commit
						769886086c
					
				
					 3 changed files with 172 additions and 50 deletions
				
			
		| 
						 | 
					@ -9,6 +9,14 @@ use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
 | 
				
			||||||
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
 | 
					#[derive(Clone, Copy, Eq, Hash, PartialEq)]
 | 
				
			||||||
pub(crate) struct BitBoard(pub(super) u64);
 | 
					pub(crate) struct BitBoard(pub(super) u64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macro_rules! moves_getter {
 | 
				
			||||||
 | 
					    ($getter_name:ident) => {
 | 
				
			||||||
 | 
					        pub fn $getter_name(sq: Square) -> BitBoard {
 | 
				
			||||||
 | 
					            library().$getter_name(sq)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl BitBoard {
 | 
					impl BitBoard {
 | 
				
			||||||
    pub const fn empty() -> BitBoard {
 | 
					    pub const fn empty() -> BitBoard {
 | 
				
			||||||
        BitBoard(0)
 | 
					        BitBoard(0)
 | 
				
			||||||
| 
						 | 
					@ -28,9 +36,11 @@ impl BitBoard {
 | 
				
			||||||
        FILES[file]
 | 
					        FILES[file]
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn knight_moves(sq: Square) -> BitBoard {
 | 
					    moves_getter!(knight_moves);
 | 
				
			||||||
        library().knight_moves(sq)
 | 
					    moves_getter!(bishop_moves);
 | 
				
			||||||
    }
 | 
					    moves_getter!(rook_moves);
 | 
				
			||||||
 | 
					    moves_getter!(queen_moves);
 | 
				
			||||||
 | 
					    moves_getter!(king_moves);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn from_square(sq: Square) -> BitBoard {
 | 
					    pub fn from_square(sq: Square) -> BitBoard {
 | 
				
			||||||
        BitBoard(1 << sq.index())
 | 
					        BitBoard(1 << sq.index())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,83 +30,195 @@ static mut MOVE_LIBRARY: MoveLibrary = MoveLibrary::new();
 | 
				
			||||||
static MOVE_LIBRARY_INIT: Once = Once::new();
 | 
					static MOVE_LIBRARY_INIT: Once = Once::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(super) fn library() -> &'static MoveLibrary {
 | 
					pub(super) fn library() -> &'static MoveLibrary {
 | 
				
			||||||
 | 
					    static MOVE_LIBRARY_INIT: Once = Once::new();
 | 
				
			||||||
 | 
					    static mut MOVE_LIBRARY: MoveLibrary = MoveLibrary::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unsafe {
 | 
					    unsafe {
 | 
				
			||||||
        MOVE_LIBRARY_INIT.call_once(|| {
 | 
					        MOVE_LIBRARY_INIT.call_once(|| {
 | 
				
			||||||
            MOVE_LIBRARY.initialize_if_needed();
 | 
					            MOVE_LIBRARY.init();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        &MOVE_LIBRARY
 | 
					        &MOVE_LIBRARY
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Copy, Debug)]
 | 
				
			||||||
 | 
					struct OrthogonalRays {
 | 
				
			||||||
 | 
					    positive_rank: BitBoard,
 | 
				
			||||||
 | 
					    positive_file: BitBoard,
 | 
				
			||||||
 | 
					    negative_rank: BitBoard,
 | 
				
			||||||
 | 
					    negative_file: BitBoard,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl OrthogonalRays {
 | 
				
			||||||
 | 
					    const fn new() -> OrthogonalRays {
 | 
				
			||||||
 | 
					        OrthogonalRays {
 | 
				
			||||||
 | 
					            positive_rank: BitBoard::empty(),
 | 
				
			||||||
 | 
					            positive_file: BitBoard::empty(),
 | 
				
			||||||
 | 
					            negative_rank: BitBoard::empty(),
 | 
				
			||||||
 | 
					            negative_file: BitBoard::empty(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Copy, Debug)]
 | 
				
			||||||
 | 
					struct DiagonalRays {
 | 
				
			||||||
 | 
					    positive_diagonal: BitBoard,
 | 
				
			||||||
 | 
					    positive_antidiagonal: BitBoard,
 | 
				
			||||||
 | 
					    negative_diagonal: BitBoard,
 | 
				
			||||||
 | 
					    negative_antidiagonal: BitBoard,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl DiagonalRays {
 | 
				
			||||||
 | 
					    const fn new() -> DiagonalRays {
 | 
				
			||||||
 | 
					        DiagonalRays {
 | 
				
			||||||
 | 
					            positive_diagonal: BitBoard::empty(),
 | 
				
			||||||
 | 
					            positive_antidiagonal: BitBoard::empty(),
 | 
				
			||||||
 | 
					            negative_diagonal: BitBoard::empty(),
 | 
				
			||||||
 | 
					            negative_antidiagonal: BitBoard::empty(),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macro_rules! library_getter {
 | 
				
			||||||
 | 
					    ($name:ident) => {
 | 
				
			||||||
 | 
					        pub(super) fn $name(&self, sq: Square) -> BitBoard {
 | 
				
			||||||
 | 
					            self.$name[sq.index() as usize]
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub(super) struct MoveLibrary {
 | 
					pub(super) struct MoveLibrary {
 | 
				
			||||||
    is_initialized: bool,
 | 
					    // Rays
 | 
				
			||||||
 | 
					    diagonal_rays: [DiagonalRays; 64],
 | 
				
			||||||
 | 
					    orthogonal_rays: [OrthogonalRays; 64],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Piecewise move tables
 | 
					    // Piecewise move tables
 | 
				
			||||||
    king_moves: [BitBoard; 64],
 | 
					 | 
				
			||||||
    knight_moves: [BitBoard; 64],
 | 
					    knight_moves: [BitBoard; 64],
 | 
				
			||||||
 | 
					    bishop_moves: [BitBoard; 64],
 | 
				
			||||||
 | 
					    rook_moves: [BitBoard; 64],
 | 
				
			||||||
 | 
					    queen_moves: [BitBoard; 64],
 | 
				
			||||||
 | 
					    king_moves: [BitBoard; 64],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl MoveLibrary {
 | 
					impl MoveLibrary {
 | 
				
			||||||
    const fn new() -> MoveLibrary {
 | 
					    const fn new() -> MoveLibrary {
 | 
				
			||||||
        MoveLibrary {
 | 
					        MoveLibrary {
 | 
				
			||||||
            is_initialized: false,
 | 
					            diagonal_rays: [DiagonalRays::new(); 64],
 | 
				
			||||||
            king_moves: [BitBoard::empty(); 64],
 | 
					            orthogonal_rays: [OrthogonalRays::new(); 64],
 | 
				
			||||||
            knight_moves: [BitBoard::empty(); 64],
 | 
					            knight_moves: [BitBoard::empty(); 64],
 | 
				
			||||||
 | 
					            bishop_moves: [BitBoard::empty(); 64],
 | 
				
			||||||
 | 
					            rook_moves: [BitBoard::empty(); 64],
 | 
				
			||||||
 | 
					            queen_moves: [BitBoard::empty(); 64],
 | 
				
			||||||
 | 
					            king_moves: [BitBoard::empty(); 64],
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn initialize_if_needed(&mut self) {
 | 
					    fn init(&mut self) {
 | 
				
			||||||
        if self.is_initialized {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.do_initialization();
 | 
					 | 
				
			||||||
        self.is_initialized = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn do_initialization(&mut self) {
 | 
					 | 
				
			||||||
        self.initialize_king_moves();
 | 
					 | 
				
			||||||
        self.initialize_knight_moves();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn initialize_king_moves(&mut self) {
 | 
					 | 
				
			||||||
        for i in 0..64 {
 | 
					        for i in 0..64 {
 | 
				
			||||||
            let king = BitBoard::new(1 << i);
 | 
					            self.init_orthogonal_rays(i);
 | 
				
			||||||
            let mut attacks = king.shift_east_one() | king.shift_west_one();
 | 
					            self.init_diagonal_rays(i);
 | 
				
			||||||
 | 
					            self.init_knight_moves(i as usize);
 | 
				
			||||||
            let king = king | attacks;
 | 
					            self.init_bishop_moves(i as usize);
 | 
				
			||||||
            attacks |= king.shift_north_one() | king.shift_south_one();
 | 
					            self.init_rook_moves(i as usize);
 | 
				
			||||||
 | 
					            self.init_queen_moves(i as usize);
 | 
				
			||||||
            self.king_moves[i] = attacks;
 | 
					            self.init_king_moves(i as usize);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init_orthogonal_rays(&mut self, idx: u8) {
 | 
				
			||||||
 | 
					        let sq = Square::from_index_unsafe(idx);
 | 
				
			||||||
 | 
					        let sq_bb = BitBoard::from_square(sq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let ortho_rays = &mut self.orthogonal_rays[idx as usize];
 | 
				
			||||||
 | 
					        ortho_rays.positive_file = Self::generate_ray(sq_bb, BitBoard::shift_north_one);
 | 
				
			||||||
 | 
					        ortho_rays.negative_file = Self::generate_ray(sq_bb, BitBoard::shift_south_one);
 | 
				
			||||||
 | 
					        ortho_rays.positive_rank = Self::generate_ray(sq_bb, BitBoard::shift_east_one);
 | 
				
			||||||
 | 
					        ortho_rays.negative_rank = Self::generate_ray(sq_bb, BitBoard::shift_west_one);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init_diagonal_rays(&mut self, idx: u8) {
 | 
				
			||||||
 | 
					        let sq = Square::from_index_unsafe(idx);
 | 
				
			||||||
 | 
					        let sq_bb = BitBoard::from_square(sq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let diag_rays = &mut self.diagonal_rays[idx as usize];
 | 
				
			||||||
 | 
					        diag_rays.positive_diagonal = Self::generate_ray(sq_bb, BitBoard::shift_north_east_one);
 | 
				
			||||||
 | 
					        diag_rays.positive_antidiagonal = Self::generate_ray(sq_bb, BitBoard::shift_north_west_one);
 | 
				
			||||||
 | 
					        diag_rays.negative_diagonal = Self::generate_ray(sq_bb, BitBoard::shift_south_west_one);
 | 
				
			||||||
 | 
					        diag_rays.negative_antidiagonal = Self::generate_ray(sq_bb, BitBoard::shift_south_east_one);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init_king_moves(&mut self, idx: usize) {
 | 
				
			||||||
 | 
					        let king = BitBoard::new(1 << idx);
 | 
				
			||||||
 | 
					        let mut attacks = king.shift_east_one() | king.shift_west_one();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let king = king | attacks;
 | 
				
			||||||
 | 
					        attacks |= king.shift_north_one() | king.shift_south_one();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.king_moves[idx] = attacks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Calculate bitboards representing knight moves from each square on the
 | 
					    /// Calculate bitboards representing knight moves from each square on the
 | 
				
			||||||
    /// board. The algorithm is described on the [Chess Programming Wiki][cpw].
 | 
					    /// board. The algorithm is described on the [Chess Programming Wiki][cpw].
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// [cpw]: https://www.chessprogramming.org/Knight_Pattern
 | 
					    /// [cpw]: https://www.chessprogramming.org/Knight_Pattern
 | 
				
			||||||
    fn initialize_knight_moves(&mut self) {
 | 
					    fn init_knight_moves(&mut self, idx: usize) {
 | 
				
			||||||
        for i in 0..64 {
 | 
					        let knight = BitBoard::new(1 << idx);
 | 
				
			||||||
            let knight = BitBoard::new(1 << i);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let east = knight.shift_east_one();
 | 
					        let east = knight.shift_east_one();
 | 
				
			||||||
            let west = knight.shift_west_one();
 | 
					        let west = knight.shift_west_one();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let mut attacks = (east | west).shift_north(2);
 | 
					        let mut attacks = (east | west).shift_north(2);
 | 
				
			||||||
            attacks |= (east | west).shift_south(2);
 | 
					        attacks |= (east | west).shift_south(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let east = east.shift_east_one();
 | 
					        let east = east.shift_east_one();
 | 
				
			||||||
            let west = west.shift_west_one();
 | 
					        let west = west.shift_west_one();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            attacks |= (east | west).shift_north_one();
 | 
					        attacks |= (east | west).shift_north_one();
 | 
				
			||||||
            attacks |= (east | west).shift_south_one();
 | 
					        attacks |= (east | west).shift_south_one();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.knight_moves[i] = attacks;
 | 
					        self.knight_moves[idx] = attacks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init_bishop_moves(&mut self, idx: usize) {
 | 
				
			||||||
 | 
					        let diag_rays = self.diagonal_rays[idx];
 | 
				
			||||||
 | 
					        self.bishop_moves[idx] = diag_rays.positive_diagonal
 | 
				
			||||||
 | 
					            | diag_rays.negative_diagonal
 | 
				
			||||||
 | 
					            | diag_rays.positive_antidiagonal
 | 
				
			||||||
 | 
					            | diag_rays.negative_antidiagonal;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init_rook_moves(&mut self, idx: usize) {
 | 
				
			||||||
 | 
					        let ortho_rays = self.orthogonal_rays[idx];
 | 
				
			||||||
 | 
					        self.rook_moves[idx] = ortho_rays.positive_rank
 | 
				
			||||||
 | 
					            | ortho_rays.negative_rank
 | 
				
			||||||
 | 
					            | ortho_rays.positive_file
 | 
				
			||||||
 | 
					            | ortho_rays.negative_file;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn init_queen_moves(&mut self, idx: usize) {
 | 
				
			||||||
 | 
					        let rook_moves = self.rook_moves[idx];
 | 
				
			||||||
 | 
					        let bishop_moves = self.bishop_moves[idx];
 | 
				
			||||||
 | 
					        self.queen_moves[idx] = rook_moves | bishop_moves;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[inline]
 | 
				
			||||||
 | 
					    fn generate_ray(sq: BitBoard, shift: fn(&BitBoard) -> BitBoard) -> BitBoard {
 | 
				
			||||||
 | 
					        let mut ray = BitBoard::empty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut iter = shift(&sq);
 | 
				
			||||||
 | 
					        while !iter.is_empty() {
 | 
				
			||||||
 | 
					            ray |= iter;
 | 
				
			||||||
 | 
					            iter = shift(&iter);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ray
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub(super) fn knight_moves(&self, sq: Square) -> BitBoard {
 | 
					    library_getter!(knight_moves);
 | 
				
			||||||
        self.knight_moves[sq.index() as usize]
 | 
					    library_getter!(bishop_moves);
 | 
				
			||||||
    }
 | 
					    library_getter!(rook_moves);
 | 
				
			||||||
 | 
					    library_getter!(queen_moves);
 | 
				
			||||||
 | 
					    library_getter!(king_moves);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,13 +87,13 @@ impl<'a> KingMoveGenerator<'a> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn generate_bitboards(&mut self) {
 | 
					    fn generate_bitboards(&mut self) {
 | 
				
			||||||
        let mut king = self
 | 
					        let king = self
 | 
				
			||||||
            .position
 | 
					            .position
 | 
				
			||||||
            .bitboard_for_piece(Piece::king(self.color))
 | 
					            .bitboard_for_piece(Piece::king(self.color))
 | 
				
			||||||
            .clone();
 | 
					            .occupied_squares()
 | 
				
			||||||
        let mut all_moves = king.shift_east_one() | king.shift_west_one();
 | 
					            .next()
 | 
				
			||||||
        king |= all_moves;
 | 
					            .unwrap();
 | 
				
			||||||
        all_moves |= king.shift_north_one() | king.shift_south_one();
 | 
					        let all_moves = BitBoard::king_moves(king);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let empty_squares = self.position.empty_squares();
 | 
					        let empty_squares = self.position.empty_squares();
 | 
				
			||||||
        let opposing_pieces = self.position.bitboard_for_color(self.color.other());
 | 
					        let opposing_pieces = self.position.bitboard_for_color(self.color.other());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue