use crate::cardinal::translate;
use crate::cardinal::Ordinal;
use crate::cardinal::Point;
#[derive(Serialize, Deserialize, Clone, Default, PartialEq, Eq)]
pub struct Grid<T>
where
T: Clone,
{
w: isize,
h: isize,
states: Vec<T>,
}
impl<T> Grid<T>
where
T: Clone,
{
pub fn new(w: usize, h: usize, init: T) -> Self {
let mut vec = Vec::with_capacity(w * h);
for _ in 0..w * h {
vec.push(init.clone());
}
Grid {
w: w as isize,
h: h as isize,
states: vec,
}
}
pub fn set_area(&mut self, a: Point, b: Point, v: T) {
if !self.in_bounds(a) {
panic!("{:?} out of bounds in grid.", a);
}
if !self.in_bounds(b) {
panic!("{:?} out of bounds in grid.", b);
}
for y in 0..=a.1.min(b.1) {
for x in 0..=a.0.min(b.0) {
self.states[(y * self.w + x) as usize] = v.clone();
}
}
}
pub fn is_area_open(&self, _a: Point, _b: Point, _f: fn(&T) -> bool) -> bool {
unimplemented!();
}
pub fn in_bounds(&self, (x, y): Point) -> bool {
x >= 0 && y >= 0 && x < self.w && y < self.h
}
pub fn dims(&self) -> (isize, isize) {
(self.w, self.h)
}
pub fn set(&mut self, xy: Point, v: T) {
if self.in_bounds(xy) {
self.states[(xy.1 * self.w + xy.0) as usize] = v;
} else {
panic!("{:?} out of bounds in grid.", xy);
}
}
pub fn get(&self, xy: Point) -> Option<&T> {
if self.in_bounds(xy) {
Some(&self.states[(xy.1 * self.w + xy.0) as usize])
} else {
None
}
}
pub fn get_mut(&mut self, xy: Point) -> Option<&mut T> {
if self.in_bounds(xy) {
Some(&mut self.states[(xy.1 * self.w + xy.0) as usize])
} else {
None
}
}
pub fn is_open(&self, xy: Point, f: fn(&T) -> bool) -> bool {
self.in_bounds(xy) && f(&self.states[(xy.1 * self.w + xy.0) as usize])
}
pub fn furthest_open(
&self,
xy: Point,
f: fn(&T) -> bool,
distance: usize,
facing: Ordinal,
) -> Point {
let mut new_xy = xy;
for _ in 0..distance {
let step = translate(1, facing, new_xy);
if !self.is_open(step, f) {
return new_xy;
}
new_xy = step;
}
new_xy
}
}