Skip to main content

satrush_client/
selection.rs

1/// Number of selectable tiles on the board.
2pub const TILE_COUNT: usize = 21;
3
4/// Convert a fixed-size array of tile selections into the packed `u32` selection
5/// mask expected by `deploy_public`: bit `i` is set when `tiles[i]` is `true`.
6///
7/// Because the array is exactly [`TILE_COUNT`] long, the result always fits in the
8/// low `TILE_COUNT` bits. Note the program still rejects an all-`false` selection
9/// (mask `0`), so callers should pick at least one tile.
10pub fn selection_mask_from_tiles(tiles: [bool; TILE_COUNT]) -> u32 {
11    let mut mask = 0u32;
12    for (i, &selected) in tiles.iter().enumerate() {
13        if selected {
14            mask |= 1u32 << i;
15        }
16    }
17    mask
18}
19
20/// Inverse of [`selection_mask_from_tiles`]: unpack a `u32` selection mask into a
21/// per-tile boolean array. Bits above [`TILE_COUNT`] are ignored.
22pub fn tiles_from_selection_mask(mask: u32) -> [bool; TILE_COUNT] {
23    let mut tiles = [false; TILE_COUNT];
24    for (i, tile) in tiles.iter_mut().enumerate() {
25        *tile = mask & (1u32 << i) != 0;
26    }
27    tiles
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn builds_mask_from_tiles() {
36        let mut tiles = [false; TILE_COUNT];
37        tiles[0] = true;
38        tiles[3] = true;
39        tiles[20] = true;
40        // bits 0, 3, 20 set
41        assert_eq!(selection_mask_from_tiles(tiles), (1 << 0) | (1 << 3) | (1 << 20));
42    }
43
44    #[test]
45    fn empty_and_full_selections() {
46        assert_eq!(selection_mask_from_tiles([false; TILE_COUNT]), 0);
47        assert_eq!(selection_mask_from_tiles([true; TILE_COUNT]), (1u32 << TILE_COUNT) - 1);
48    }
49
50    #[test]
51    fn round_trips() {
52        let mut tiles = [false; TILE_COUNT];
53        tiles[1] = true;
54        tiles[7] = true;
55        tiles[19] = true;
56        assert_eq!(tiles_from_selection_mask(selection_mask_from_tiles(tiles)), tiles);
57    }
58}