From 8405b70ea5f282583430b526786155b694cb6a33 Mon Sep 17 00:00:00 2001 From: David Blajda Date: Thu, 22 Aug 2019 15:02:54 +0000 Subject: :WIP: Refactor Direction enum to const. Implement pretty print --- src/main.rs | 220 ++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 176 insertions(+), 44 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3cc85ae..3232cec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,13 +18,34 @@ enum LevelBuilderError { InvalidRoomId, } -#[derive(Debug)] -enum Direction { - None = 0, - Up = 1 << 1, - Right = 1 << 2, - Down = 1 << 3, - Left = 1 << 4, +mod Direction { + pub const NONE: u8 = 0; + pub const UP: u8 = 1 << 0; + pub const RIGHT: u8 = 1 << 1; + pub const DOWN: u8 = 1 << 2; + pub const LEFT: u8 = 1 << 3; + + pub fn opposite(dir: u8) -> u8 { + match dir { + UP => DOWN, + RIGHT => LEFT, + DOWN => UP, + LEFT => RIGHT, + _ => unreachable!() + } + } + + pub fn step(dir: u8, point: &mut (u32, u32)) { + match dir { + UP => point.1 -= 1, + RIGHT => point.0 += 1, + DOWN => point.1 += 1, + LEFT => point.0 -= 1, + _ => unreachable!() + + }; + } + } struct RoomDescription { @@ -97,22 +118,30 @@ impl Region { } } + +const TILE_IS_PATH: u8 = 0x4; + #[derive(Clone, Debug)] struct Tile { id: u16, room: RoomId, + flags: u8, + connections: u8, } #[derive(Clone)] struct TileTemplate { id: u16, + connections: u8 } impl TileTemplate { fn into_tile(&self, room: RoomId) -> Tile { Tile { + connections: self.connections, id: self.id, room: room, + flags: 0, } } } @@ -158,7 +187,7 @@ fn place_template(level: &mut Level, template: &RoomTemplate, x: u32, y: u32) -> for row in 0..template.height() { for column in 0..template.width() { region.set(column + x, row + y, - template.get(row, column)?.clone().map(|t| t.into_tile(room_id)))?; + template.get(column, row)?.clone().map(|t| t.into_tile(room_id)))?; } } @@ -173,21 +202,17 @@ fn tunnel(level: &mut Level, from: (u32, u32), to: (u32, u32), println!("{:?} {:?}", diff, abs_diff); println!("{:?} {:?}", from, to); let mut direction = if abs_diff.1 < abs_diff.0 { - if diff.0 < 0 { Direction::Right } else { Direction::Left } + if diff.0 < 0 { Direction::RIGHT } else { Direction::LEFT } } else { - if diff.1 < 0 { Direction::Down } else { Direction::Up } + if diff.1 < 0 { Direction::DOWN } else { Direction::UP } }; println!("{:?}", direction); /*TODO: Pick an random number of steps*/ let mut steps = match direction { - Direction::Right | Direction::Left => { - rng.gen_range(0, abs_diff.0) + 1 - }, - Direction::Up | Direction::Down => { - rng.gen_range(0, abs_diff.1) + 1 - }, - Direction::None => unreachable!("direction is somehow None") + Direction::RIGHT | Direction::LEFT => rng.gen_range(0, abs_diff.0) + 1, + Direction::UP | Direction::DOWN => rng.gen_range(0, abs_diff.1) + 1, + _ => 0 }; /*Start tunneling*/ @@ -195,24 +220,33 @@ fn tunnel(level: &mut Level, from: (u32, u32), to: (u32, u32), while !connected { while steps > 0 { /*TODO: Locate possible link neighbours*/ + let connection = direction; + let opposite = Direction::opposite(connection); + let tile = level.region.get_mut(from.0, from.1)?; + if let Some(tile) = tile { + tile.connections = tile.connections | connection; + } + match direction { - Direction::Up => from.1 = from.1 - 1, - Direction::Right => from.0 = from.0 + 1, - Direction::Down => from.1 = from.1 + 1, - Direction::Left => from.0 = from.0 - 1, + Direction::UP => from.1 = from.1 - 1, + Direction::RIGHT => from.0 = from.0 + 1, + Direction::DOWN => from.1 = from.1 + 1, + Direction::LEFT => from.0 = from.0 - 1, _ => {}, } - let tile = level.region.get(from.0, from.1)?; + + let tile = level.region.get_mut(from.0, from.1)?; match tile { Some(tile) => { if tile.room != from_id { + tile.connections = tile.connections | opposite; connected = true; break; } }, None => { println!("SET -> {} {}", from.0, from.1); - level.region.set(from.0, from.1, Some(Tile { id: 1, room: from_id})); + level.region.set(from.0, from.1, Some(Tile { id: 1, room: from_id, flags: TILE_IS_PATH, connections: opposite})); } } steps = steps - 1; @@ -222,17 +256,17 @@ fn tunnel(level: &mut Level, from: (u32, u32), to: (u32, u32), let abs_diff = (i64::abs(diff.0), i64::abs(diff.1)); direction = if abs_diff.1 < abs_diff.0 { - if -1 < diff.0 { Direction::Left } else { Direction::Right } + if -1 < diff.0 { Direction::LEFT } else { Direction::RIGHT } } else { - if -1 < diff.1 { Direction::Up } else { Direction::Down } + if -1 < diff.1 { Direction::UP } else { Direction::DOWN } }; println!("{:?}", direction); steps = match direction { - Direction::Right | Direction::Left => { + Direction::RIGHT | Direction::LEFT => { if abs_diff.0 == 0 { 1 } else { rng.gen_range(0, abs_diff.0) + 1 } }, - Direction::Up | Direction::Down => { + Direction::UP | Direction::DOWN => { if abs_diff.1 == 0 { 1 } else { rng.gen_range(0, abs_diff.1) + 1 } }, _ => 0 @@ -254,15 +288,15 @@ fn connect_rooms(level: &mut Level, from_id: RoomId, to_id: Roo let abs_diff = (i32::abs(diff.0), i32::abs(diff.1)); let direction = if abs_diff.1 < abs_diff.0 { - if -1 < diff.0 { Direction::Left } else { Direction::Right } + if -1 < diff.0 { Direction::LEFT } else { Direction::RIGHT } } else { - if diff.1 < 0 { Direction::Down } else { Direction::Up } + if diff.1 < 0 { Direction::DOWN } else { Direction::UP } }; println!("{:?}", direction); /*Find a suitable starting location*/ match direction { - Direction::Up => { + Direction::UP => { while candidates.len() < 1 { let mut y = from.y; for x in from.x..(from.x + from.width) { @@ -273,7 +307,7 @@ fn connect_rooms(level: &mut Level, from_id: RoomId, to_id: Roo y = y + 1; } }, - Direction::Right => { + Direction::RIGHT => { while candidates.len() < 1 { let mut x = from.x + from.width - 1; for y in from.y..(from.y + from.height) { @@ -284,7 +318,7 @@ fn connect_rooms(level: &mut Level, from_id: RoomId, to_id: Roo x = x - 1; } }, - Direction::Down => { + Direction::DOWN => { while candidates.len() < 1 { let mut y = from.y + from.height - 1; for x in from.x..(from.x + from.width) { @@ -295,7 +329,7 @@ fn connect_rooms(level: &mut Level, from_id: RoomId, to_id: Roo y = y - 1; } }, - Direction::Left => { + Direction::LEFT => { while candidates.len() < 1 { let mut x = from.x; for y in from.y..(from.y + from.height) { @@ -306,11 +340,10 @@ fn connect_rooms(level: &mut Level, from_id: RoomId, to_id: Roo x = x + 1; } }, - Direction::None => unreachable!("direction is somehow None") + _ => unreachable!() } - /*TODO: Pick a random point*/ - let mut pos = candidates[rng.gen_range(0, candidates.len())]; + let pos = candidates[rng.gen_range(0, candidates.len())]; tunnel(level, pos, to_center, from_id, rng) } @@ -344,10 +377,71 @@ fn create_deadend(level: &mut Level, rng: &mut R) -> Result<(), Ok(()) } +fn random_walk(level: &mut Level, rng: &mut R) -> Result<(), u32> { + let mut iterations = 0; + const max_iterations: u32 = 128; + + let mut neighbours = 0; + let region = &mut level.region; + let mut options = [0; 4]; + let mut x = 0; + let mut y = 0; + + while neighbours <= 0 && iterations < max_iterations { + neighbours = 0; + x = rng.gen_range(0, region.width() - 4) + 2; + y = rng.gen_range(0, region.height() - 4) + 2; + + if let Some(tile) = region.get(x, y)? { + if tile.flags & TILE_IS_PATH != 0 { + if region.get(x, y - 1)?.is_none() { + options[neighbours] = Direction::UP; + neighbours = neighbours + 1; + } + + if region.get(x + 1, y)?.is_none() { + options[neighbours] = Direction::RIGHT; + neighbours = neighbours + 1; + } + + if region.get(x, y + 1)?.is_none() { + options[neighbours] = Direction::DOWN; + neighbours = neighbours + 1; + } + + if region.get(x - 1, y)?.is_none() { + options[neighbours] = Direction::LEFT; + neighbours = neighbours + 1; + } + } + } + iterations = iterations + 1; + } + + if neighbours <= 0 { + return Err(1); + } + + let direction = options[rng.gen_range(0, neighbours)]; + println!("dir x {} y {} -> {}",x, y, direction); + if let Some(tile) = region.get_mut(x, y)? { + println!("is some"); + tile.connections |= direction; + println!("{}", tile.connections); + }; + + let mut pos = (x, y); + Direction::step(direction, &mut pos); + println!("{:?}", &mut pos); + + region.set(pos.0, pos.1, Some(Tile { id: 1, room: 8, flags: TILE_IS_PATH, connections: Direction::opposite(direction)})); + let mut iterations = rng.gen_range(0, 2); + + Ok(()) +} fn print_level(level: &Level) { let region = &level.region; - for y in 0..region.height() { for x in 0..region.width() { let tile = region.get(x, y).unwrap(); @@ -360,6 +454,33 @@ fn print_level(level: &Level) { } } +/*Requires additonal info for proper rendering*/ +fn print_level2(level: &Level) { + + let region = &level.region; + + for x in 0..region.width() { print!(" _"); } + println!(""); + + for y in 0..region.height() { + for x in 0..region.width() { + if x == 0 { print!("|");} + let tile = region.get(x, y).unwrap(); + match tile { + Some(tile) => { + if tile.connections & Direction::DOWN == 0 { print!("_") } else { print!(" ") } + if tile.connections & Direction::RIGHT == 0 { print!("|") } else { print!(" ") } + }, + None => print!("_|"), + } + + //if x == 0 { print!("_|"); } else { print!("_|"); } + } + println!(""); + } + +} + /* impl LevelBuilder { @@ -405,21 +526,30 @@ fn main() { println!("Hello, world!"); let mut thread_rng = thread_rng(); //18 - let mut rng = SmallRng::from_seed([18;16]); + let mut rng = SmallRng::from_seed([19;16]); let mut template:VecRegion> = Region::new_with(3, 3); - let mut level: VecRegion> = Region::new_with(15, 10); + use Direction::{UP, DOWN, LEFT, RIGHT}; + template.set(0, 0, Some(TileTemplate { id: 1, connections: RIGHT | DOWN})); + template.set(1, 0, Some(TileTemplate { id: 1, connections: RIGHT | DOWN | LEFT})); + template.set(2, 0, Some(TileTemplate { id: 1, connections: DOWN | LEFT})); + + template.set(0, 1, Some(TileTemplate { id: 1, connections: UP | RIGHT | DOWN})); + template.set(1, 1, Some(TileTemplate { id: 1, connections: UP | RIGHT | DOWN | LEFT})); + template.set(2, 1, Some(TileTemplate { id: 1, connections: UP | DOWN | LEFT})); + + template.set(0, 2, Some(TileTemplate { id: 1, connections: UP | RIGHT})); + template.set(1, 2, Some(TileTemplate { id: 1, connections: UP | RIGHT | LEFT})); + template.set(2, 2, Some(TileTemplate { id: 1, connections: UP | LEFT})); + + + let mut level: VecRegion> = Region::new_with(15, 11); let mut level = Level { rooms: Vec::new(), region: Box::new(level), }; - for row in 0..3 { - for col in 0..3 { - template.set(row, col, Some(TileTemplate { id: 1})); - } - } let res = place_template(&mut level, &mut template, 0, 0); let res = place_template(&mut level, &mut template, 3, 7); let res = place_template(&mut level, &mut template, 5, 2); @@ -429,8 +559,10 @@ fn main() { let res = connect_rooms(&mut level, 1, 2, &mut rng); let res = connect_rooms(&mut level, 3, 2, &mut rng); create_deadend(&mut level, &mut rng); + random_walk(&mut level, &mut rng); //create_deadend(&mut level, &mut rng); println!("{:?}", res); print_level(&level); + print_level2(&level); //println!("{:?}", level); } -- cgit v1.2.3