terrain_forge/algorithms/
drunkard.rs1use crate::{Algorithm, Grid, Rng, Tile};
2
3#[derive(Debug, Clone)]
4pub struct DrunkardConfig {
5 pub floor_percent: f64,
6 pub max_iterations: usize,
7}
8
9impl Default for DrunkardConfig {
10 fn default() -> Self { Self { floor_percent: 0.4, max_iterations: 50000 } }
11}
12
13pub struct DrunkardWalk {
14 config: DrunkardConfig,
15}
16
17impl DrunkardWalk {
18 pub fn new(config: DrunkardConfig) -> Self { Self { config } }
19}
20
21impl Default for DrunkardWalk {
22 fn default() -> Self { Self::new(DrunkardConfig::default()) }
23}
24
25impl Algorithm<Tile> for DrunkardWalk {
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 target = ((w * h) as f64 * self.config.floor_percent) as usize;
30 let dirs: [(i32, i32); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)];
31
32 let mut x = w as i32 / 2;
33 let mut y = h as i32 / 2;
34 let mut floor_count = 0;
35
36 for _ in 0..self.config.max_iterations {
37 if floor_count >= target { break; }
38
39 if !grid.get(x, y).map(|t| t.is_floor()).unwrap_or(true) {
40 grid.set(x, y, Tile::Floor);
41 floor_count += 1;
42 }
43
44 let (dx, dy) = dirs[rng.range_usize(0, 4)];
45 let (nx, ny) = (x + dx, y + dy);
46 if nx > 0 && nx < w as i32 - 1 && ny > 0 && ny < h as i32 - 1 {
47 x = nx;
48 y = ny;
49 }
50 }
51 }
52
53 fn name(&self) -> &'static str { "DrunkardWalk" }
54}