Adapt methods from dual maze to original maze.
This commit is contained in:
		@@ -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);
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user