From 42e06126fc8ad6b17d3e4c1c082fb7feb36d067f Mon Sep 17 00:00:00 2001 From: David Blajda Date: Sat, 24 Aug 2019 02:49:25 +0000 Subject: :WIP: slim tunnelling --- src/main.rs | 188 ++++++++++++++++-------------------------------------------- 1 file changed, 50 insertions(+), 138 deletions(-) (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs index 12d0208..fe32d14 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,14 +3,6 @@ use rand::thread_rng; use rand::rngs::SmallRng; -/*Notes - * - * It's entirely possible that the compiler inlined some functions - * so I dont need to to strive 1-to-1 parity. - * Tunelling procedure performed in deadend and connect rooms - * can be placed in a separate definition. - */ - type RoomId = u32; enum LevelBuilderError { @@ -18,6 +10,14 @@ enum LevelBuilderError { InvalidRoomId, } +#[derive(Debug)] +enum Error { + OutOfBounds, + MaximumIterations, + NonEmpty, + InvalidRoomId, +} + mod Direction { pub const UP: u8 = 1 << 0; @@ -66,9 +66,9 @@ struct LevelBuilder { } trait Region { fn width(&self) -> u32; fn height(&self) -> u32; - fn set(&mut self, x: u32, y: u32, value: T) -> Result<(), u32>; - fn get(&self, x: u32, y: u32) -> Result<&T, u32>; - fn get_mut(&mut self, x: u32, y: u32) -> Result<&mut T, u32>; + fn set(&mut self, x: u32, y: u32, value: T) -> Result<(), Error>; + fn get(&self, x: u32, y: u32) -> Result<&T, Error>; + fn get_mut(&mut self, x: u32, y: u32) -> Result<&mut T, Error>; } struct VecRegion { @@ -86,26 +86,26 @@ impl Region for VecRegion { self.height } - fn set(&mut self, x: u32, y: u32, value: T) -> Result<(), u32> { + fn set(&mut self, x: u32, y: u32, value: T) -> Result<(), Error> { if x >= self.width || y >= self.height { - return Err(1); + return Err(Error::OutOfBounds); } self.inner[(y * self.width + x) as usize] = value; Ok(()) } - fn get(&self, x: u32, y:u32) -> Result<&T, u32> { + fn get(&self, x: u32, y:u32) -> Result<&T, Error> { if x >= self.width || y >= self.height { - return Err(1); + return Err(Error::OutOfBounds); } Ok(&self.inner[(y * self.width + x) as usize]) } - fn get_mut(&mut self, x: u32, y: u32) -> Result<&mut T, u32> { + fn get_mut(&mut self, x: u32, y: u32) -> Result<&mut T, Error> { if x >= self.width || y >= self.height { - return Err(1); + return Err(Error::OutOfBounds); } Ok(&mut self.inner[(y * self.width + x) as usize]) @@ -172,19 +172,19 @@ struct Level { tunnels: u32, } -fn place_template(level: &mut Level, template: &RoomTemplate, x: u32, y: u32) -> Result<(RoomId), (u32)> { +fn place_template(level: &mut Level, template: &RoomTemplate, x: u32, y: u32) -> Result { let region = &mut level.region; let width = region.width(); let height = region.height(); if x >= width || x + template.width() > width || y >= height || y + template.height() > height { - return Err(1); + return Err(Error::OutOfBounds); } for row in 0..template.height() { for column in 0..template.width() { if region.get(column + x, row + y)?.is_some() { - return Err(2); + return Err(Error::NonEmpty); } } } @@ -208,29 +208,28 @@ fn place_template(level: &mut Level, template: &RoomTemplate, x: u32, y: u32) -> Ok(room_id) } -fn tunnel(level: &mut Level, from: (u32, u32), to: (u32, u32), owner: Owner, rng: &mut R) -> Result<(), u32> { +fn tunnel(level: &mut Level, from: (u32, u32), to: (u32, u32), owner: Owner, rng: &mut R) -> Result<(), Error> { let mut from = from; - let diff: (i64, i64) = (from.0 as i64 - to.0 as i64, from.1 as i64 - to.1 as i64); - let abs_diff = (i64::abs(diff.0), i64::abs(diff.1)); - let mut direction = if abs_diff.1 < abs_diff.0 { - if diff.0 < 0 { Direction::RIGHT } else { Direction::LEFT } - } else { - if diff.1 < 0 { Direction::DOWN } else { Direction::UP } - }; - - /*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, - _ => 0 - }; - - /*Start tunneling*/ let mut connected = false; + while !connected { + + let diff: (i64, i64) = (from.0 as i64 - to.0 as i64, from.1 as i64 - to.1 as i64); + let abs_diff = (i64::abs(diff.0), i64::abs(diff.1)); + let mut direction = if abs_diff.1 < abs_diff.0 { + if diff.0 < 0 { Direction::RIGHT } else { Direction::LEFT } + } else { + if diff.1 < 0 { Direction::DOWN } else { Direction::UP } + }; + + 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, + _ => 1 + }; + 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)?; @@ -238,13 +237,7 @@ fn tunnel(level: &mut Level, from: (u32, u32), to: (u32, u32), 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, - _ => {}, - } + from = Direction::step_towards(direction, from).unwrap(); let tile = level.region.get_mut(from.0, from.1)?; match tile { @@ -261,36 +254,17 @@ fn tunnel(level: &mut Level, from: (u32, u32), to: (u32, u32), } steps = steps - 1; } - - let diff: (i64, i64) = (from.0 as i64 - to.0 as i64, from.1 as i64 - to.1 as i64); - 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 } - } else { - if -1 < diff.1 { Direction::UP } else { Direction::DOWN } - }; - - steps = match direction { - Direction::RIGHT | Direction::LEFT => { - if abs_diff.0 == 0 { 1 } else { rng.gen_range(0, abs_diff.0) + 1 } - }, - Direction::UP | Direction::DOWN => { - if abs_diff.1 == 0 { 1 } else { rng.gen_range(0, abs_diff.1) + 1 } - }, - _ => 0 - }; } Ok(()) } -fn connect_rooms(level: &mut Level, from_id: RoomId, to_id: RoomId, rng: &mut R) -> Result<(), u32> { +fn connect_rooms(level: &mut Level, from_id: RoomId, to_id: RoomId, rng: &mut R) -> Result<(), Error> { let mut candidates = Vec::new(); - let from = level.rooms.get(from_id as usize).ok_or(2 as u32)?; + let from = level.rooms.get(from_id as usize).ok_or(Error::InvalidRoomId)?; let from_center = (from.x + (from.width / 2), from.y + (from.height / 2)); - let to = level.rooms.get(to_id as usize).ok_or(2 as u32)?; + let to = level.rooms.get(to_id as usize).ok_or(Error::InvalidRoomId)?; let to_center = (to.x + (to.width / 2), to.y + (to.height / 2)); let diff: (i32, i32) = (from_center.0 as i32 - to_center.0 as i32, from_center.1 as i32 - to_center.1 as i32); @@ -355,7 +329,7 @@ fn connect_rooms(level: &mut Level, from_id: RoomId, to_id: Roo tunnel(level, pos, to_center, Owner::Room(from_id), rng) } -fn create_deadend(level: &mut Level, rng: &mut R) -> Result<(), u32> { +fn create_deadend(level: &mut Level, rng: &mut R) -> Result<(), Error> { let mut attempts = 0; loop { let x = rng.gen_range(0, level.region.width() - 3); @@ -410,7 +384,7 @@ fn empty_neighbours(level: &Level, x: u32, y:u32, options: &mut [u8; 4], neighbo } } -fn random_walk(level: &mut Level, rng: &mut R) -> Result<(), u32> { +fn random_walk(level: &mut Level, rng: &mut R) -> Result<(), Error> { let mut iterations = 0; const max_iterations: u32 = 128; @@ -436,7 +410,7 @@ fn random_walk(level: &mut Level, rng: &mut R) -> Result<(), u3 } if neighbours <= 0 { - return Err(1); + return Err(Error::NonEmpty); } let direction = options[rng.gen_range(0, neighbours)]; @@ -490,21 +464,6 @@ fn random_walk(level: &mut Level, rng: &mut R) -> Result<(), u3 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(); - match tile { - Some(tile) => print!("{:?}", tile.owner), - None => print!("+"), - } - } - println!(""); - } -} - -/*Requires additonal info for proper rendering*/ fn pretty_print(level: &Level) { let region = &level.region; @@ -523,57 +482,12 @@ fn pretty_print(level: &Level) { }, None => print!("_|"), } - - //if x == 0 { print!("_|"); } else { print!("_|"); } } println!(""); } - } -/* -impl LevelBuilder { - - fn build(self) -> Result { - Ok(0) - } - - fn add_room(&self, description: RoomDescription, x: u32, y: u32) -> Result { - if x > self - Ok(0) - } - - fn connect_rooms(&self, from: RoomId, to: RoomId) -> Result<(), LevelBuilderError> { - Ok(()) - } -} - -/* -LevelBuilder::new() - .add_room(r1) - .add_room(r2) - .connect(r1, r2) - .add_room(r3) - .connect(r2, r3) - .add_terminals() - .build().unwrap() - */ - -fn add_room(room_desc: u32) -> Result { - Ok(0) -} - -fn connect_rooms(from: u32, to: u32) -> Result { - Ok(0) -} - -fn add_terminals() -> Result { - Ok(0) -} -*/ - - -fn random_dungeon(templates: Vec>>, mut rng: &mut R) -> Result { +fn random_dungeon(templates: Vec>>, mut rng: &mut R) -> Result { let mut region: VecRegion> = Region::new_with(15, 15); let mut level = Level { rooms: Vec::new(), @@ -637,19 +551,19 @@ fn random_dungeon(templates: Vec let mut deadends = rng.gen_range(0, 3) + 1; while deadends > 0 { - create_deadend(&mut level, &mut rng); + create_deadend(&mut level, &mut rng)?; deadends += -1; } - random_walk(&mut level, &mut rng); - random_walk(&mut level, &mut rng); - random_walk(&mut level, &mut rng); + random_walk(&mut level, &mut rng)?; + random_walk(&mut level, &mut rng)?; + random_walk(&mut level, &mut rng)?; Ok(level) } + fn main() { - println!("Hello, world!"); let mut thread_rng = thread_rng(); //18 let mut rng = SmallRng::from_seed([14;16]); @@ -681,7 +595,6 @@ fn main() { let res = place_template(&mut level, &mut template, 3, 7); let res = place_template(&mut level, &mut template, 5, 2); let res = place_template(&mut level, &mut template, 8, 7); - print_level(&level); let res = connect_rooms(&mut level, 0, 1, &mut rng); let res = connect_rooms(&mut level, 2, 1, &mut rng); let res = connect_rooms(&mut level, 3, 2, &mut rng); @@ -692,7 +605,6 @@ fn main() { random_walk(&mut level, &mut rng); //create_deadend(&mut level, &mut rng); println!("{:?}", res); - print_level(&level); pretty_print(&level); let l = random_dungeon(vec!(template), &mut rng).unwrap(); -- cgit v1.2.3