tbg/
grid.rs

1use crate::cardinal::translate;
2use crate::cardinal::Ordinal;
3use crate::cardinal::Point;
4
5#[derive(Serialize, Deserialize, Clone, Default, PartialEq, Eq)]
6pub struct Grid<T>
7where
8    T: Clone,
9{
10    w: isize,
11    h: isize,
12    states: Vec<T>,
13}
14
15impl<T> Grid<T>
16where
17    T: Clone,
18{
19    pub fn new(w: usize, h: usize, init: T) -> Self {
20        let mut vec = Vec::with_capacity(w * h);
21
22        for _ in 0..w * h {
23            vec.push(init.clone());
24        }
25
26        Grid {
27            w: w as isize,
28            h: h as isize,
29            states: vec,
30        }
31    }
32
33    pub fn set_area(&mut self, a: Point, b: Point, v: T) {
34        if !self.in_bounds(a) {
35            panic!("{:?} out of bounds in grid.", a);
36        }
37        if !self.in_bounds(b) {
38            panic!("{:?} out of bounds in grid.", b);
39        }
40        for y in 0..=a.1.min(b.1) {
41            for x in 0..=a.0.min(b.0) {
42                self.states[(y * self.w + x) as usize] = v.clone();
43            }
44        }
45    }
46
47    pub fn is_area_open(&self, _a: Point, _b: Point, _f: fn(&T) -> bool) -> bool {
48        unimplemented!();
49    }
50
51    pub fn in_bounds(&self, (x, y): Point) -> bool {
52        x >= 0 && y >= 0 && x < self.w && y < self.h
53    }
54
55    pub fn dims(&self) -> (isize, isize) {
56        (self.w, self.h)
57    }
58
59    pub fn set(&mut self, xy: Point, v: T) {
60        if self.in_bounds(xy) {
61            self.states[(xy.1 * self.w + xy.0) as usize] = v;
62        } else {
63            panic!("{:?} out of bounds in grid.", xy);
64        }
65    }
66
67    pub fn get(&self, xy: Point) -> Option<&T> {
68        if self.in_bounds(xy) {
69            Some(&self.states[(xy.1 * self.w + xy.0) as usize])
70        } else {
71            None
72        }
73    }
74
75    pub fn get_mut(&mut self, xy: Point) -> Option<&mut T> {
76        if self.in_bounds(xy) {
77            Some(&mut self.states[(xy.1 * self.w + xy.0) as usize])
78        } else {
79            None
80        }
81    }
82
83    pub fn is_open(&self, xy: Point, f: fn(&T) -> bool) -> bool {
84        self.in_bounds(xy) && f(&self.states[(xy.1 * self.w + xy.0) as usize])
85    }
86
87    pub fn furthest_open(
88        &self,
89        xy: Point,
90        f: fn(&T) -> bool,
91        distance: usize,
92        facing: Ordinal,
93    ) -> Point {
94        let mut new_xy = xy;
95        for _ in 0..distance {
96            let step = translate(1, facing, new_xy);
97            if !self.is_open(step, f) {
98                return new_xy;
99            }
100            new_xy = step;
101        }
102        new_xy
103    }
104}