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}