Factor out two-dimensional arithmetic from maze.
This commit is contained in:
parent
610c864cd9
commit
c3ca8888fd
@ -8,6 +8,10 @@ use rand::thread_rng;
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
use pixelfoo::color::Color;
|
use pixelfoo::color::Color;
|
||||||
|
use pixelfoo::p2;
|
||||||
|
use pixelfoo::point2::Point2;
|
||||||
|
use pixelfoo::v2;
|
||||||
|
use pixelfoo::vec2::Vec2;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
enum Square {
|
enum Square {
|
||||||
@ -37,17 +41,17 @@ fn send<T: Write>(w: &mut T, board: &Board) -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Board {
|
impl Board {
|
||||||
fn new(x_size: i32, y_size: i32, x_maze_size: i32, y_maze_size: i32) -> Board {
|
fn new(board_size: Vec2, maze_size: Vec2) -> Board {
|
||||||
Board(
|
Board(
|
||||||
(0..y_size)
|
(0..board_size.y)
|
||||||
.map(move |y| {
|
.map(move |y| {
|
||||||
(0..x_size)
|
(0..board_size.x)
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
if x < x_maze_size && y < y_maze_size {
|
if x < maze_size.x && y < maze_size.y {
|
||||||
if x == 0
|
if x == 0
|
||||||
|| x == x_maze_size - 1
|
|| x == maze_size.x - 1
|
||||||
|| y == 0
|
|| y == 0
|
||||||
|| y == y_maze_size - 1
|
|| y == maze_size.y - 1
|
||||||
|| (x % 2 == 0 && y % 2 == 0)
|
|| (x % 2 == 0 && y % 2 == 0)
|
||||||
{
|
{
|
||||||
Square::Wall
|
Square::Wall
|
||||||
@ -63,23 +67,21 @@ impl Board {
|
|||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
fn get(&self, pos: (i32, i32)) -> Square {
|
fn get(&self, pos: Point2) -> Square {
|
||||||
let (x, y) = pos;
|
self.0[pos.y as usize][pos.x as usize]
|
||||||
self.0[y as usize][x as usize]
|
|
||||||
}
|
}
|
||||||
fn set(&mut self, pos: (i32, i32), sq: Square) {
|
fn set(&mut self, pos: Point2, sq: Square) {
|
||||||
let (x, y) = pos;
|
self.0[pos.y as usize][pos.x as usize] = sq;
|
||||||
self.0[y as usize][x as usize] = sq;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Move {
|
struct Move {
|
||||||
from: (i32, i32),
|
from: Point2,
|
||||||
dir: (i32, i32),
|
dir: Vec2,
|
||||||
prio: i32,
|
prio: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_move(open: &mut Vec<Move>, arg: isize, from: (i32, i32), dir: (i32, i32)) {
|
fn add_move(open: &mut Vec<Move>, arg: isize, from: Point2, dir: Vec2) {
|
||||||
open.push(Move { from, dir, prio: 0 });
|
open.push(Move { from, dir, prio: 0 });
|
||||||
open.sort_unstable_by(|Move { prio: pa, .. }, Move { prio: pb, .. }| pa.cmp(pb));
|
open.sort_unstable_by(|Move { prio: pa, .. }, Move { prio: pb, .. }| pa.cmp(pb));
|
||||||
}
|
}
|
||||||
@ -101,12 +103,14 @@ fn main() -> std::io::Result<()> {
|
|||||||
let delay = Duration::new(0, (1_000_000_000.0 * t_frame) as u32);
|
let delay = Duration::new(0, (1_000_000_000.0 * t_frame) as u32);
|
||||||
let mut t_wait = 0.0; // s
|
let mut t_wait = 0.0; // s
|
||||||
|
|
||||||
let x_size = x_size as i32;
|
let board_size = v2!(x_size as i32, y_size as i32);
|
||||||
let y_size = y_size as i32;
|
// round down to odd size for maze
|
||||||
let x_maze_size = (x_size - 1) / 2 * 2 + 1;
|
let maze_size = v2!(
|
||||||
let y_maze_size = (y_size - 1) / 2 * 2 + 1;
|
(board_size.x - 1) / 2 * 2 + 1,
|
||||||
let x_maze_mid = (x_maze_size - 1) / 4 * 2 + 1;
|
(board_size.y - 1) / 2 * 2 + 1
|
||||||
let y_maze_mid = (y_maze_size - 1) / 4 * 2 + 1;
|
);
|
||||||
|
// pick odd position at or near the middle
|
||||||
|
let maze_mid = p2!((maze_size.x - 1) / 4 * 2 + 1, (maze_size.y - 1) / 4 * 2 + 1);
|
||||||
|
|
||||||
let mut board = Board(Vec::new());
|
let mut board = Board(Vec::new());
|
||||||
let mut open = Vec::new();
|
let mut open = Vec::new();
|
||||||
@ -116,15 +120,14 @@ fn main() -> std::io::Result<()> {
|
|||||||
t_wait -= t_frame;
|
t_wait -= t_frame;
|
||||||
} else {
|
} else {
|
||||||
t_wait = 60.0; // s
|
t_wait = 60.0; // s
|
||||||
board = Board::new(x_size, y_size, x_maze_size, y_maze_size);
|
board = Board::new(board_size, maze_size);
|
||||||
|
|
||||||
// start in the middle
|
// start in the middle
|
||||||
let mid = (x_maze_mid, y_maze_mid);
|
board.set(maze_mid, Square::Corridor);
|
||||||
board.set(mid, Square::Corridor);
|
add_move(&mut open, arg, maze_mid, v2!(1, 0));
|
||||||
add_move(&mut open, arg, mid, (1, 0));
|
add_move(&mut open, arg, maze_mid, v2!(0, 1));
|
||||||
add_move(&mut open, arg, mid, (0, 1));
|
add_move(&mut open, arg, maze_mid, v2!(-1, 0));
|
||||||
add_move(&mut open, arg, mid, (-1, 0));
|
add_move(&mut open, arg, maze_mid, v2!(0, -1));
|
||||||
add_move(&mut open, arg, mid, (0, -1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,25 +153,25 @@ fn main() -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
let r = rng.gen_range(start, limit);
|
let r = rng.gen_range(start, limit);
|
||||||
let Move {
|
let Move {
|
||||||
from: (x0, y0),
|
from: p0,
|
||||||
dir: (dx, dy),
|
dir: dir0,
|
||||||
..
|
..
|
||||||
} = open.remove(r);
|
} = open.remove(r);
|
||||||
|
|
||||||
let (x1, y1) = (x0 + dx, y0 + dy);
|
let p1 = p0 + dir0;
|
||||||
let (x2, y2) = (x1 + dx, y1 + dy);
|
let p2 = p1 + dir0;
|
||||||
if board.get((x1, y1)) == Square::Unknown {
|
if board.get(p1) == Square::Unknown {
|
||||||
board.set((x1, y1), Square::Corridor);
|
board.set(p1, Square::Corridor);
|
||||||
board.set((x2, y2), Square::Corridor);
|
board.set(p2, Square::Corridor);
|
||||||
|
|
||||||
for (dx, dy) in vec![(1, 0), (0, 1), (-1, 0), (0, -1)] {
|
for dir1 in Vec2::directions() {
|
||||||
let (x3, y3) = (x2 + dx, y2 + dy);
|
let p3 = p2 + dir1;
|
||||||
let (x4, y4) = (x3 + dx, y3 + dy);
|
let p4 = p3 + dir1;
|
||||||
if board.get((x3, y3)) == Square::Unknown {
|
if board.get(p3) == Square::Unknown {
|
||||||
if board.get((x4, y4)) == Square::Unknown {
|
if board.get(p4) == Square::Unknown {
|
||||||
add_move(&mut open, arg, (x2, y2), (dx, dy));
|
add_move(&mut open, arg, p2, dir1);
|
||||||
} else {
|
} else {
|
||||||
board.set((x3, y3), Square::Wall);
|
board.set(p3, Square::Wall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,12 +180,12 @@ fn main() -> std::io::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if open.is_empty() {
|
if open.is_empty() {
|
||||||
board.set((1, 1), Square::Start);
|
board.set(p2!(1, 1), Square::Start);
|
||||||
board.set((x_maze_size - 2, y_maze_size - 2), Square::Finish);
|
board.set(p2!(maze_size.x - 2, maze_size.y - 2), Square::Finish);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut buf = Vec::with_capacity((x_size * y_size * 3) as usize);
|
let mut buf = Vec::with_capacity((board_size.x * board_size.y * 3) as usize);
|
||||||
send(&mut buf, &board)?;
|
send(&mut buf, &board)?;
|
||||||
stdout().write_all(&buf)?;
|
stdout().write_all(&buf)?;
|
||||||
stdout().flush()?;
|
stdout().flush()?;
|
||||||
|
@ -1 +1,5 @@
|
|||||||
pub mod color;
|
pub mod color;
|
||||||
|
#[macro_use]
|
||||||
|
pub mod point2;
|
||||||
|
#[macro_use]
|
||||||
|
pub mod vec2;
|
||||||
|
66
src/point2.rs
Normal file
66
src/point2.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
use crate::vec2::Vec2;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! p2 {
|
||||||
|
( $x:expr, $y:expr ) => {
|
||||||
|
Point2::new($x, $y)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Point2 {
|
||||||
|
pub x: i32,
|
||||||
|
pub y: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Point2 {
|
||||||
|
pub fn new(x: i32, y: i32) -> Point2 {
|
||||||
|
Point2 { x, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn neighbours(&self) -> Vec<Point2> {
|
||||||
|
Vec2::directions().iter().map(|v| self + v).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<Vec2> for Point2 {
|
||||||
|
type Output = Point2;
|
||||||
|
|
||||||
|
fn add(self, other: Vec2) -> Point2 {
|
||||||
|
let x = self.x + other.x;
|
||||||
|
let y = self.y + other.y;
|
||||||
|
Point2 { x, y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Add<&'a Vec2> for Point2 {
|
||||||
|
type Output = Point2;
|
||||||
|
|
||||||
|
fn add(self, other: &'a Vec2) -> Point2 {
|
||||||
|
let x = self.x + other.x;
|
||||||
|
let y = self.y + other.y;
|
||||||
|
Point2 { x, y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Add<Vec2> for &'a Point2 {
|
||||||
|
type Output = Point2;
|
||||||
|
|
||||||
|
fn add(self, other: Vec2) -> Point2 {
|
||||||
|
let x = self.x + other.x;
|
||||||
|
let y = self.y + other.y;
|
||||||
|
Point2 { x, y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Add<&'a Vec2> for &'a Point2 {
|
||||||
|
type Output = Point2;
|
||||||
|
|
||||||
|
fn add(self, other: &'a Vec2) -> Point2 {
|
||||||
|
let x = self.x + other.x;
|
||||||
|
let y = self.y + other.y;
|
||||||
|
Point2 { x, y }
|
||||||
|
}
|
||||||
|
}
|
64
src/vec2.rs
Normal file
64
src/vec2.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use std::ops::Add;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! v2 {
|
||||||
|
( $x:expr, $y:expr ) => {
|
||||||
|
Vec2::new($x, $y)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct Vec2 {
|
||||||
|
pub x: i32,
|
||||||
|
pub y: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vec2 {
|
||||||
|
pub fn new(x: i32, y: i32) -> Vec2 {
|
||||||
|
Vec2 { x, y }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn directions() -> Vec<Vec2> {
|
||||||
|
vec![v2!(1, 0), v2!(0, 1), v2!(-1, 0), v2!(0, -1)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for Vec2 {
|
||||||
|
type Output = Vec2;
|
||||||
|
|
||||||
|
fn add(self, other: Vec2) -> Vec2 {
|
||||||
|
let x = self.x + other.x;
|
||||||
|
let y = self.y + other.y;
|
||||||
|
Vec2 { x, y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Add<&'a Vec2> for Vec2 {
|
||||||
|
type Output = Vec2;
|
||||||
|
|
||||||
|
fn add(self, other: &'a Vec2) -> Vec2 {
|
||||||
|
let x = self.x + other.x;
|
||||||
|
let y = self.y + other.y;
|
||||||
|
Vec2 { x, y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Add<Vec2> for &'a Vec2 {
|
||||||
|
type Output = Vec2;
|
||||||
|
|
||||||
|
fn add(self, other: Vec2) -> Vec2 {
|
||||||
|
let x = self.x + other.x;
|
||||||
|
let y = self.y + other.y;
|
||||||
|
Vec2 { x, y }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Add<&'a Vec2> for &'a Vec2 {
|
||||||
|
type Output = Vec2;
|
||||||
|
|
||||||
|
fn add(self, other: &'a Vec2) -> Vec2 {
|
||||||
|
let x = self.x + other.x;
|
||||||
|
let y = self.y + other.y;
|
||||||
|
Vec2 { x, y }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user