terrain_forge/algorithms/
agent.rs1use 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}