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 { Self { num_agents: 5, steps_per_agent: 200, turn_chance: 0.3 } }
12}
13
14pub struct AgentBased {
15    config: AgentConfig,
16}
17
18impl AgentBased {
19    pub fn new(config: AgentConfig) -> Self { Self { config } }
20}
21
22impl Default for AgentBased {
23    fn default() -> Self { Self::new(AgentConfig::default()) }
24}
25
26impl Algorithm<Tile> for AgentBased {
27    fn generate(&self, grid: &mut Grid<Tile>, seed: u64) {
28        let mut rng = Rng::new(seed);
29        let dirs: [(i32, i32); 4] = [(0, -1), (1, 0), (0, 1), (-1, 0)];
30        let (w, h) = (grid.width() as i32, grid.height() as i32);
31
32        for _ in 0..self.config.num_agents {
33            let mut x = rng.range(1, w - 1);
34            let mut y = rng.range(1, h - 1);
35            let mut dir = rng.range_usize(0, 4);
36
37            for _ in 0..self.config.steps_per_agent {
38                grid.set(x, y, Tile::Floor);
39
40                if rng.chance(self.config.turn_chance) {
41                    dir = if rng.chance(0.5) { (dir + 1) % 4 } else { (dir + 3) % 4 };
42                }
43
44                let (dx, dy) = dirs[dir];
45                let (nx, ny) = (x + dx, y + dy);
46
47                if nx > 0 && nx < w - 1 && ny > 0 && ny < h - 1 {
48                    x = nx;
49                    y = ny;
50                } else {
51                    dir = (dir + 2) % 4;
52                }
53            }
54        }
55    }
56
57    fn name(&self) -> &'static str { "AgentBased" }
58}