terrain_forge/algorithms/
fractal.rs

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