summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Blajda <blajda@hotmail.com>2019-08-23 01:50:10 +0000
committerDavid Blajda <blajda@hotmail.com>2019-08-23 01:50:10 +0000
commitc93a6a4743af9ee72f12bb18b210f9523c6c50d1 (patch)
tree9025718444f08b5b6f51afc06679dd99fa9cd8fa
parent8405b70ea5f282583430b526786155b694cb6a33 (diff)
:WIP: Implement random walks
-rw-r--r--src/main.rs110
1 files changed, 91 insertions, 19 deletions
diff --git a/src/main.rs b/src/main.rs
index 3232cec..7bba3d8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -18,6 +18,7 @@ enum LevelBuilderError {
InvalidRoomId,
}
+
mod Direction {
pub const NONE: u8 = 0;
pub const UP: u8 = 1 << 0;
@@ -25,6 +26,12 @@ mod Direction {
pub const DOWN: u8 = 1 << 2;
pub const LEFT: u8 = 1 << 3;
+ #[derive(Debug)]
+ pub enum Error {
+ Underflow,
+ Overflow,
+ }
+
pub fn opposite(dir: u8) -> u8 {
match dir {
UP => DOWN,
@@ -35,15 +42,16 @@ mod Direction {
}
}
- 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,
+ pub fn step_towards(dir: u8, point: (u32, u32)) -> Result<(u32, u32), Error> {
+ let p = match dir {
+ UP => if point.1 > 0 { (point.0, point.1 - 1) } else { return Err(Error::Underflow) },
+ RIGHT => (point.0 + 1, point.1),
+ DOWN => (point.0, point.1 + 1),
+ LEFT => if point.0 > 0 { (point.0 - 1, point.1) } else { return Err(Error::Underflow) },
_ => unreachable!()
};
+ Ok(p)
}
}
@@ -377,26 +385,50 @@ fn create_deadend<R: Rng + ?Sized>(level: &mut Level, rng: &mut R) -> Result<(),
Ok(())
}
+fn empty_neighbours(level: &Level, x: u32, y:u32, options: &mut [u8; 4], neighbours: &mut usize) {
+ let region = &level.region;
+ if y > 0 && region.get(x, y - 1).unwrap().is_none() {
+ options[*neighbours] = Direction::UP;
+ *neighbours += 1;
+ }
+
+ if x + 1 < region.width() && region.get(x + 1, y).unwrap().is_none() {
+ options[*neighbours] = Direction::RIGHT;
+ *neighbours += 1;
+ }
+
+ if y + 1 < region.height() && region.get(x, y + 1).unwrap().is_none() {
+ options[*neighbours] = Direction::DOWN;
+ *neighbours += 1;
+ }
+
+ if x > 0 && region.get(x - 1, y).unwrap().is_none() {
+ options[*neighbours] = Direction::LEFT;
+ *neighbours += 1;
+ }
+}
+
fn random_walk<R: Rng + ?Sized>(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;
+ x = rng.gen_range(0, level.region.width() - 4) + 2;
+ y = rng.gen_range(0, level.region.height() - 4) + 2;
- if let Some(tile) = region.get(x, y)? {
+ if let Some(tile) = level.region.get(x, y)? {
if tile.flags & TILE_IS_PATH != 0 {
+ empty_neighbours(level, x, y, &mut options, &mut neighbours);
+ /*
if region.get(x, y - 1)?.is_none() {
options[neighbours] = Direction::UP;
- neighbours = neighbours + 1;
+ neighbours += 1;
}
if region.get(x + 1, y)?.is_none() {
@@ -413,6 +445,7 @@ fn random_walk<R: Rng + ?Sized>(level: &mut Level, rng: &mut R) -> Result<(), u3
options[neighbours] = Direction::LEFT;
neighbours = neighbours + 1;
}
+ */
}
}
iterations = iterations + 1;
@@ -424,19 +457,56 @@ fn random_walk<R: Rng + ?Sized>(level: &mut Level, rng: &mut R) -> Result<(), u3
let direction = options[rng.gen_range(0, neighbours)];
println!("dir x {} y {} -> {}",x, y, direction);
- if let Some(tile) = region.get_mut(x, y)? {
+ if let Some(tile) = level.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)}));
+ pos = Direction::step_towards(direction, pos).unwrap();
+ level.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);
+ while iterations >= 0 {
+ neighbours = 0;
+ empty_neighbours(level, pos.0, pos.1, &mut options, &mut neighbours);
+
+ if neighbours <= 0 {
+ return Ok(());
+ }
+
+ let direction = options[rng.gen_range(0, neighbours)];
+ let mut length = rng.gen_range(0, 2) + 1;
+ println!("len {}", length);
+ while length > 0 {
+ let old_pos = pos.clone();
+ let m_pos = Direction::step_towards(direction, pos);
+ if let Err(_) = m_pos {
+ break;
+ } else {
+ pos = m_pos.unwrap();
+ }
+
+ match level.region.get(pos.0, pos.1) {
+ Ok(tile) => {
+ if tile.is_none() {
+ level.region.set(pos.0, pos.1, Some(Tile { id: 1, room: 8, flags: TILE_IS_PATH, connections: Direction::opposite(direction)}));
+ if let Some(tile) = level.region.get_mut(old_pos.0, old_pos.1)? {
+ tile.connections |= direction;
+ }
+ }
+ },
+ Err(_) => {
+ pos = old_pos;
+ length = 0;
+ }
+ }
+ length += -1;
+ }
+ iterations += -1;
+ }
+
Ok(())
}
@@ -455,7 +525,7 @@ fn print_level(level: &Level) {
}
/*Requires additonal info for proper rendering*/
-fn print_level2(level: &Level) {
+fn pretty_print(level: &Level) {
let region = &level.region;
@@ -526,7 +596,7 @@ fn main() {
println!("Hello, world!");
let mut thread_rng = thread_rng();
//18
- let mut rng = SmallRng::from_seed([19;16]);
+ let mut rng = SmallRng::from_seed([18;16]);
let mut template:VecRegion<Option<TileTemplate>> = Region::new_with(3, 3);
@@ -560,9 +630,11 @@ fn main() {
let res = connect_rooms(&mut level, 3, 2, &mut rng);
create_deadend(&mut level, &mut rng);
random_walk(&mut level, &mut rng);
+ random_walk(&mut level, &mut rng);
+ random_walk(&mut level, &mut rng);
//create_deadend(&mut level, &mut rng);
println!("{:?}", res);
print_level(&level);
- print_level2(&level);
+ pretty_print(&level);
//println!("{:?}", level);
}