summaryrefslogtreecommitdiff
path: root/2019-worms/src/game/map.rs
blob: 84ec99a0de166f26a8278845d871e5140fc23396 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
use crate::constants::*;
use crate::geometry::*;

#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
pub struct Map {
    pub cells: [u64; MAP_U64S],
}

impl Map {
    fn internal_index(p: Point2d) -> Option<(usize, usize)> {
        if p.y < 0 || p.y as usize >= MAP_SIZE {
            None
        } else {
            let row_data = &MAP_ROW_SIZE[p.y as usize];
            if p.x < row_data.x_offset as i8 || p.x as usize >= row_data.x_offset + row_data.len() {
                None
            } else {
                let global_bit = row_data.start_bit + p.x as usize - row_data.x_offset;
                let integer = global_bit / 64;
                let bit = global_bit % 64;
                Some((integer, bit))
            }
        }
    }

    pub fn at(&self, p: Point2d) -> Option<bool> {
        Map::internal_index(p).map(|(integer, bit)| {
            let mask = 1 << bit;
            self.cells[integer] & mask != 0
        })
    }

    pub fn set(&mut self, p: Point2d) {
        if let Some((integer, bit)) = Map::internal_index(p) {
            let mask = 1 << bit;
            self.cells[integer] |= mask;
        } else {
            panic!("Tried to set an out of bounds bit, {:?}", p);
        }
    }
    pub fn clear(&mut self, p: Point2d) {
        if let Some((integer, bit)) = Map::internal_index(p) {
            let mask = !(1 << bit);
            self.cells[integer] &= mask;
        } else {
            panic!("Tried to set an out of bounds bit, {:?}", p);
        }
    }
}