terrain_forge/algorithms/
dla.rs1use crate::{Algorithm, Grid, Rng, Tile};
2
3#[derive(Debug, Clone)]
4pub struct DlaConfig {
5 pub num_particles: usize,
6 pub max_walk_steps: usize,
7}
8
9impl Default for DlaConfig {
10 fn default() -> Self { Self { num_particles: 500, max_walk_steps: 1000 } }
11}
12
13pub struct Dla {
14 config: DlaConfig,
15}
16
17impl Dla {
18 pub fn new(config: DlaConfig) -> Self { Self { config } }
19}
20
21impl Default for Dla {
22 fn default() -> Self { Self::new(DlaConfig::default()) }
23}
24
25impl Algorithm<Tile> for Dla {
26 fn generate(&self, grid: &mut Grid<Tile>, seed: u64) {
27 let mut rng = Rng::new(seed);
28 let (w, h) = (grid.width(), grid.height());
29 let dirs: [(i32, i32); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)];
30
31 grid.set(w as i32 / 2, h as i32 / 2, Tile::Floor);
33
34 for _ in 0..self.config.num_particles {
35 let mut x = rng.range(1, w as i32 - 1);
36 let mut y = rng.range(1, h as i32 - 1);
37
38 for _ in 0..self.config.max_walk_steps {
39 let has_neighbor = dirs.iter().any(|&(dx, dy)| {
40 grid.get(x + dx, y + dy).map(|t| t.is_floor()).unwrap_or(false)
41 });
42
43 if has_neighbor {
44 grid.set(x, y, Tile::Floor);
45 break;
46 }
47
48 let (dx, dy) = dirs[rng.range_usize(0, 4)];
49 let (nx, ny) = (x + dx, y + dy);
50 if nx > 0 && nx < w as i32 - 1 && ny > 0 && ny < h as i32 - 1 {
51 x = nx;
52 y = ny;
53 }
54 }
55 }
56 }
57
58 fn name(&self) -> &'static str { "DLA" }
59}