about summary refs log tree commit diff
path: root/src/level_gen
diff options
context:
space:
mode:
Diffstat (limited to 'src/level_gen')
-rw-r--r--src/level_gen/cave_automata.rs4
-rw-r--r--src/level_gen/display.rs17
-rw-r--r--src/level_gen/mod.rs100
-rw-r--r--src/level_gen/util.rs19
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;
+    }
+}