summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Blajda <blajda@hotmail.com>2019-08-22 15:02:54 +0000
committerDavid Blajda <blajda@hotmail.com>2019-08-22 15:02:54 +0000
commit8405b70ea5f282583430b526786155b694cb6a33 (patch)
treedb988386666ea125c66b9a9dffb88328028f4b15 /src
parent71a2e56d0fd9aa5b1f62fe5c41dee6551107c840 (diff)
:WIP: Refactor Direction enum to const. Implement pretty print
Diffstat (limited to 'src')
-rw-r--r--src/main.rs220
1 files 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<T: Default> Region<T> {
}
}
+
+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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(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<R: Rng + ?Sized>(level: &mut Level, rng: &mut R) -> Result<(),
Ok(())
}
+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;
+
+ 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<Option<TileTemplate>> = Region::new_with(3, 3);
- let mut level: VecRegion<Option<Tile>> = 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<Option<Tile>> = 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);
}