terrain_forge/algorithms/
agent.rs

1use crate::{Algorithm, Grid, Rng, Tile};
2
3#[derive(Debug, Clone)]
4pub struct AgentConfig {
5    pub num_agents: usize,
6    pub steps_per_agent: usize,
7    pub turn_chance: f64,
8}
9
10impl Default for AgentConfig {
11    fn default() -> Self {
12        Self {
13            num_agents: 5,
14            steps_per_agent: 200,
15            turn_chance: 0.3,
16        }
17    }
18}
19
20pub struct AgentBased {
21    config: AgentConfig,
22}
23
24impl AgentBased {
25    pub fn new(config: AgentConfig) -> Self {
26        Self { config }
27    }
28}
29
30impl Default for AgentBased {
31    fn default() -> Self {
32        Self::new(AgentConfig::default())
33    }
34}
35
36impl Algorithm<Tile> for AgentBased {
37    fn generate(&self, grid: &mut Grid<Tile>, seed: u64) {
38        let mut rng = Rng::new(seed);
39        let dirs: [(i32, i32); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)];
40        let (w, h) = (grid.width() as i32, grid.height() as i32);
41
42        for _ in 0..self.config.num_agents {
43            let mut x = rng.range(1, w - 1);
44            let mut y = rng.range(1, h - 1);
45            let mut dir = rng.range_usize(0, 4);
46
47            for _ in 0..self.config.steps_per_agent {
48                grid.set(x, y, Tile::Floor);
49
50                if rng.chance(self.config.turn_chance) {
51                    dir = if rng.chance(0.5) {
52                        (dir + 1) % 4
53                    } else {
54                        (dir + 3) % 4
55                    };
56                }
57
58                let (dx, dy) = dirs[dir];
59                let (nx, ny) = (x + dx, y + dy);
60
61                if nx > 0 && nx < w - 1 && ny > 0 && ny < h - 1 {
62                    x = nx;
63                    y = ny;
64                } else {
65                    dir = (dir + 2) % 4;
66                }
67            }
68        }
69    }
70
71    fn name(&self) -> &'static str {
72        "AgentBased"
73    }
74}