1
0
Fork 0
roguelike-game/src/map_builders/limestone_cavern.rs

176 lines
6.1 KiB
Rust

use super::prefab_builder::prefab_sections;
use super::{
AreaEndingPosition, AreaStartingPosition, BspDungeonBuilder, BuilderChain, BuilderMap,
CellularAutomataBuilder, CullUnreachable, DLABuilder, DistantExit, DrunkardsWalkBuilder,
MetaMapBuilder, NearestCorridors, PrefabBuilder, RoomBasedSpawner, RoomDrawer, RoomExploder,
RoomSort, RoomSorter, VoronoiSpawning, XEnd, XStart, YEnd, YStart,
};
use crate::map::TileType;
use crate::rng::roll_dice;
pub fn limestone_cavern_builder(new_depth: i32, 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, 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 fn limestone_transition_builder(new_depth: i32, 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
}
pub struct CaveDecorator {}
impl MetaMapBuilder for CaveDecorator {
fn build_map(&mut self, build_data: &mut BuilderMap) {
self.build(build_data);
}
}
impl CaveDecorator {
#[allow(dead_code)]
pub fn new() -> Box<CaveDecorator> {
Box::new(CaveDecorator {})
}
fn build(&mut self, 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 && roll_dice(1, 6) == 1 {
*tt = TileType::Gravel;
} else if *tt == TileType::Floor && 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 roll_dice(1, 4) {
1 => TileType::Stalactite,
2 => TileType::Stalagmite,
_ => *tt,
}
}
}
}
build_data.take_snapshot();
build_data.map.outdoors = false;
}
}
pub struct CaveTransition {}
impl MetaMapBuilder for CaveTransition {
fn build_map(&mut self, build_data: &mut BuilderMap) {
self.build(build_data);
}
}
impl CaveTransition {
#[allow(dead_code)]
pub fn new() -> Box<CaveTransition> {
Box::new(CaveTransition {})
}
fn build(&mut self, 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();
// 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());
}
}
}
}