Skip to content

Commit

Permalink
Merge pull request #1 from Earthmark/earthmark-dev
Browse files Browse the repository at this point in the history
Fixed up some of the clippy findings.
  • Loading branch information
Earthmark authored Feb 26, 2022
2 parents 8906b0b + c0505e4 commit 1970943
Showing 1 changed file with 54 additions and 67 deletions.
121 changes: 54 additions & 67 deletions src/maze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,64 @@ use std::{
rc::{Rc, Weak},
};

#[allow(dead_code)]
#[derive(PartialEq)]
pub enum MazeMoveDir {
Forward,
Backward,
}

pub trait Maze<const DIMS: usize> {
fn can_move(
&self,
point: &[usize; DIMS],
dimension: usize,
direction: MazeMoveDir,
) -> Option<bool>;
}

struct WalkMaze<const DIMS: usize> {
pub struct Maze<const DIMS: usize> {
walks: std::collections::HashSet<([usize; DIMS], [usize; DIMS])>,
lengths: [usize; DIMS],
}

impl<const DIMS: usize> WalkMaze<DIMS> {
#[allow(dead_code)]
impl<const DIMS: usize> Maze<DIMS> {
// Generate a maze with the provided number of side lengths.
pub fn new(lengths: &[usize; DIMS], rng: &mut impl rand::Rng) -> Maze<DIMS> {
let mut maze = Maze::<DIMS> {
lengths: *lengths,
walks: Default::default(),
};

let cell_count = lengths.iter().product();

// Indexed by dimension sums (higher is higher power).
let mut cells = HashMap::<[usize; DIMS], MazeGenCellRef>::with_capacity(cell_count);
for index in 0..cell_count {
let pos = unwrap_index(lengths, index).unwrap();
cells.insert(pos, MazeGenCell::new(index));
}

let mut pending_edges = BinaryHeap::with_capacity(cell_count * DIMS);
for index in 0..cell_count {
for dim in 0..DIMS {
pending_edges.push((rng.next_u32(), index, dim))
}
}

while let Some((_, target_index, dim)) = pending_edges.pop() {
let a = unwrap_index(lengths, target_index).unwrap();
// Skip the ends of each dimension, as that's checking outside the bounds of the space.
// In the future do this check on insertion into the heap.
if a[dim] == lengths[dim] {
continue;
}
let mut b = a;
b[dim] += 1;
if let Some(cell_a) = cells.get(&a) {
if let Some(cell_b) = cells.get(&b) {
if MazeGenCell::try_merge(cell_a, cell_b) {
maze.walks.insert((a, b));
}
}
}
}

maze
}

fn check_pair(&self, a: &[usize; DIMS], b: &[usize; DIMS]) -> Option<bool> {
for index in 0..DIMS {
let length = self.lengths[index];
Expand All @@ -35,21 +72,16 @@ impl<const DIMS: usize> WalkMaze<DIMS> {

// Check for either direction because it's cheaper to check twice
// than store an exponential memory problem.
return Some(
self.walks.contains(&(a.clone(), b.clone()))
|| self.walks.contains(&(b.clone(), a.clone())),
);
Some(self.walks.contains(&(*a, *b)) || self.walks.contains(&(*b, *a)))
}
}

impl<const DIMS: usize> Maze<DIMS> for WalkMaze<DIMS> {
fn can_move(
pub fn can_move(
&self,
point: &[usize; DIMS],
dimension: usize,
direction: MazeMoveDir,
) -> Option<bool> {
let mut target_point = point.clone();
let mut target_point = *point;
if let Some(shift_axis) = target_point.get_mut(dimension) {
if let Some(new_shifted) = match direction {
MazeMoveDir::Forward => shift_axis.checked_add(1),
Expand All @@ -59,7 +91,7 @@ impl<const DIMS: usize> Maze<DIMS> for WalkMaze<DIMS> {
return self.check_pair(point, &target_point);
}
}
return None;
None
}
}

Expand Down Expand Up @@ -115,51 +147,6 @@ fn unwrap_index<const DIMS: usize>(lengths: &[usize; DIMS], index: usize) -> Opt
}
}

// Generate a maze with the provided number of side lengths.
pub fn generate_maze<const DIMS: usize>(
lengths: &[usize; DIMS],
rng: &mut impl rand::Rng,
) -> impl Maze<DIMS> {
let mut maze = WalkMaze::<DIMS> {
lengths: lengths.clone(),
walks: Default::default(),
};

let cell_count = lengths.iter().product();

// Indexed by dimension sums (higher is higher power).
let mut cells = HashMap::<[usize; DIMS], MazeGenCellRef>::with_capacity(cell_count);
for index in 0..cell_count {
let pos = unwrap_index(lengths, index).unwrap();
cells.insert(pos, MazeGenCell::new(index));
}

let mut pending_edges = BinaryHeap::with_capacity(cell_count * DIMS);
for index in 0..cell_count {
for dim in 0..DIMS {
pending_edges.push((rng.next_u32(), index, dim))
}
}

while let Some((_, target_index, dim)) = pending_edges.pop() {
let a = unwrap_index(lengths, target_index).unwrap();
if a[dim] == lengths[dim] {
continue;
}
let mut b = a.clone();
b[dim] += 1;
if let Some(cell_a) = cells.get(&a) {
if let Some(cell_b) = cells.get(&b) {
if MazeGenCell::try_merge(cell_a, cell_b) {
maze.walks.insert((a, b));
}
}
}
}

maze
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -203,7 +190,7 @@ mod tests {
#[test]
fn verify_generates() {
let mut rng = StdRng::seed_from_u64(684153987);
let maze = generate_maze(&[5, 5, 5, 5, 5], &mut rng);
let maze = Maze::new(&[5, 5, 5, 5, 5], &mut rng);

assert_eq!(
maze.can_move(&[1, 2, 3214, 2, 2], 2, MazeMoveDir::Forward),
Expand All @@ -214,7 +201,7 @@ mod tests {
#[test]
fn verify_generates_single() {
let mut rng = StdRng::seed_from_u64(684153987);
let maze = generate_maze(&[5, 1, 1], &mut rng);
let maze = Maze::new(&[5, 1, 1], &mut rng);

assert_eq!(
maze.can_move(&[0, 0, 0], 0, MazeMoveDir::Forward),
Expand Down

0 comments on commit 1970943

Please sign in to comment.