use crate::engine::common::{File, Rank, Square};
pub type Bitboard = u64;
pub type Direction = i8;
pub const EMPTY: Bitboard = 0;
pub const WHITE_PAWNS: Bitboard = 0b11111111 << 8;
pub const WHITE_ROOKS: Bitboard = 0b10000001;
pub const WHITE_KNIGHTS: Bitboard = 0b01000010;
pub const WHITE_BISHOPS: Bitboard = 0b00100100;
pub const WHITE_QUEENS: Bitboard = 0b00001000;
pub const WHITE_KING: Bitboard = 0b00010000;
pub const BLACK_PAWNS: Bitboard = 0b11111111 << (8 * 6);
pub const BLACK_ROOKS: Bitboard = 0b10000001 << (8 * 7);
pub const BLACK_KNIGHTS: Bitboard = 0b01000010 << (8 * 7);
pub const BLACK_BISHOPS: Bitboard = 0b00100100 << (8 * 7);
pub const BLACK_QUEENS: Bitboard = 0b00001000 << (8 * 7);
pub const BLACK_KING: Bitboard = 0b00010000 << (8 * 7);
pub const A_FILE: Bitboard = 0b0000000100000001000000010000000100000001000000010000000100000001;
pub const B_FILE: Bitboard = 0b0000001000000010000000100000001000000010000000100000001000000010;
pub const C_FILE: Bitboard = 0b0000010000000100000001000000010000000100000001000000010000000100;
pub const D_FILE: Bitboard = 0b0000100000001000000010000000100000001000000010000000100000001000;
pub const E_FILE: Bitboard = 0b0001000000010000000100000001000000010000000100000001000000010000;
pub const F_FILE: Bitboard = 0b0010000000100000001000000010000000100000001000000010000000100000;
pub const G_FILE: Bitboard = 0b0100000001000000010000000100000001000000010000000100000001000000;
pub const H_FILE: Bitboard = 0b1000000010000000100000001000000010000000100000001000000010000000;
pub const RANK_1: Bitboard = 0b11111111;
pub const RANK_2: Bitboard = 0b11111111 << 8;
pub const RANK_3: Bitboard = 0b11111111 << (8 * 2);
pub const RANK_4: Bitboard = 0b11111111 << (8 * 3);
pub const RANK_5: Bitboard = 0b11111111 << (8 * 4);
pub const RANK_6: Bitboard = 0b11111111 << (8 * 5);
pub const RANK_7: Bitboard = 0b11111111 << (8 * 6);
pub const RANK_8: Bitboard = 0b11111111 << (8 * 7);
pub const CASTLING_WHITE_KING_SQUARE: Bitboard = 0b01000000;
pub const CASTLING_WHITE_QUEEN_SQUARE: Bitboard = 0b00000100;
pub const CASTLING_BLACK_KING_SQUARE: Bitboard = 0b01000000 << (8 * 7);
pub const CASTLING_BLACK_QUEEN_SQUARE: Bitboard = 0b00000100 << (8 * 7);
pub const CASTLING_WHITE_KING_JUMP_SQUARES: Bitboard = 0b01100000;
pub const CASTLING_WHITE_QUEEN_JUMP_SQUARES: Bitboard = 0b00001100;
pub const CASTLING_BLACK_KING_JUMP_SQUARES: Bitboard = 0b01100000 << (8 * 7);
pub const CASTLING_BLACK_QUEEN_JUMP_SQUARES: Bitboard = 0b00001100 << (8 * 7);
pub const CASTLING_WHITE_KING_OCCUPIABLE_SQUARES: Bitboard = 0b01100000;
pub const CASTLING_WHITE_QUEEN_OCCUPIABLE_SQUARES: Bitboard = 0b00001110;
pub const CASTLING_BLACK_KING_OCCUPIABLE_SQUARES: Bitboard = 0b01100000 << (8 * 7);
pub const CASTLING_BLACK_QUEEN_OCCUPIABLE_SQUARES: Bitboard = 0b00001110 << (8 * 7);
pub const NORTH: Direction = 8;
pub const SOUTH: Direction = -8;
pub const EAST: Direction = 1;
pub const WEST: Direction = -1;
pub const NORTH_EAST: Direction = 9;
pub const NORTH_WEST: Direction = 7;
pub const SOUTH_EAST: Direction = -7;
pub const SOUTH_WEST: Direction = -9;
pub const DIRECTIONS: [Direction; 8] = [
NORTH, SOUTH, EAST, WEST, NORTH_EAST, NORTH_WEST, SOUTH_EAST, SOUTH_WEST,
];
pub fn set_bit(bitboard: Bitboard, file: File, rank: Rank) -> Bitboard {
bitboard | (0b1 << (rank.index() * 8 + file.index()))
}
pub fn get_single_piece_bitboard(bitboard: Bitboard, square: Square) -> Bitboard {
let bit = 0b1 << (square.rank.index() * 8 + square.file.index());
bitboard & bit
}
pub fn occupied_squares(bitboard: Bitboard) -> Vec<Square> {
if bitboard == EMPTY {
return Vec::with_capacity(0);
}
let mut squares = Vec::with_capacity(32);
let mut bb = bitboard;
let mut index = 0;
while bb != 0 {
if (bb & 1) != 0 {
let rank = Rank::from_index(index / 8 + 1);
let file = File::from_index(index % 8 + 1);
squares.push(Square { file, rank });
}
bb >>= 1;
index += 1;
}
squares
}
pub fn to_square(bitboard: Bitboard) -> Square {
let rank = Rank::from_index((bitboard.trailing_zeros() / 8) as i8);
let file = File::from_index((bitboard.trailing_zeros() % 8) as i8);
Square { file, rank }
}
pub fn popcnt(bitboard: Bitboard) -> u32 {
bitboard.count_ones()
}
pub fn is_empty(bitboard: Bitboard) -> bool {
bitboard == EMPTY
}
pub fn is_occupied(bitboard: Bitboard, square: Square) -> bool {
!is_empty(bitboard & square.bitboard())
}
pub fn is_diagonal(direction: Direction) -> bool {
direction == NORTH_EAST
|| direction == NORTH_WEST
|| direction == SOUTH_EAST
|| direction == SOUTH_WEST
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_set_bit() {
let bitboard = 0;
let expected = 0b1 << (8 * 4 + 3);
let result = set_bit(bitboard, File::D, Rank::Five);
assert_eq!(result, expected);
}
}