diff options
Diffstat (limited to 'src/level_gen')
-rw-r--r-- | src/level_gen/cave_automata.rs | 120 | ||||
-rw-r--r-- | src/level_gen/mod.rs | 101 | ||||
-rw-r--r-- | src/level_gen/util.rs | 52 |
3 files changed, 0 insertions, 273 deletions
diff --git a/src/level_gen/cave_automata.rs b/src/level_gen/cave_automata.rs deleted file mode 100644 index e5e2807ab251..000000000000 --- a/src/level_gen/cave_automata.rs +++ /dev/null @@ -1,120 +0,0 @@ -use crate::level_gen::util::fill_outer_edges; -use crate::level_gen::util::rand_initialize; -use crate::types::Dimensions; -use rand::Rng; - -pub struct Params { - chance_to_start_alive: f64, - birth_limit: i32, - death_limit: i32, - steps: usize, -} - -macro_rules! parse_optional { - ($out: ident . $attr: ident, $matches: expr, $arg: expr) => { - if let Some(val_s) = $matches.value_of($arg) { - $out.$attr = val_s.parse().unwrap(); - } - }; -} - -macro_rules! parse_optional_matches { - ($matches: expr) => {}; - ($matches: expr , { $ret: ident . $attr: ident = $arg: expr }) => { - parse_optional!($ret.$attr, $matches, $arg); - }; - ($matches: expr, { $($ret: ident . $attr: ident = $arg: expr ,)* }) => { - $(parse_optional!($ret.$attr, $matches, $arg);)* - }; -} - -impl Params { - pub fn from_matches<'a>(matches: &clap::ArgMatches<'a>) -> Self { - let mut ret: Self = Default::default(); - parse_optional_matches!(matches, { - ret.chance_to_start_alive = "start-alive-chance", - ret.birth_limit = "birth-limit", - ret.death_limit = "death-limit", - ret.steps = "steps", - }); - ret - } -} - -impl Default for Params { - fn default() -> Self { - Params { - chance_to_start_alive: 0.45, - birth_limit: 4, - death_limit: 3, - steps: 2, - } - } -} - -pub fn generate<R: Rng + ?Sized>( - dimensions: Dimensions, - params: &Params, - rand: &mut R, -) -> Vec<Vec<bool>> { - let mut cells = - rand_initialize(dimensions, rand, params.chance_to_start_alive); - for _ in 0..params.steps { - step_automata(&mut cells, dimensions, params); - } - - fill_outer_edges(&mut cells); - - cells -} - -fn step_automata( - cells: &mut Vec<Vec<bool>>, - dimensions: Dimensions, - params: &Params, -) { - let orig_cells = (*cells).clone(); - for x in 0..(dimensions.h as usize) { - for y in 0..(dimensions.w as usize) { - let nbs = num_alive_neighbors(&orig_cells, x as i32, y as i32); - if orig_cells[x][y] { - if nbs < params.death_limit { - cells[x][y] = false; - } else { - cells[x][y] = true; - } - } else if nbs > params.birth_limit { - cells[x][y] = true; - } else { - cells[x][y] = false; - } - } - } -} - -const COUNT_EDGES_AS_NEIGHBORS: bool = true; - -fn num_alive_neighbors(cells: &[Vec<bool>], x: i32, y: i32) -> i32 { - let mut count = 0; - for i in -1..2 { - for j in -1..2 { - if i == 0 && j == 0 { - continue; - } - - let neighbor_x = x + i; - let neighbor_y = y + j; - - if (COUNT_EDGES_AS_NEIGHBORS - && (neighbor_x < 0 - || neighbor_y < 0 - || neighbor_x >= (cells.len() as i32) - || neighbor_y >= (cells[0].len()) as i32)) - || cells[neighbor_x as usize][neighbor_y as usize] - { - count += 1; - } - } - } - count -} diff --git a/src/level_gen/mod.rs b/src/level_gen/mod.rs deleted file mode 100644 index d796a103b11e..000000000000 --- a/src/level_gen/mod.rs +++ /dev/null @@ -1,101 +0,0 @@ -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 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.is_empty() { - 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 deleted file mode 100644 index 4f56fe6c9557..000000000000 --- a/src/level_gen/util.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::types::Dimensions; -use rand::{distributions, Rng}; - -pub fn falses(dims: Dimensions) -> Vec<Vec<bool>> { - let mut ret = Vec::with_capacity(dims.h as usize); - for _ in 0..dims.h { - let mut row = Vec::with_capacity(dims.w as usize); - for _ in 0..dims.w { - row.push(false); - } - ret.push(row); - } - ret -} - -/// Randomly initialize a 2-dimensional boolean vector of the given -/// `Dimensions`, using the given random number generator and alive chance -pub fn rand_initialize<R: Rng + ?Sized>( - dims: Dimensions, - rng: &mut R, - alive_chance: f64, -) -> Vec<Vec<bool>> { - let distrib = distributions::Bernoulli::new(alive_chance).unwrap(); - let mut ret = Vec::with_capacity(dims.h as usize); - for _ in 0..dims.h { - let mut row = Vec::with_capacity(dims.w as usize); - for _ in 0..dims.w { - row.push(rng.sample(distrib)); - } - ret.push(row); - } - 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 row in level.iter_mut() { - row[0] = true; - row[ymax - 1] = true; - } - - for y in 0..level[0].len() { - level[0][y] = true; - level[xmax - 1][y] = true; - } -} |