use super::{Algorithm, BOOL_TRUE_PROBABILITY};
use crate::maze::grid::{cell::Cell, Grid};
use rand::prelude::*;
enum Orientation {
Horizontal,
Vertical,
}
pub struct RecursiveDivision;
impl RecursiveDivision {
fn divide<R: Rng>(grid: &mut Grid, x: usize, y: usize, ax: usize, ay: usize, rng: &mut R) {
let w = ax - x + 1;
let h = ay - y + 1;
if w < 2 || h < 2 {
if w > 1 {
for cx in x..ax {
grid.carve_passage((cx, y), Cell::EAST).unwrap();
}
} else if h > 1 {
for cy in y..ay {
grid.carve_passage((x, cy), Cell::SOUTH).unwrap();
}
}
return;
}
let orientation = choose_orientation(w, h, rng);
let px = rng.random_range(x..ax);
let py = rng.random_range(y..ay);
let dir = match orientation {
Orientation::Horizontal => Cell::SOUTH,
Orientation::Vertical => Cell::EAST,
};
let (nx, ny) = grid.carve_passage((px, py), dir).unwrap();
match orientation {
Orientation::Horizontal => {
RecursiveDivision::divide(grid, x, y, ax, py, rng);
RecursiveDivision::divide(grid, x, ny, ax, ay, rng);
}
Orientation::Vertical => {
RecursiveDivision::divide(grid, x, y, px, ay, rng);
RecursiveDivision::divide(grid, nx, y, ax, ay, rng);
}
}
}
}
impl Algorithm for RecursiveDivision {
fn generate(&mut self, grid: &mut Grid, rng: &mut StdRng) {
let width = grid.width();
let height = grid.height();
RecursiveDivision::divide(grid, 0, 0, width - 1, height - 1, rng);
}
}
fn choose_orientation<R: Rng>(width: usize, height: usize, rng: &mut R) -> Orientation {
if width < height {
return Orientation::Horizontal;
}
if height < width {
return Orientation::Vertical;
}
if !rng.random_bool(BOOL_TRUE_PROBABILITY) {
Orientation::Horizontal
} else {
Orientation::Vertical
}
}