roguelike-game/src/map_builders/limestone_cavern.rs
2022-01-14 10:47:43 -05:00

108 lines
3.6 KiB
Rust

use ::rltk::RandomNumberGenerator;
use super::{
AreaStartingPosition, BuilderChain, BuilderMap, CullUnreachable, DistantExit,
DrunkardsWalkBuilder, MetaMapBuilder, VoronoiSpawning, XStart, YStart,
};
use crate::map::TileType;
use crate::map_builders::dla::DLABuilder;
use crate::map_builders::prefab_builder::{prefab_sections, PrefabBuilder};
pub fn limestone_cavern_builder(
new_depth: i32,
_rng: &mut RandomNumberGenerator,
width: i32,
height: i32,
) -> BuilderChain {
let mut chain = BuilderChain::new(new_depth, width, height, "Limestone Caverns");
chain
.start_with(DrunkardsWalkBuilder::winding_passages())
.with(AreaStartingPosition::new(XStart::Center, YStart::Center))
.with(CullUnreachable::new())
.with(AreaStartingPosition::new(XStart::Left, YStart::Center))
.with(VoronoiSpawning::new())
.with(DistantExit::new())
.with(CaveDecorator::new());
chain
}
pub fn limestone_deep_cavern_builder(
new_depth: i32,
_rng: &mut RandomNumberGenerator,
width: i32,
height: i32,
) -> BuilderChain {
let mut chain = BuilderChain::new(new_depth, width, height, "Deep Limestone Caverns");
chain
.start_with(DLABuilder::central_attractor())
.with(AreaStartingPosition::new(XStart::Left, YStart::Top))
.with(VoronoiSpawning::new())
.with(DistantExit::new())
.with(CaveDecorator::new())
.with(PrefabBuilder::sectional(prefab_sections::ORC_CAMP));
chain
}
pub struct CaveDecorator {}
impl MetaMapBuilder for CaveDecorator {
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
self.build(rng, build_data);
}
}
impl CaveDecorator {
#[allow(dead_code)]
pub fn new() -> Box<CaveDecorator> {
Box::new(CaveDecorator {})
}
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
let old_map = build_data.map.clone();
for (idx, tt) in build_data.map.tiles.iter_mut().enumerate() {
// Gravel Spawning
if *tt == TileType::Floor && rng.roll_dice(1, 6) == 1 {
*tt = TileType::Gravel;
} else if *tt == TileType::Floor && rng.roll_dice(1, 10) == 1 {
// Spawn passable pools
*tt = TileType::ShallowWater;
} else if *tt == TileType::Wall {
// Spawn deep pools and stalactites
let mut neighbors = 0;
let x = idx as i32 % old_map.width;
let y = idx as i32 / old_map.width;
if x > 0 && old_map.tiles[idx - 1] == TileType::Wall {
neighbors += 1;
}
if x < old_map.width - 2 && old_map.tiles[idx + 1] == TileType::Wall {
neighbors += 1
}
if y > 0 && old_map.tiles[idx - old_map.width as usize] == TileType::Wall {
neighbors += 1
}
if y < old_map.height - 2
&& old_map.tiles[idx + old_map.width as usize] == TileType::Wall
{
neighbors += 1
}
if neighbors == 2 {
*tt = TileType::DeepWater;
} else if neighbors == 1 {
*tt = match rng.roll_dice(1, 4) {
1 => TileType::Stalactite,
2 => TileType::Stalagmite,
_ => *tt,
}
}
}
}
build_data.take_snapshot();
build_data.map.outdoors = false;
}
}