mapgen/filter/
cellular_automata.rs1use rand::prelude::*;
25use crate::MapFilter;
26use crate::MapBuffer;
27
28
29pub struct CellularAutomata {
31 num_iteraction: u32,
32}
33
34impl MapFilter for CellularAutomata {
35 fn modify_map(&self, _rng: &mut StdRng, map: &MapBuffer) -> MapBuffer {
36 self.build(map)
37 }
38}
39
40impl CellularAutomata {
41 pub fn new() -> Box<CellularAutomata> {
43 Box::new(CellularAutomata { num_iteraction: 15})
44 }
45
46 fn build(&self, map: &MapBuffer) -> MapBuffer {
48 let mut new_map = map.clone();
49 for _ in 0..self.num_iteraction {
50 new_map = apply_iteration(&new_map);
51 }
52
53 new_map
54 }
55
56}
57
58fn apply_iteration(map: &MapBuffer) -> MapBuffer {
59 let mut new_map = map.clone();
60
61 for y in 1..map.height-1 {
62 for x in 1..map.width-1 {
63 let idxs = [
64 (x-1, y-1), (x, y-1), (x+1, y-1),
65 (x-1, y), (x+1, y),
66 (x-1, y+1), (x, y+1), (x+1, y+1)];
67 let neighbors = idxs.iter()
68 .filter(|(x, y)| map.is_blocked(*x, *y))
69 .count();
70
71 let walkable = neighbors < 5 && neighbors > 0;
72 new_map.set_walkable(x, y, walkable);
73 }
74 }
75
76 new_map
77}
78
79#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn test_iteration_wal() {
88 let map = MapBuffer::new(3, 3);
89 let new_map = apply_iteration(&map);
90 assert!(new_map.is_blocked(1, 1));
91 }
92
93
94 #[test]
95 fn test_iteration_floor() {
96 let mut map = MapBuffer::new(3, 3);
97 for i in 0..3 {
98 for j in 0..2 {
99 map.set_walkable(i, j, true);
100 }
101 }
102 let new_map = apply_iteration(&map);
103 assert!(new_map.is_walkable(1, 1));
104 }
105
106}