bit_board/
bitboard.rs

1use bitvec::slice::BitSlice;
2
3use crate::DimensionMismatch;
4
5pub trait BitBoard: Sized {
6    /// Returns the number of rows in the board.
7    fn n_rows(&self) -> usize;
8
9    /// Returns the number of columns in the board.
10    fn n_cols(&self) -> usize;
11
12    /// Returns a mutable reference to the underlying bits.
13    fn board_mut(&mut self) -> &mut BitSlice;
14
15    /// Returns an immutable reference to the underlying bits.
16    fn board(&self) -> &BitSlice;
17
18    /// Get the index that we can use to directly access a certain spot on the board
19    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    /// Set all bits to the desired value.
32    fn fill(&mut self, value: bool) {
33        self.board_mut().fill(value);
34    }
35
36    fn or(&self, other: &impl BitBoard) -> Result<Self, DimensionMismatch>;
37    fn and(&self, other: &impl BitBoard) -> Result<Self, DimensionMismatch>;
38
39    /// Set the value at index [row, col] to be the `new_val`.
40    fn set(&mut self, row: usize, col: usize, value: bool) {
41        let new_ind = self.index_of(row, col);
42        self.board_mut().set(new_ind, value);
43    }
44    /// Set an entire column to a certain value
45    fn set_col(&mut self, col: usize, value: bool) {
46        // For each row
47        for r_idx in 0..self.n_rows() {
48            // Calculate the index
49            let idx = (r_idx * self.n_cols()) + col;
50            self.board_mut().set(idx, value);
51        }
52    }
53
54    /// Set an entire row to a certain value
55    fn set_row(&mut self, row: usize, value: bool) {
56        // For each column in the row
57        for cidx in 0..self.n_cols() {
58            // Calculate the index
59            let idx = (row * self.n_cols()) + cidx;
60            self.board_mut().set(idx, value);
61        }
62    }
63
64    /// Will set the neighbors immediately above, below, left, and right to `value`. If
65    /// the neighbor is out of bounds, nothing will happen
66    fn set_cardinal_neighbors(&mut self, row: usize, col: usize, value: bool) {
67        // Above
68        if row > 0 {
69            self.set(row - 1, col, value);
70        }
71
72        // Below
73        if row < self.n_rows() - 1 {
74            self.set(row + 1, col, value);
75        }
76
77        // Left
78        if col > 0 {
79            self.set(row, col - 1, value);
80        }
81
82        // Right
83        if col < self.n_cols() - 1 {
84            self.set(row, col + 1, value);
85        }
86    }
87
88    /// Set just the spots diagonal from the given position to `value`. If
89    /// the neighbor is out of bounds, nothing will happen
90    fn set_diagonals(&mut self, row: usize, col: usize, value: bool) {
91        // Above left
92        if row > 0 && col > 0 {
93            self.set(row - 1, col - 1, value);
94        }
95
96        // Above right
97        if row > 0 && col < self.n_cols() - 1 {
98            self.set(row - 1, col + 1, value);
99        }
100
101        // Below left
102        if row < self.n_rows() - 1 && col > 0 {
103            self.set(row + 1, col - 1, value);
104        }
105
106        // Below right
107        if row < self.n_rows() - 1 && col < self.n_cols() - 1 {
108            self.set(row + 1, col + 1, value);
109        }
110    }
111
112    /// Set the cardinal neighbors and the diagonal neighbors to `value`. If
113    /// the neighbor is out of bounds, nothing will happen
114    fn set_all_neighbors(&mut self, row: usize, col: usize, value: bool) {
115        self.set_cardinal_neighbors(row, col, value);
116        self.set_diagonals(row, col, value);
117    }
118}