summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorDavid Blajda <blajda@hotmail.com>2019-08-24 02:49:25 +0000
committerDavid Blajda <blajda@hotmail.com>2019-08-24 02:49:25 +0000
commit42e06126fc8ad6b17d3e4c1c082fb7feb36d067f (patch)
tree54ef9ee3988301789765d63c25f5ce283dd7ac1b /src/main.rs
parent4011712aeaba558ac8d9f75aa79921efa67c5f4f (diff)
:WIP: slim tunnelling
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs188
1 files changed, 50 insertions, 138 deletions
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<T> {
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<T> {
@@ -86,26 +86,26 @@ impl<T> Region<T> for VecRegion<T> {
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<RoomId, Error> {
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<R: Rng + ?Sized>(level: &mut Level, from: (u32, u32), to: (u32, u32), owner: Owner, rng: &mut R) -> Result<(), u32> {
+fn tunnel<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(level: &mut Level, from_id: RoomId, to_id: RoomId, rng: &mut R) -> Result<(), u32> {
+fn connect_rooms<R: Rng + ?Sized>(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<R: Rng + ?Sized>(level: &mut Level, from_id: RoomId, to_id: Roo
tunnel(level, pos, to_center, Owner::Room(from_id), rng)
}
-fn create_deadend<R: Rng + ?Sized>(level: &mut Level, rng: &mut R) -> Result<(), u32> {
+fn create_deadend<R: Rng + ?Sized>(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<R: Rng + ?Sized>(level: &mut Level, rng: &mut R) -> Result<(), u32> {
+fn random_walk<R: Rng + ?Sized>(level: &mut Level, rng: &mut R) -> Result<(), Error> {
let mut iterations = 0;
const max_iterations: u32 = 128;
@@ -436,7 +410,7 @@ fn random_walk<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<u32, LevelBuilderError> {
- Ok(0)
- }
-
- fn add_room(&self, description: RoomDescription, x: u32, y: u32) -> Result<RoomId, LevelBuilderError> {
- 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<u32, u32> {
- Ok(0)
-}
-
-fn connect_rooms(from: u32, to: u32) -> Result<u32, u32> {
- Ok(0)
-}
-
-fn add_terminals() -> Result<u32, u32> {
- Ok(0)
-}
-*/
-
-
-fn random_dungeon<R: Rng + ?Sized>(templates: Vec<VecRegion<Option<TileTemplate>>>, mut rng: &mut R) -> Result<Level, u32> {
+fn random_dungeon<R: Rng + ?Sized>(templates: Vec<VecRegion<Option<TileTemplate>>>, mut rng: &mut R) -> Result<Level, Error> {
let mut region: VecRegion<Option<Tile>> = Region::new_with(15, 15);
let mut level = Level {
rooms: Vec::new(),
@@ -637,19 +551,19 @@ fn random_dungeon<R: Rng + ?Sized>(templates: Vec<VecRegion<Option<TileTemplate>
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();