terrain_forge/algorithms/
fractal.rs

1use crate::{Algorithm, Grid, Rng, Tile};
2
3pub struct Fractal;
4
5impl Default for Fractal {
6    fn default() -> Self {
7        Self
8    }
9}
10
11impl Algorithm<Tile> for Fractal {
12    fn generate(&self, grid: &mut Grid<Tile>, seed: u64) {
13        let mut rng = Rng::new(seed);
14        if rng.chance(0.5) {
15            generate_mandelbrot(grid);
16        } else {
17            generate_julia(grid, &mut rng);
18        }
19    }
20
21    fn name(&self) -> &'static str {
22        "Fractal"
23    }
24}
25
26fn generate_mandelbrot(grid: &mut Grid<Tile>) {
27    let (w, h) = (grid.width(), grid.height());
28    let max_iter = 100;
29
30    for y in 0..h {
31        for x in 0..w {
32            let cx = (x as f64 / w as f64 - 0.5) * 4.0 - 0.5;
33            let cy = (y as f64 / h as f64 - 0.5) * 4.0;
34
35            let mut zx = 0.0;
36            let mut zy = 0.0;
37            let mut iter = 0;
38
39            while zx * zx + zy * zy < 4.0 && iter < max_iter {
40                let temp = zx * zx - zy * zy + cx;
41                zy = 2.0 * zx * zy + cy;
42                zx = temp;
43                iter += 1;
44            }
45
46            if iter < max_iter / 3 {
47                grid.set(x as i32, y as i32, Tile::Floor);
48            }
49        }
50    }
51}
52
53fn generate_julia(grid: &mut Grid<Tile>, rng: &mut Rng) {
54    let (w, h) = (grid.width(), grid.height());
55    let max_iter = 100;
56    let cx = rng.random() * 2.0 - 1.0;
57    let cy = rng.random() * 2.0 - 1.0;
58
59    for y in 0..h {
60        for x in 0..w {
61            let mut zx = (x as f64 / w as f64 - 0.5) * 3.0;
62            let mut zy = (y as f64 / h as f64 - 0.5) * 3.0;
63            let mut iter = 0;
64
65            while zx * zx + zy * zy < 4.0 && iter < max_iter {
66                let temp = zx * zx - zy * zy + cx;
67                zy = 2.0 * zx * zy + cy;
68                zx = temp;
69                iter += 1;
70            }
71
72            if iter < max_iter / 2 {
73                grid.set(x as i32, y as i32, Tile::Floor);
74            }
75        }
76    }
77}