shogiutil/board/
bitboard.rs1use crate::Square;
2use std::ops::{BitAnd, BitOr, BitXor};
3
4const BIT_BOARD_FULL: u128 =
5 0b_111111111_111111111_111111111_111111111_111111111_111111111_111111111_111111111_111111111;
6
7#[derive(Clone, Copy)]
8pub struct Bitboard(pub u128);
9
10impl BitAnd for Bitboard {
11 type Output = Bitboard;
12
13 fn bitand(self, rhs: Self) -> Self::Output {
14 Self(self.0 & rhs.0)
15 }
16}
17
18impl BitOr for Bitboard {
19 type Output = Bitboard;
20
21 fn bitor(self, rhs: Self) -> Self::Output {
22 Self(self.0 | rhs.0)
23 }
24}
25
26impl BitXor for Bitboard {
27 type Output = Bitboard;
28
29 fn bitxor(self, rhs: Self) -> Self::Output {
30 Self(self.0 ^ rhs.0)
31 }
32}
33
34impl Bitboard {
35 pub const fn empty() -> Self {
36 Self(0)
37 }
38 pub const fn full() -> Self {
39 Self(BIT_BOARD_FULL)
40 }
41
42 pub fn is_filled(&self, sq: &Square) -> bool {
43 let pos = sq_to_pos(sq);
44 self.0 & (1 << pos) != 0
45 }
46 pub fn fill(&mut self, sq: &Square) {
47 let pos = sq_to_pos(sq);
48 assert_eq!(self.0 & (1 << pos), 0);
49 self.0 ^= 1 << pos;
50 }
51 pub fn remove(&mut self, sq: &Square) {
52 let pos = sq_to_pos(sq);
53 assert_ne!(self.0 & (1 << pos), 0);
54 self.0 ^= 1 << pos;
55 }
56
57 pub fn rotate180(&self) -> Self {
58 let reversed = self.0.reverse_bits();
59 Bitboard(reversed >> 47)
60 }
61
62 pub fn iter(&self) -> impl Iterator<Item = u32> {
63 BitIterator(self.0)
64 }
65
66 pub fn file_count_ones(&self, file: u8) -> u32 {
67 let file_only = super::bit_file(file) & self.0;
68 file_only.count_ones()
69 }
70}
71
72struct BitIterator(u128);
73
74impl Iterator for BitIterator {
75 type Item = u32;
76
77 fn next(&mut self) -> Option<Self::Item> {
78 if self.0 == 0 {
79 None
80 } else {
81 let pos = self.0.trailing_zeros();
82 self.0 ^= 1 << pos;
83 Some(pos)
84 }
85 }
86}
87
88fn sq_to_pos(sq: &Square) -> u8 {
89 (sq.rank - 1) * 9 + 9 - sq.file
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_rotate180() {
98 let input: u128 =
99 0b_101001000100001000001000000100000001000000001000000000100000000001000000000001000;
100 let expected: u128 =
101 0b_000100000000000100000000001000000000100000000100000001000000100000100001000100101;
102 assert_eq!(expected, Bitboard(input).rotate180().0);
103 assert_eq!(input, Bitboard(input).rotate180().rotate180().0);
104 }
105
106 #[test]
107 fn test_bit_iterator() {
108 let v = Bitboard(0b1000100101).iter().collect::<Vec<_>>();
109 assert_eq!(v, [0, 2, 5, 9]);
110 }
111
112 #[test]
113 fn test_full_bit() {
114 let full = Bitboard::full();
115 assert_eq!(81, full.0.count_ones());
116 }
117}