auto_cellular/
world.rs

1use crate::{
2    cell::BasicCell,
3    common::{Dimensions, DoubleVec, Index},
4};
5
6/// A given [BasicWorld] knows how to go from one state of [BasicCell] to the next on each
7/// tick by provding a [BasicWorld::changes] method
8pub trait BasicWorld<C>
9where
10    C: BasicCell,
11    Self: Sized,
12{
13    /// Gives a blank [BasicWorld] of the same configuration as the original world
14    fn blank(&self) -> Self {
15        Self::new_blank(self.dimensions())
16    }
17
18    /// Gives a random [BasicWorld] of the same configuration as the original world
19    fn random<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Self {
20        Self::new_random(rng, self.dimensions())
21    }
22
23    /// Constaruct a new [BasicWorld]
24    fn new(cells: DoubleVec<C>, dimensions: Dimensions) -> Self;
25    fn new_blank(dimensions: Dimensions) -> Self {
26        let default = C::default();
27        let cells = vec![vec![(); dimensions.0]; dimensions.1]
28            .into_iter()
29            .map(|row| row.into_iter().map(|_| default).collect())
30            .collect();
31        Self::new(cells, dimensions)
32    }
33
34    fn new_random<R: rand::Rng + ?Sized>(rng: &mut R, dimensions: Dimensions) -> Self {
35        let cells = (0..dimensions.0 * dimensions.1)
36            .collect::<Vec<usize>>()
37            .chunks(dimensions.0)
38            .into_iter()
39            .map(|chunk| chunk.iter().map(|_| C::random(rng)).collect())
40            .collect();
41        Self::new(cells, dimensions)
42    }
43
44    /// Gets a shared referene to the grid of [BasicCell]s
45    fn cells(&self) -> &DoubleVec<C>;
46    /// Gets a mutable referene to the grid of [BasicCell]s
47    fn cells_mut(&mut self) -> &mut DoubleVec<C>;
48
49    /// Given a [BasicWorld], return the changes to [BasicCell]s that
50    /// would happned the *upcoming* tick and the [Index]s where they happened
51    fn changes(&self) -> Vec<(Index, C)>;
52
53    /// Returns the dela that happened the previous [BasicWorld::tick]
54    fn delta(&self) -> &Vec<(Index, C)>;
55    /// Returns a mutable reference to that value
56    fn delta_mut(&mut self) -> &mut Vec<(Index, C)>;
57
58    /// Get the dimensions of the world
59    fn dimensions(&self) -> Dimensions;
60
61    /// Commit the [BasicWorld::changes] to memory
62    fn tick(&mut self) {
63        let changes = self.changes();
64        for ((x, y), cell) in changes.iter() {
65            self.cells_mut()[*y][*x] = *cell;
66        }
67        *self.delta_mut() = changes;
68    }
69
70    /// A click happened at a given [Index]
71    fn click(&mut self, i @ (x, y): Index) {
72        let c = &mut self.cells_mut()[y][x];
73        *c = c.next_state();
74        *self.delta_mut() = vec![(i, *c)]
75    }
76
77    /// Returns the Moore Neihgbors for a given [BasicCell] at a given [Index] (x, y)
78    fn moore_neighbors(&self, p @ (x, y): Index) -> Vec<Index> {
79        let (x, y) = (x as isize, y as isize);
80        let (w, h) = (self.dimensions().0 as isize, self.dimensions().1 as isize);
81
82        (-1..=1)
83            .flat_map(|i| {
84                (-1..=1).map(move |j| {
85                    (
86                        (x + i).rem_euclid(w) as usize,
87                        (y + j).rem_euclid(h) as usize,
88                    )
89                })
90            })
91            .filter(move |&item| item != p)
92            .collect()
93    }
94}
95
96#[cfg(test)]
97mod test {
98    use super::*;
99    use crate::cell::test::Cell;
100
101    struct World;
102
103    impl BasicWorld<Cell> for World {
104        fn new(cells: DoubleVec<Cell>, dimensions: Dimensions) -> Self {
105            todo!()
106        }
107
108        fn cells(&self) -> &DoubleVec<Cell> {
109            todo!()
110        }
111
112        fn cells_mut(&mut self) -> &mut DoubleVec<Cell> {
113            todo!()
114        }
115
116        fn changes(&self) -> Vec<(Index, Cell)> {
117            todo!()
118        }
119
120        fn delta(&self) -> &Vec<(Index, Cell)> {
121            todo!()
122        }
123
124        fn delta_mut(&mut self) -> &mut Vec<(Index, Cell)> {
125            todo!()
126        }
127
128        fn dimensions(&self) -> Dimensions {
129            Dimensions(50, 50)
130        }
131    }
132
133    #[test]
134    fn moore_neighbors_works() {
135        let world = World;
136
137        println!("{:?}", world.moore_neighbors((49, 49)));
138    }
139}