diff options
Diffstat (limited to 'src/level_gen')
-rw-r--r-- | src/level_gen/cave_automata.rs | 4 | ||||
-rw-r--r-- | src/level_gen/display.rs | 17 | ||||
-rw-r--r-- | src/level_gen/mod.rs | 100 | ||||
-rw-r--r-- | src/level_gen/util.rs | 19 |
4 files changed, 122 insertions, 18 deletions
diff --git a/src/level_gen/cave_automata.rs b/src/level_gen/cave_automata.rs index 6a237c0303df..de584f4111ab 100644 --- a/src/level_gen/cave_automata.rs +++ b/src/level_gen/cave_automata.rs @@ -1,3 +1,4 @@ +use crate::level_gen::util::fill_outer_edges; use crate::level_gen::util::rand_initialize; use crate::types::Dimensions; use rand::Rng; @@ -61,6 +62,9 @@ pub fn generate<R: Rng + ?Sized>( for _ in 0..params.steps { step_automata(&mut cells, dimensions, params); } + + fill_outer_edges(&mut cells); + cells } diff --git a/src/level_gen/display.rs b/src/level_gen/display.rs deleted file mode 100644 index 4472bf4fe392..000000000000 --- a/src/level_gen/display.rs +++ /dev/null @@ -1,17 +0,0 @@ -use std::io::{self, Write}; - -pub fn print_generated_level<W>( - level: &Vec<Vec<bool>>, - out: &mut W, -) -> io::Result<()> -where - W: Write, -{ - for row in level { - for cell in row { - write!(out, "{}", if *cell { "X" } else { " " })?; - } - write!(out, "\n")?; - } - Ok(()) -} diff --git a/src/level_gen/mod.rs b/src/level_gen/mod.rs index 4df57a408fa8..df742bb3a1b0 100644 --- a/src/level_gen/mod.rs +++ b/src/level_gen/mod.rs @@ -1,3 +1,101 @@ +use crate::display::draw_box::BoxStyle; +use crate::display::utils::clone_times; +use crate::display::DrawWithNeighbors; +use crate::entities::entity::Entity; +use crate::entities::environment::Wall; +use crate::types::entity_map::EntityMap; +use crate::types::pos; +use itertools::Itertools; +use std::io; + pub mod cave_automata; -pub mod display; pub mod util; + +pub fn level_to_entities(level: Vec<Vec<bool>>) -> EntityMap<Box<dyn Entity>> { + let mut res: EntityMap<Box<dyn Entity>> = EntityMap::new(); + + let xmax = level.len() as i16; + let ymax = if xmax == 0 { + 0i16 + } else { + level[0].len() as i16 + }; + + let get = |mut x: i16, mut y: i16| { + if x < 0 { + x = 0; + } + if y < 0 { + y = 0; + } + if x >= xmax - 1 { + x = xmax - 1; + } + if y >= ymax - 1 { + y = ymax - 1; + } + level[x as usize][y as usize] + }; + + for x in 0..xmax { + for y in 0..ymax { + if get(x, y) { + // don't output walls that are surrounded on all 8 sides by + // walls + if (x == 0 || get(x - 1, y)) + && (y == 0 || get(x, y - 1)) + && (x == xmax - 1 || get(x + 1, y)) + && (y == ymax - 1 || get(x, y + 1)) + && ((x == 0 && y == 0) || get(x - 1, y - 1)) + && ((x == 0 && y == ymax - 1) || get(x - 1, y + 1)) + && ((x == xmax - 1 && y == 0) || get(x + 1, y - 1)) + && ((x == xmax - 1 && y == ymax - 1) || get(x + 1, y + 1)) + { + continue; + } + res.insert(Box::new(Wall::new( + pos(y as i16, x as i16), + BoxStyle::Thin, + ))); + } + } + } + + res +} + +pub fn draw_level<W: io::Write>( + level: Vec<Vec<bool>>, + out: &mut W, +) -> io::Result<()> { + if level.len() == 0 { + return Ok(()); + } + + let mut lines = clone_times::<Vec<char>, Vec<Vec<char>>>( + clone_times(' ', level[0].len() as u16), + level.len() as u16, + ); + + let em = level_to_entities(level); + + for entity in em.entities() { + let mut buf = Vec::new(); + entity.do_draw_with_neighbors( + &mut buf, + &em.neighbor_entities(entity.position()), + )?; + let buf_s = std::str::from_utf8(&buf).unwrap(); + if let Some(chr) = buf_s.chars().next() { + lines[entity.position().y as usize][entity.position().x as usize] = + chr; + } + } + + let res = lines + .iter() + .map(|line| line.iter().collect::<String>()) + .join("\n"); + + write!(out, "{}", res) +} diff --git a/src/level_gen/util.rs b/src/level_gen/util.rs index 629292c430fa..c9cd87309257 100644 --- a/src/level_gen/util.rs +++ b/src/level_gen/util.rs @@ -31,3 +31,22 @@ pub fn rand_initialize<R: Rng + ?Sized>( } ret } + +/// Fill the outer edges of a generated level with walls +pub fn fill_outer_edges(level: &mut Vec<Vec<bool>>) { + let xmax = level.len(); + if xmax == 0 { + return; + } + let ymax = level[0].len(); + + for x in 0..xmax { + level[x][0] = true; + level[x][ymax - 1] = true; + } + + for y in 0..level[0].len() { + level[0][y] = true; + level[xmax - 1][y] = true; + } +} |