1use bitvec::slice::BitSlice;
2
3use crate::DimensionMismatch;
4
5pub trait BitBoard: Sized {
6 fn n_rows(&self) -> usize;
8
9 fn n_cols(&self) -> usize;
11
12 fn board_mut(&mut self) -> &mut BitSlice;
14
15 fn board(&self) -> &BitSlice;
17
18 fn index_of(&self, row: usize, col: usize) -> usize {
20 assert!(
21 row <= (self.n_rows() - 1),
22 "row cannot be greater than n_rows"
23 );
24 assert!(
25 col <= (self.n_cols() - 1),
26 "col cannot be greater than n_cols"
27 );
28 (row * self.n_cols()) + col
29 }
30
31 fn row_col_of(&self, index: usize) -> (usize, usize) {
33 let row = index / self.n_cols();
34 let col = index % self.n_cols();
35 (row, col)
36 }
37
38 fn fill(&mut self, value: bool) {
40 self.board_mut().fill(value);
41 }
42
43 fn or(&self, other: &impl BitBoard) -> Result<Self, DimensionMismatch>;
44 fn and(&self, other: &impl BitBoard) -> Result<Self, DimensionMismatch>;
45
46 fn set(&mut self, row: usize, col: usize, value: bool) {
48 let new_ind = self.index_of(row, col);
49 self.board_mut().set(new_ind, value);
50 }
51 fn set_col(&mut self, col: usize, value: bool) {
53 for r_idx in 0..self.n_rows() {
55 let idx = (r_idx * self.n_cols()) + col;
57 self.board_mut().set(idx, value);
58 }
59 }
60
61 fn set_row(&mut self, row: usize, value: bool) {
63 for cidx in 0..self.n_cols() {
65 let idx = (row * self.n_cols()) + cidx;
67 self.board_mut().set(idx, value);
68 }
69 }
70
71 fn set_cardinal_neighbors(&mut self, row: usize, col: usize, value: bool) {
74 if row > 0 {
76 self.set(row - 1, col, value);
77 }
78
79 if row < self.n_rows() - 1 {
81 self.set(row + 1, col, value);
82 }
83
84 if col > 0 {
86 self.set(row, col - 1, value);
87 }
88
89 if col < self.n_cols() - 1 {
91 self.set(row, col + 1, value);
92 }
93 }
94
95 fn set_diagonals(&mut self, row: usize, col: usize, value: bool) {
98 if row > 0 && col > 0 {
100 self.set(row - 1, col - 1, value);
101 }
102
103 if row > 0 && col < self.n_cols() - 1 {
105 self.set(row - 1, col + 1, value);
106 }
107
108 if row < self.n_rows() - 1 && col > 0 {
110 self.set(row + 1, col - 1, value);
111 }
112
113 if row < self.n_rows() - 1 && col < self.n_cols() - 1 {
115 self.set(row + 1, col + 1, value);
116 }
117 }
118
119 fn set_all_neighbors(&mut self, row: usize, col: usize, value: bool) {
122 self.set_cardinal_neighbors(row, col, value);
123 self.set_diagonals(row, col, value);
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use crate::{bitboard::BitBoard, bitboardstatic::BitBoardStatic};
130 use rstest::rstest;
131
132 #[rstest]
133 #[case(0, 0, 0)]
134 #[case(1, 0, 1)]
135 #[case(2, 1, 0)]
136 #[case(3, 1, 1)]
137 fn index_of_and_row_col_of(#[case] index: usize, #[case] row: usize, #[case] col: usize) {
138 let bb = BitBoardStatic::<1>::new(2, 2);
139 assert_eq!(bb.index_of(row, col), index);
140 assert_eq!(bb.row_col_of(index), (row, col));
141 }
142
143 #[rstest]
144 #[case(0, 0, 0)]
145 #[case(1, 0, 1)]
146 #[case(2, 0, 2)]
147 #[case(3, 1, 0)]
148 #[case(4, 1, 1)]
149 #[case(5, 1, 2)]
150 #[case(6, 2, 0)]
151 #[case(7, 2, 1)]
152 #[case(8, 2, 2)]
153 fn index_of_and_row_col_of_3x3(#[case] index: usize, #[case] row: usize, #[case] col: usize) {
154 let bb = BitBoardStatic::<1>::new(3, 3);
155 assert_eq!(bb.index_of(row, col), index);
156 assert_eq!(bb.row_col_of(index), (row, col));
157 }
158
159 #[test]
160 fn index_of_and_row_col_of_2x10() {
161 let bb = BitBoardStatic::<1>::new(2, 10);
162 for index in 0..20 {
163 let (row, col) = bb.row_col_of(index);
164 assert_eq!(bb.index_of(row, col), index);
165 }
166 }
167}