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)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
enum Square {
|
enum Square {
|
||||||
Unknown,
|
Unused,
|
||||||
|
Unknown { prio: i32 },
|
||||||
Corridor,
|
Corridor,
|
||||||
Wall,
|
Wall,
|
||||||
Start,
|
Start,
|
||||||
Finish,
|
Finish,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Square {
|
||||||
|
pub fn is_unknown(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Square::Unknown { .. } => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Board(Vec<Vec<Square>>);
|
struct Board(Vec<Vec<Square>>);
|
||||||
|
|
||||||
fn send<T: Write>(w: &mut T, board: &Board) -> std::io::Result<()> {
|
fn send<T: Write>(w: &mut T, board: &Board) -> std::io::Result<()> {
|
||||||
for line in &board.0 {
|
for line in &board.0 {
|
||||||
for square in line {
|
for square in line {
|
||||||
let c = match square {
|
let c = match square {
|
||||||
Square::Unknown => Color::black(),
|
Square::Unused => Color::black(),
|
||||||
|
Square::Unknown { .. } => Color::black(),
|
||||||
Square::Corridor => Color::yellow(),
|
Square::Corridor => Color::yellow(),
|
||||||
Square::Wall => Color::darkblue(),
|
Square::Wall => Color::darkblue(),
|
||||||
Square::Start => Color::red(),
|
Square::Start => Color::red(),
|
||||||
@ -40,6 +51,12 @@ fn send<T: Write>(w: &mut T, board: &Board) -> std::io::Result<()> {
|
|||||||
w.flush()
|
w.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
enum Orientation {
|
||||||
|
Horizontal,
|
||||||
|
Vertical,
|
||||||
|
}
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
fn new(board_size: Vec2d, maze_size: Vec2d) -> Board {
|
fn new(board_size: Vec2d, maze_size: Vec2d) -> Board {
|
||||||
Board(
|
Board(
|
||||||
@ -56,10 +73,10 @@ impl Board {
|
|||||||
{
|
{
|
||||||
Square::Wall
|
Square::Wall
|
||||||
} else {
|
} else {
|
||||||
Square::Unknown
|
Square::Unknown { prio: 0 }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Square::Unknown
|
Square::Unused
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
@ -73,6 +90,81 @@ impl Board {
|
|||||||
fn set(&mut self, pos: Point2d, sq: Square) {
|
fn set(&mut self, pos: Point2d, sq: Square) {
|
||||||
self.0[pos.y as usize][pos.x as usize] = sq;
|
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 {
|
struct Move {
|
||||||
@ -81,9 +173,17 @@ struct Move {
|
|||||||
prio: i32,
|
prio: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_move(open: &mut Vec<Move>, arg: isize, from: Point2d, dir: Vec2d) {
|
fn add_move<R>(board: &Board, open: &mut Vec<Move>, rng: &mut R, from: Point2d, dir: Vec2d)
|
||||||
open.push(Move { from, dir, prio: 0 });
|
where
|
||||||
open.sort_unstable_by(|Move { prio: pa, .. }, Move { prio: pb, .. }| pa.cmp(pb));
|
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;
|
const DEFAULT_ARG: isize = 16;
|
||||||
@ -122,12 +222,19 @@ fn main() -> std::io::Result<()> {
|
|||||||
t_wait = 60.0; // s
|
t_wait = 60.0; // s
|
||||||
board = Board::new(board_size, maze_size);
|
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
|
// start in the middle
|
||||||
board.set(maze_mid, Square::Corridor);
|
board.set(maze_mid, Square::Corridor);
|
||||||
add_move(&mut open, arg, maze_mid, v2d(1, 0));
|
add_move(&board, &mut open, &mut rng, 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(0, 1));
|
||||||
add_move(&mut open, arg, maze_mid, v2d(-1, 0));
|
add_move(&board, &mut open, &mut rng, 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(0, -1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,41 +242,25 @@ fn main() -> std::io::Result<()> {
|
|||||||
let work = arg.max(1);
|
let work = arg.max(1);
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
while !open.is_empty() && count < work {
|
while !open.is_empty() && count < work {
|
||||||
let mut start = 0;
|
open.sort_unstable_by(|Move { prio: pa, .. }, Move { prio: pb, .. }| pa.cmp(pb));
|
||||||
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);
|
|
||||||
let Move {
|
let Move {
|
||||||
from: p0,
|
from: p0,
|
||||||
dir: dir0,
|
dir: dir0,
|
||||||
..
|
..
|
||||||
} = open.remove(r);
|
} = open.pop().unwrap();
|
||||||
|
|
||||||
let p1 = p0 + dir0;
|
let p1 = p0 + dir0;
|
||||||
let p2 = p1 + dir0;
|
let p2 = p1 + dir0;
|
||||||
if board.get(p1) == Square::Unknown {
|
if board.get(p1).is_unknown() {
|
||||||
board.set(p1, Square::Corridor);
|
board.set(p1, Square::Corridor);
|
||||||
board.set(p2, Square::Corridor);
|
board.set(p2, Square::Corridor);
|
||||||
|
|
||||||
for dir1 in Vec2d::directions() {
|
for dir1 in Vec2d::directions() {
|
||||||
let p3 = p2 + dir1;
|
let p3 = p2 + dir1;
|
||||||
let p4 = p3 + dir1;
|
let p4 = p3 + dir1;
|
||||||
if board.get(p3) == Square::Unknown {
|
if board.get(p3).is_unknown() {
|
||||||
if board.get(p4) == Square::Unknown {
|
if board.get(p4).is_unknown() {
|
||||||
add_move(&mut open, arg, p2, dir1);
|
add_move(&board, &mut open, &mut rng, p2, dir1);
|
||||||
} else {
|
} else {
|
||||||
board.set(p3, Square::Wall);
|
board.set(p3, Square::Wall);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user