Adapt methods from dual maze to original maze.
This commit is contained in:
parent
045f03374d
commit
85ff8c6c62
@ -15,20 +15,31 @@ use pixelfoo::vec2d::Vec2d;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum Square {
|
||||
Unknown,
|
||||
Unused,
|
||||
Unknown { prio: i32 },
|
||||
Corridor,
|
||||
Wall,
|
||||
Start,
|
||||
Finish,
|
||||
}
|
||||
|
||||
impl Square {
|
||||
pub fn is_unknown(&self) -> bool {
|
||||
match self {
|
||||
Square::Unknown { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Board(Vec<Vec<Square>>);
|
||||
|
||||
fn send<T: Write>(w: &mut T, board: &Board) -> std::io::Result<()> {
|
||||
for line in &board.0 {
|
||||
for square in line {
|
||||
let c = match square {
|
||||
Square::Unknown => Color::black(),
|
||||
Square::Unused => Color::black(),
|
||||
Square::Unknown { .. } => Color::black(),
|
||||
Square::Corridor => Color::yellow(),
|
||||
Square::Wall => Color::darkblue(),
|
||||
Square::Start => Color::red(),
|
||||
@ -40,6 +51,12 @@ fn send<T: Write>(w: &mut T, board: &Board) -> std::io::Result<()> {
|
||||
w.flush()
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum Orientation {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
}
|
||||
|
||||
impl Board {
|
||||
fn new(board_size: Vec2d, maze_size: Vec2d) -> Board {
|
||||
Board(
|
||||
@ -56,10 +73,10 @@ impl Board {
|
||||
{
|
||||
Square::Wall
|
||||
} else {
|
||||
Square::Unknown
|
||||
Square::Unknown { prio: 0 }
|
||||
}
|
||||
} else {
|
||||
Square::Unknown
|
||||
Square::Unused
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
@ -73,6 +90,81 @@ impl Board {
|
||||
fn set(&mut self, pos: Point2d, sq: Square) {
|
||||
self.0[pos.y as usize][pos.x as usize] = sq;
|
||||
}
|
||||
|
||||
fn set_orientation(&mut self, desired: Orientation, pos: Point2d) {
|
||||
let sq = self.get(pos);
|
||||
let actual;
|
||||
match sq {
|
||||
Square::Unknown { .. } => {
|
||||
// determine corridor orientation
|
||||
if pos.x % 2 == 0 && pos.y % 2 != 0 {
|
||||
actual = Orientation::Horizontal;
|
||||
} else if pos.x % 2 != 0 && pos.y % 2 == 0 {
|
||||
actual = Orientation::Vertical;
|
||||
} else {
|
||||
// not a potential wall, unused
|
||||
actual = Orientation::Horizontal;
|
||||
}
|
||||
let prio = if actual == desired { 10 } else { -10 };
|
||||
self.set(pos, Square::Unknown { prio });
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
fn set_horizontal(&mut self, pos: Point2d) {
|
||||
self.set_orientation(Orientation::Horizontal, pos);
|
||||
}
|
||||
fn set_vertical(&mut self, pos: Point2d) {
|
||||
self.set_orientation(Orientation::Vertical, pos);
|
||||
}
|
||||
fn draw_horizontal_segment(&mut self, pos: Point2d, size: Vec2d) {
|
||||
for x in 0..size.x {
|
||||
let xn = size.x - 1 - x;
|
||||
self.set_horizontal(pos + v2d(x, 0));
|
||||
for y in 1..x.min(xn).min(size.y / 2) + 1 {
|
||||
self.set_horizontal(pos + v2d(x, y));
|
||||
self.set_horizontal(pos + v2d(x, -y));
|
||||
}
|
||||
}
|
||||
}
|
||||
fn draw_vertical_segment(&mut self, pos: Point2d, size: Vec2d) {
|
||||
for y in 0..size.y {
|
||||
let yn = size.y - 1 - y;
|
||||
self.set_vertical(pos + v2d(0, y));
|
||||
for x in 1..y.min(yn).min(size.x / 2) + 1 {
|
||||
self.set_vertical(pos + v2d(x, y));
|
||||
self.set_vertical(pos + v2d(-x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
fn draw_7_segments(&mut self, pos: Point2d, size: Vec2d, segments: u8) {
|
||||
let length = size.x;
|
||||
let width = size.y;
|
||||
let delta = length + 1;
|
||||
let hsize = v2d(length, width);
|
||||
let vsize = v2d(width, length);
|
||||
if (segments & (1 << 0)) != 0 {
|
||||
self.draw_horizontal_segment(pos + v2d(1, 0), hsize);
|
||||
}
|
||||
if (segments & (1 << 1)) != 0 {
|
||||
self.draw_vertical_segment(pos + v2d(delta, 1), vsize);
|
||||
}
|
||||
if (segments & (1 << 2)) != 0 {
|
||||
self.draw_vertical_segment(pos + v2d(delta, delta + 1), vsize);
|
||||
}
|
||||
if (segments & (1 << 3)) != 0 {
|
||||
self.draw_horizontal_segment(pos + v2d(1, 2 * delta), hsize);
|
||||
}
|
||||
if (segments & (1 << 4)) != 0 {
|
||||
self.draw_vertical_segment(pos + v2d(0, 1), vsize);
|
||||
}
|
||||
if (segments & (1 << 5)) != 0 {
|
||||
self.draw_vertical_segment(pos + v2d(0, delta + 1), vsize);
|
||||
}
|
||||
if (segments & (1 << 6)) != 0 {
|
||||
self.draw_horizontal_segment(pos + v2d(1, delta), hsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Move {
|
||||
@ -81,9 +173,17 @@ struct Move {
|
||||
prio: i32,
|
||||
}
|
||||
|
||||
fn add_move(open: &mut Vec<Move>, arg: isize, from: Point2d, dir: Vec2d) {
|
||||
open.push(Move { from, dir, prio: 0 });
|
||||
open.sort_unstable_by(|Move { prio: pa, .. }, Move { prio: pb, .. }| pa.cmp(pb));
|
||||
fn add_move<R>(board: &Board, open: &mut Vec<Move>, rng: &mut R, from: Point2d, dir: Vec2d)
|
||||
where
|
||||
R: Rng,
|
||||
{
|
||||
if let Square::Unknown { prio } = board.get(from + dir) {
|
||||
open.push(Move {
|
||||
from,
|
||||
dir,
|
||||
prio: prio * 100 + rng.gen_range(0, 1000),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_ARG: isize = 16;
|
||||
@ -122,12 +222,19 @@ fn main() -> std::io::Result<()> {
|
||||
t_wait = 60.0; // s
|
||||
board = Board::new(board_size, maze_size);
|
||||
|
||||
// draw stuff in prios
|
||||
let segment_size = v2d(11, 5);
|
||||
board.draw_7_segments(p2d(6, 8), segment_size, 0x06);
|
||||
board.draw_7_segments(p2d(24, 8), segment_size, 0x4f);
|
||||
board.draw_7_segments(p2d(42, 8), segment_size, 0x4f);
|
||||
board.draw_7_segments(p2d(60, 8), segment_size, 0x07);
|
||||
|
||||
// start in the middle
|
||||
board.set(maze_mid, Square::Corridor);
|
||||
add_move(&mut open, arg, maze_mid, v2d(1, 0));
|
||||
add_move(&mut open, arg, maze_mid, v2d(0, 1));
|
||||
add_move(&mut open, arg, maze_mid, v2d(-1, 0));
|
||||
add_move(&mut open, arg, maze_mid, v2d(0, -1));
|
||||
add_move(&board, &mut open, &mut rng, maze_mid, v2d(1, 0));
|
||||
add_move(&board, &mut open, &mut rng, maze_mid, v2d(0, 1));
|
||||
add_move(&board, &mut open, &mut rng, maze_mid, v2d(-1, 0));
|
||||
add_move(&board, &mut open, &mut rng, maze_mid, v2d(0, -1));
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,41 +242,25 @@ fn main() -> std::io::Result<()> {
|
||||
let work = arg.max(1);
|
||||
let mut count = 0;
|
||||
while !open.is_empty() && count < work {
|
||||
let mut start = 0;
|
||||
let mut limit = 0;
|
||||
let mut prio = open[limit].prio;
|
||||
loop {
|
||||
limit += 1;
|
||||
if limit >= open.len() {
|
||||
break;
|
||||
}
|
||||
if open[limit].prio > prio {
|
||||
if rng.gen::<f64>() >= 0.4 {
|
||||
break;
|
||||
}
|
||||
start = limit;
|
||||
prio = open[limit].prio;
|
||||
}
|
||||
}
|
||||
let r = rng.gen_range(start, limit);
|
||||
open.sort_unstable_by(|Move { prio: pa, .. }, Move { prio: pb, .. }| pa.cmp(pb));
|
||||
let Move {
|
||||
from: p0,
|
||||
dir: dir0,
|
||||
..
|
||||
} = open.remove(r);
|
||||
} = open.pop().unwrap();
|
||||
|
||||
let p1 = p0 + dir0;
|
||||
let p2 = p1 + dir0;
|
||||
if board.get(p1) == Square::Unknown {
|
||||
if board.get(p1).is_unknown() {
|
||||
board.set(p1, Square::Corridor);
|
||||
board.set(p2, Square::Corridor);
|
||||
|
||||
for dir1 in Vec2d::directions() {
|
||||
let p3 = p2 + dir1;
|
||||
let p4 = p3 + dir1;
|
||||
if board.get(p3) == Square::Unknown {
|
||||
if board.get(p4) == Square::Unknown {
|
||||
add_move(&mut open, arg, p2, dir1);
|
||||
if board.get(p3).is_unknown() {
|
||||
if board.get(p4).is_unknown() {
|
||||
add_move(&board, &mut open, &mut rng, p2, dir1);
|
||||
} else {
|
||||
board.set(p3, Square::Wall);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user