1use std::ops::{BitAnd, BitOr};
2
3use thiserror::Error;
4
5pub const BLACK_SQUARES: BitBoard = BitBoard(0x5555555555555555);
7
8pub const WHITE_SQUARES: BitBoard = BitBoard(0xAAAAAAAAAAAAAAAA);
10
11pub const CORNER_SQUARES: BitBoard = BitBoard(0x8100000000000081);
13
14pub const LEFT_SQUARES: BitBoard = BitBoard(0x8080808080808080);
16
17pub const RIGHT_SQUARES: BitBoard = BitBoard(0x101010101010101);
19
20pub const LEFT_AND_RIGHT_SQUARES: BitBoard = BitBoard(0x8181818181818181);
22
23pub const TOP_SQUARES: BitBoard = BitBoard(0xFF00000000000000);
25
26pub const BOTTOM_SQUARES: BitBoard = BitBoard(0x00000000000000FF);
28
29pub const TOP_AND_BOTTOM_SQUARES: BitBoard = BitBoard(0xFF000000000000FF);
31
32#[derive(Copy, Clone, Debug)]
35pub struct BitBoard(u64);
36
37impl BitBoard {
38 pub const fn new(value: u64) -> Self {
40 Self(value)
41 }
42
43 pub fn empty(&self) -> bool {
54 self.0 == 0
55 }
56
57 pub fn pieces(&self) -> Vec<MonoBitBoard> {
69 let mut result = Vec::new();
70 for index in 0..64 {
71 if (self.0 & (1 << index)) != 0 {
72 result.push(MonoBitBoard(1 << index))
73 }
74 }
75
76 result
77 }
78
79 pub fn contains(&self, bitboard: MonoBitBoard) -> bool {
91 !(*self & bitboard).empty()
92 }
93}
94
95impl BitAnd for BitBoard {
96 type Output = BitBoard;
97
98 fn bitand(self, rhs: Self) -> Self::Output {
99 BitBoard(self.0 & rhs.0)
100 }
101}
102
103impl BitOr for BitBoard {
104 type Output = BitBoard;
105
106 fn bitor(self, rhs: Self) -> Self::Output {
107 BitBoard(self.0 | rhs.0)
108 }
109}
110
111impl BitAnd<MonoBitBoard> for BitBoard {
112 type Output = BitBoard;
113
114 fn bitand(self, rhs: MonoBitBoard) -> Self::Output {
115 BitBoard(self.0 & rhs.0)
116 }
117}
118
119impl BitOr<MonoBitBoard> for BitBoard {
120 type Output = BitBoard;
121
122 fn bitor(self, rhs: MonoBitBoard) -> Self::Output {
123 BitBoard(self.0 | rhs.0)
124 }
125}
126
127#[derive(Debug, Error)]
128#[error("MonoBitBoard can only be constructed with a value that contains a single bit of 1.")]
129pub struct MonoBitBoardError;
130
131#[derive(Copy, Clone, Debug)]
134pub struct MonoBitBoard(u64);
135
136impl MonoBitBoard {
137 pub fn new(value: u64) -> Result<Self, MonoBitBoardError> {
139 let is_single_piece = value != 0 && (value & (value - 1)) == 0;
140 match is_single_piece {
141 true => {
142 let result = MonoBitBoard(value);
143 Ok(result)
144 }
145 false => Err(MonoBitBoardError)
146 }
147 }
148}
149
150impl TryFrom<BitBoard> for MonoBitBoard {
151 type Error = MonoBitBoardError;
152
153 fn try_from(value: BitBoard) -> Result<Self, Self::Error> {
155 MonoBitBoard::new(value.0)
156 }
157}
158
159macro_rules! impl_common {
160 ($x:ident, $y:ident) => {
161 impl PartialEq for $x {
162 fn eq(&self, other: &Self) -> bool { self.0 == other.0 }
163 }
164
165 impl PartialEq<u64> for $x {
166 fn eq(&self, other: &u64) -> bool { self.0 == *other }
167 }
168
169 impl PartialEq<$y> for $x {
170 fn eq(&self, other: &$y) -> bool {
171 self.0 == other.0
172 }
173 }
174 }
175}
176
177impl_common!(MonoBitBoard, BitBoard);
178impl_common!(BitBoard, MonoBitBoard);