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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use rand::Rng;

use super::pixel::Pixel;

/// Trait representing an error during Grid initialization. The only possible error is currently SizeMustNotBeZero.
#[derive(Debug)]
pub enum SizeErr {
    SizeMustNotBeZero,
}

/// Trait representing an implemented Grid, which is implemented for 2D and 3D grids by default.
pub trait ImplementedGrid<L, T: Clone, SL>: Sized {
    /// Constructs a new Grid using the n-dimensional size.
    fn new(size: L) -> Result<Self, SizeErr>;
    /// Clones and returns a Pixel from the Grid.
    fn get_item(&self, location: L) -> Pixel<T>;
    /// Sets a Pixel in the Grid.
    fn set_item(&mut self, location: L, item: Pixel<T>);

    /// Returns unidirectional neighbors, meaning only neighbord with one common face.
    /// This means the corners will not be returned.
    fn unidirectional_neighbors(&self, location: L) -> Vec<Pixel<T>>;
    /// Returns all neighbord, including ones touching only at a single point.
    /// This does return corners.
    fn neighbors(&self, location: L, distance: usize) -> Vec<(L, Pixel<T>)>;

    /// Checks if a location is inside the Grid, then returns its Grid coordinates.
    fn check_loc(&self, location: SL) -> Option<L>;

    /// Checks if the Grid is valid
    fn check_validity<F>(&mut self, test: F) -> Result<(), L>
    where
        F: Fn(&Self, L, &T) -> bool;

    /// Collapses a single Pixel and updates neighbors. This will return false if the Grid is invalid.
    /// Please note that this function is not very useful, and you should use wfc instead
    fn collapse<F, R>(
        &mut self,
        test: F,
        effect_distance: usize,
        rng: &mut R,
        data: (L, Pixel<T>),
    ) -> Result<(), L>
    where
        F: Fn(&Self, L, &T) -> bool,
        R: Rng;

    /// Performs the wave-function-collapse algorithm on the Grid.
    /// This returns if the algorithm was successful, and the state of the Grid is not guaranteed
    /// to be valid if it returns false, but there is never unsafety in reading from the Grid.
    fn wfc<F, R>(&mut self, test: F, effect_distance: usize, rng: &mut R) -> Result<(), L>
    where
        F: Fn(&Self, L, &T) -> bool,
        R: Rng;
}

/// A microwfc grid, which can exist in all dimensions, but is only implemented for 2D and 3D.
pub struct Grid<L: Clone, V: Clone> {
    pub(crate) size: L,
    pub(crate) data: V,
}

impl<L: Clone, V: Clone> Grid<L, V> {
    /// Returns the n-dimensional size of the Grid.
    /// In all default implementations, this returns a n-tuple where n is the dimensionality of the Grid.
    pub fn size(&self) -> L {
        self.size.clone()
    }
}