Skip to main content

atomic_movegen/
bitboard.rs

1use crate::attacks::{BETWEEN_BB, LINE_BB};
2use crate::types::*;
3
4/// Bitboard with all squares on file A set.
5pub const FILE_ABB: Bitboard = Bitboard(0x0101010101010101);
6pub const FILE_BBB: Bitboard = Bitboard(FILE_ABB.0 << 1);
7pub const FILE_CBB: Bitboard = Bitboard(FILE_ABB.0 << 2);
8pub const FILE_DBB: Bitboard = Bitboard(FILE_ABB.0 << 3);
9pub const FILE_EBB: Bitboard = Bitboard(FILE_ABB.0 << 4);
10pub const FILE_FBB: Bitboard = Bitboard(FILE_ABB.0 << 5);
11pub const FILE_GBB: Bitboard = Bitboard(FILE_ABB.0 << 6);
12pub const FILE_HBB: Bitboard = Bitboard(FILE_ABB.0 << 7);
13
14pub const RANK_1BB: Bitboard = Bitboard(0xFF);
15pub const RANK_2BB: Bitboard = Bitboard(RANK_1BB.0 << FILE_NB);
16pub const RANK_3BB: Bitboard = Bitboard(RANK_1BB.0 << (FILE_NB * 2));
17pub const RANK_4BB: Bitboard = Bitboard(RANK_1BB.0 << (FILE_NB * 3));
18pub const RANK_5BB: Bitboard = Bitboard(RANK_1BB.0 << (FILE_NB * 4));
19pub const RANK_6BB: Bitboard = Bitboard(RANK_1BB.0 << (FILE_NB * 5));
20pub const RANK_7BB: Bitboard = Bitboard(RANK_1BB.0 << (FILE_NB * 6));
21pub const RANK_8BB: Bitboard = Bitboard(RANK_1BB.0 << (FILE_NB * 7));
22
23/// Bitboard with all 64 squares set.
24pub const ALL_SQUARES: Bitboard = Bitboard(!0u64);
25
26/// Return the bitboard of squares strictly between `s1` and `s2`.
27///
28/// Returns [`Bitboard::EMPTY`] if the squares are not on the same rank,
29/// file, or diagonal.
30#[inline(always)]
31pub fn between_bb(s1: Square, s2: Square) -> Bitboard {
32    BETWEEN_BB[s1 as usize][s2 as usize]
33}
34
35/// Return the bitboard of all squares on the same rank, file, or diagonal
36/// as `s1` and `s2` (including both endpoints).
37///
38/// Returns [`Bitboard::EMPTY`] if the squares are not aligned.
39#[inline(always)]
40pub fn line_bb(s1: Square, s2: Square) -> Bitboard {
41    LINE_BB[s1 as usize][s2 as usize]
42}
43
44#[cfg(test)]
45pub fn aligned(s1: Square, s2: Square, s3: Square) -> bool {
46    line_bb(s1, s2) & Bitboard::square_bb(s3) != Bitboard::EMPTY
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_file_rank_constants() {
55        assert_eq!(FILE_ABB.0, 0x0101010101010101);
56        assert_eq!(FILE_HBB.0, 0x8080808080808080);
57        assert_eq!(RANK_1BB.0, 0xFF);
58        assert_eq!(RANK_8BB.0, 0xFF00000000000000);
59    }
60
61    #[test]
62    fn test_between_bb() {
63        let between = between_bb(Square::C1, Square::F4);
64        assert!(between & Bitboard::square_bb(Square::D2) != Bitboard::EMPTY);
65        assert!(between & Bitboard::square_bb(Square::E3) != Bitboard::EMPTY);
66        // Non-aligned squares return empty
67        assert!((between_bb(Square::A1, Square::B3)).is_empty());
68        // Same-square returns empty
69        assert!((between_bb(Square::D4, Square::D4)).is_empty());
70    }
71
72    #[test]
73    fn test_line_bb() {
74        let line = line_bb(Square::A1, Square::H8);
75        assert!(line & Bitboard::square_bb(Square::B2) != Bitboard::EMPTY);
76        assert!(line & Bitboard::square_bb(Square::C3) != Bitboard::EMPTY);
77        // Line includes both endpoints
78        assert!(line & Bitboard::square_bb(Square::A1) != Bitboard::EMPTY);
79        assert!(line & Bitboard::square_bb(Square::H8) != Bitboard::EMPTY);
80    }
81
82    #[test]
83    fn test_aligned() {
84        assert!(aligned(Square::A1, Square::C3, Square::E5));
85        assert!(aligned(Square::A1, Square::C3, Square::E5));
86    }
87}