2022-01-10 09:57:59 -05:00
|
|
|
use ::rltk::RandomNumberGenerator;
|
|
|
|
|
2022-01-18 11:00:13 -05:00
|
|
|
use super::prefab_builder::prefab_sections;
|
2022-01-10 09:57:59 -05:00
|
|
|
use super::{
|
2022-01-18 11:00:13 -05:00
|
|
|
AreaEndingPosition, AreaStartingPosition, BspDungeonBuilder, BuilderChain, BuilderMap,
|
|
|
|
CellularAutomataBuilder, CullUnreachable, DLABuilder, DistantExit, DrunkardsWalkBuilder,
|
|
|
|
MetaMapBuilder, NearestCorridors, PrefabBuilder, RoomBasedSpawner, RoomDrawer, RoomExploder,
|
|
|
|
RoomSort, RoomSorter, VoronoiSpawning, XEnd, XStart, YEnd, YStart,
|
2022-01-10 09:57:59 -05:00
|
|
|
};
|
2022-01-10 10:21:19 -05:00
|
|
|
use crate::map::TileType;
|
2022-01-10 09:57:59 -05:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-01-14 10:47:43 -05:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2022-01-18 09:32:48 -05:00
|
|
|
pub fn limestone_transition_builder(
|
|
|
|
new_depth: i32,
|
|
|
|
_rng: &mut RandomNumberGenerator,
|
|
|
|
width: i32,
|
|
|
|
height: i32,
|
|
|
|
) -> BuilderChain {
|
|
|
|
let mut chain = BuilderChain::new(new_depth, width, height, "Dwarf Fort - Upper Reaches");
|
|
|
|
chain
|
|
|
|
.start_with(CellularAutomataBuilder::new())
|
|
|
|
.with(AreaStartingPosition::new(XStart::Center, YStart::Center))
|
|
|
|
.with(CullUnreachable::new())
|
|
|
|
.with(AreaStartingPosition::new(XStart::Left, YStart::Center))
|
|
|
|
.with(VoronoiSpawning::new())
|
|
|
|
.with(CaveDecorator::new())
|
|
|
|
.with(CaveTransition::new())
|
|
|
|
.with(AreaStartingPosition::new(XStart::Left, YStart::Center))
|
|
|
|
.with(CullUnreachable::new())
|
|
|
|
.with(AreaEndingPosition::new(XEnd::Right, YEnd::Center));
|
|
|
|
|
|
|
|
chain
|
|
|
|
}
|
|
|
|
|
2022-01-10 09:57:59 -05:00
|
|
|
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();
|
2022-01-10 10:21:19 -05:00
|
|
|
build_data.map.outdoors = false;
|
2022-01-10 09:57:59 -05:00
|
|
|
}
|
|
|
|
}
|
2022-01-18 09:32:48 -05:00
|
|
|
|
|
|
|
pub struct CaveTransition {}
|
|
|
|
|
|
|
|
impl MetaMapBuilder for CaveTransition {
|
|
|
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
|
|
|
self.build(rng, build_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CaveTransition {
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub fn new() -> Box<CaveTransition> {
|
|
|
|
Box::new(CaveTransition {})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
|
|
|
|
build_data.map.depth = 5;
|
|
|
|
build_data.take_snapshot();
|
|
|
|
|
|
|
|
// Build a BSP-based dungeon
|
|
|
|
let mut builder = BuilderChain::new(5, build_data.width, build_data.height, "New Map");
|
|
|
|
builder
|
|
|
|
.start_with(BspDungeonBuilder::new())
|
|
|
|
.with(RoomDrawer::new())
|
|
|
|
.with(RoomSorter::new(RoomSort::RightMost))
|
|
|
|
.with(NearestCorridors::new())
|
|
|
|
.with(RoomExploder::new())
|
|
|
|
.with(RoomBasedSpawner::new());
|
|
|
|
builder.build_map(rng);
|
|
|
|
|
|
|
|
// Add the history to our history
|
|
|
|
for h in builder.build_data.history.iter() {
|
|
|
|
build_data.history.push(h.clone());
|
|
|
|
}
|
|
|
|
build_data.take_snapshot();
|
|
|
|
|
|
|
|
// Copy the right half of the BSP map into our map
|
|
|
|
for x in build_data.map.width / 2..build_data.map.width {
|
|
|
|
for y in 0..build_data.map.height {
|
|
|
|
let idx = build_data.map.xy_idx(x, y);
|
|
|
|
build_data.map.tiles[idx] = builder.build_data.map.tiles[idx];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
build_data.take_snapshot();
|
|
|
|
|
|
|
|
// Keep Voronoi spawn data from the left half of the map
|
|
|
|
let w = build_data.map.width;
|
|
|
|
build_data.spawn_list.retain(|s| {
|
|
|
|
let x = s.0 as i32 / w;
|
|
|
|
x < w / 2
|
|
|
|
});
|
|
|
|
|
|
|
|
// Keep room spawn data from the right half of the map
|
|
|
|
for s in builder.build_data.spawn_list.iter() {
|
|
|
|
let x = s.0 as i32 / w;
|
|
|
|
if x < w / 2 {
|
|
|
|
build_data.spawn_list.push(s.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|