mazeir/map/orthogonal/
depth_first.rs1use super::{Orthogonal, Direction2D};
8
9use rand::Rng;
10use rand::seq::SliceRandom;
11
12use crate::algorithm::DepthFirst;
13
14const FLAG: u8 = 0b1000_0000;
15const LAST_DIRECTION_MASK: u8 = 0b0111_0000;
16const LAST_DIRECTION_MASK_INVERSE: u8 = 0b1000_1111;
17const LAST_DIRECTION_NONE: u8 = 0b0000_0000;
18const LAST_DIRECTION_LEFT: u8 = 0b0001_0000;
19const LAST_DIRECTION_RIGHT: u8 = 0b0010_0000;
20const LAST_DIRECTION_UP: u8 = 0b0011_0000;
21const LAST_DIRECTION_DOWN: u8 = 0b00100_0000;
22
23
24impl Orthogonal {
25 #[inline]
26 fn add_walls_to_vec_with_flag(&mut self, x: usize, y: usize, vec: &mut Vec<Direction2D>) {
27 if x != 0 && *self.get_mut(x - 1, y) & FLAG == 0 { vec.push(Direction2D::Left); }
28 if x != self.width - 1 && *self.get_mut(x + 1, y) & FLAG == 0 { vec.push(Direction2D::Right); }
29 if y != 0 && *self.get_mut(x, y - 1) & FLAG == 0 { vec.push(Direction2D::Up); }
30 if y != self.height - 1 && *self.get_mut(x, y + 1) & FLAG == 0 { vec.push(Direction2D::Down); }
31 }
32}
33
34
35impl DepthFirst for Orthogonal {
36 fn depth_first_with_rng<R: Rng + ?Sized>(&mut self, rng: &mut R) {
37 if self.width == 0 || self.height == 0 { return; }
38 let mut rng = rng;
39 let start_point = self.center_point();
40 let (mut x, mut y) = (start_point.0, start_point.1);
41 self.set(x, y, FLAG);
42 let mut walls = Vec::with_capacity(4);
43 loop {
44 walls.clear();
45 self.add_walls_to_vec_with_flag(x, y, &mut walls);
46 let wall = walls.choose(&mut rng);
47 match wall {
48 Some(wall) => {
49 self.break_wall(x, y, wall);
50 match wall {
51 Direction2D::Left => {
52 x -= 1;
53 self.map[y * self.width + x] &= LAST_DIRECTION_MASK_INVERSE;
54 self.map[y * self.width + x] |= LAST_DIRECTION_RIGHT;
55 }
56 Direction2D::Right => {
57 x += 1;
58 self.map[y * self.width + x] &= LAST_DIRECTION_MASK_INVERSE;
59 self.map[y * self.width + x] |= LAST_DIRECTION_LEFT;
60 }
61 Direction2D::Up => {
62 y -= 1;
63 self.map[y * self.width + x] &= LAST_DIRECTION_MASK_INVERSE;
64 self.map[y * self.width + x] |= LAST_DIRECTION_DOWN;
65 }
66 Direction2D::Down => {
67 y += 1;
68 self.map[y * self.width + x] &= LAST_DIRECTION_MASK_INVERSE;
69 self.map[y * self.width + x] |= LAST_DIRECTION_UP;
70 }
71 }
72 self.map[y * self.width + x] |= FLAG;
73 }
74 None => {
75 let point_value = self.get_mut(x, y);
76 match *point_value & LAST_DIRECTION_MASK {
77 LAST_DIRECTION_LEFT => { x -= 1; }
78 LAST_DIRECTION_RIGHT => { x += 1; }
79 LAST_DIRECTION_UP => { y -= 1; }
80 LAST_DIRECTION_DOWN => { y += 1; }
81 LAST_DIRECTION_NONE => { break; }
82 _ => {}}
84 }
85 }
86 }
87 }
88}