tbg 0.1.3

A library for implementing turn based games logic
Documentation
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
    }
}