221 lines
6.5 KiB
Rust
221 lines
6.5 KiB
Rust
mod area_starting_points;
|
|
mod bsp_dungeon;
|
|
mod bsp_interior;
|
|
mod cellular_automata;
|
|
mod common;
|
|
mod cull_unreachable;
|
|
mod distant_exit;
|
|
mod dla;
|
|
mod drunkard;
|
|
mod maze;
|
|
mod prefab_builder;
|
|
mod room_based_spawner;
|
|
mod room_based_stairs;
|
|
mod room_based_starting_position;
|
|
mod room_corner_rounding;
|
|
mod room_exploder;
|
|
mod simple_map;
|
|
mod voronoi;
|
|
mod voronoi_spawning;
|
|
mod waveform_collapse;
|
|
|
|
use ::rltk::RandomNumberGenerator;
|
|
use area_starting_points::{AreaStartingPosition, XStart, YStart};
|
|
use bsp_dungeon::BspDungeonBuilder;
|
|
use bsp_interior::BspInteriorBuilder;
|
|
use cellular_automata::CellularAutomataBuilder;
|
|
use cull_unreachable::CullUnreachable;
|
|
use distant_exit::DistantExit;
|
|
use dla::DLABuilder;
|
|
use drunkard::DrunkardsWalkBuilder;
|
|
use maze::MazeBuilder;
|
|
use prefab_builder::PrefabBuilder;
|
|
use room_based_spawner::RoomBasedSpawner;
|
|
use room_based_stairs::RoomBasedStairs;
|
|
use room_based_starting_position::RoomBasedStartingPosition;
|
|
use room_corner_rounding::RoomCornerRounder;
|
|
use room_exploder::RoomExploder;
|
|
use simple_map::SimpleMapBuilder;
|
|
use specs::prelude::*;
|
|
use voronoi::VoronoiCellBuilder;
|
|
use voronoi_spawning::VoronoiSpawning;
|
|
use waveform_collapse::WaveformCollapseBuilder;
|
|
|
|
use crate::{spawner, Map, Position, Rect, SHOW_MAPGEN_VISUALIZER};
|
|
|
|
pub struct BuilderMap {
|
|
pub spawn_list: Vec<(usize, String)>,
|
|
pub map: Map,
|
|
pub starting_position: Option<Position>,
|
|
pub rooms: Option<Vec<Rect>>,
|
|
pub history: Vec<Map>,
|
|
}
|
|
|
|
impl BuilderMap {
|
|
fn new(new_depth: i32) -> BuilderMap {
|
|
BuilderMap {
|
|
spawn_list: Vec::new(),
|
|
map: Map::new(new_depth),
|
|
starting_position: None,
|
|
rooms: None,
|
|
history: Vec::new(),
|
|
}
|
|
}
|
|
|
|
fn take_snapshot(&mut self) {
|
|
if SHOW_MAPGEN_VISUALIZER {
|
|
let mut snapshot = self.map.clone();
|
|
for v in snapshot.revealed_tiles.iter_mut() {
|
|
*v = true;
|
|
}
|
|
self.history.push(snapshot);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct BuilderChain {
|
|
starter: Option<Box<dyn InitialMapBuilder>>,
|
|
builders: Vec<Box<dyn MetaMapBuilder>>,
|
|
pub build_data: BuilderMap,
|
|
}
|
|
|
|
impl BuilderChain {
|
|
pub fn new(new_depth: i32) -> BuilderChain {
|
|
BuilderChain {
|
|
starter: None,
|
|
builders: Vec::new(),
|
|
build_data: BuilderMap::new(new_depth),
|
|
}
|
|
}
|
|
|
|
pub fn start_with(&mut self, starter: Box<dyn InitialMapBuilder>) -> &mut Self {
|
|
match self.starter {
|
|
None => self.starter = Some(starter),
|
|
Some(_) => panic!("You can only have one starting builder."),
|
|
}
|
|
|
|
self
|
|
}
|
|
|
|
pub fn with(&mut self, metabuilder: Box<dyn MetaMapBuilder>) -> &mut Self {
|
|
self.builders.push(metabuilder);
|
|
|
|
self
|
|
}
|
|
|
|
pub fn build_map(&mut self, rng: &mut RandomNumberGenerator) -> &mut Self {
|
|
match &mut self.starter {
|
|
None => panic!("Cannot run a map builder chain without starting a build system"),
|
|
Some(starter) => {
|
|
// Build the starting map
|
|
starter.build_map(rng, &mut self.build_data);
|
|
}
|
|
}
|
|
|
|
// Build additional layers in turn
|
|
for metabuilder in self.builders.iter_mut() {
|
|
metabuilder.build_map(rng, &mut self.build_data);
|
|
}
|
|
|
|
self
|
|
}
|
|
|
|
pub fn spawn_entities(&mut self, ecs: &mut World) -> &mut Self {
|
|
for entity in self.build_data.spawn_list.iter() {
|
|
spawner::spawn_entity(ecs, &(&entity.0, &entity.1));
|
|
}
|
|
|
|
self
|
|
}
|
|
|
|
pub fn get_map(&self) -> Map {
|
|
self.build_data.map.clone()
|
|
}
|
|
|
|
pub fn get_starting_position(&self) -> Option<Position> {
|
|
self.build_data.starting_position
|
|
}
|
|
|
|
pub fn get_snapshot_history(&self) -> Vec<Map> {
|
|
self.build_data.history.clone()
|
|
}
|
|
|
|
pub fn get_spawn_list(&self) -> &Vec<(usize, String)> {
|
|
&self.build_data.spawn_list
|
|
}
|
|
}
|
|
|
|
pub trait InitialMapBuilder {
|
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap);
|
|
}
|
|
|
|
pub trait MetaMapBuilder {
|
|
fn build_map(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap);
|
|
}
|
|
|
|
fn random_initial_builder(rng: &mut RandomNumberGenerator) -> (Box<dyn InitialMapBuilder>, bool) {
|
|
match rng.roll_dice(1, 17) {
|
|
1 => (BspDungeonBuilder::new(), true),
|
|
2 => (BspInteriorBuilder::new(), true),
|
|
3 => (CellularAutomataBuilder::new(), false),
|
|
4 => (DrunkardsWalkBuilder::open_area(), false),
|
|
5 => (DrunkardsWalkBuilder::open_halls(), false),
|
|
6 => (DrunkardsWalkBuilder::winding_passages(), false),
|
|
7 => (DrunkardsWalkBuilder::fat_passages(), false),
|
|
8 => (DrunkardsWalkBuilder::fearful_symmetry(), false),
|
|
9 => (MazeBuilder::new(), false),
|
|
10 => (DLABuilder::walk_inwards(), false),
|
|
11 => (DLABuilder::walk_outwards(), false),
|
|
12 => (DLABuilder::central_attractor(), false),
|
|
13 => (DLABuilder::insectoid(), false),
|
|
14 => (VoronoiCellBuilder::pythagoras(), false),
|
|
15 => (VoronoiCellBuilder::manhattan(), false),
|
|
16 => (
|
|
PrefabBuilder::constant(prefab_builder::prefab_levels::WFC_POPULATED),
|
|
false,
|
|
),
|
|
_ => (SimpleMapBuilder::new(), true),
|
|
}
|
|
}
|
|
|
|
pub fn random_builder(new_depth: i32, rng: &mut RandomNumberGenerator) -> BuilderChain {
|
|
let mut builder = BuilderChain::new(new_depth);
|
|
// let (random_starter, has_rooms) = random_initial_builder(rng);
|
|
// builder.start_with(random_starter);
|
|
//
|
|
// if has_rooms {
|
|
// builder
|
|
// .with(RoomBasedSpawner::new())
|
|
// .with(RoomBasedStairs::new())
|
|
// .with(RoomBasedStartingPosition::new());
|
|
// } else {
|
|
// builder
|
|
// .with(AreaStartingPosition::new(XStart::Center, YStart::Center))
|
|
// .with(CullUnreachable::new())
|
|
// .with(VoronoiSpawning::new())
|
|
// .with(DistantExit::new());
|
|
// }
|
|
//
|
|
// if rng.roll_dice(1, 3) == 1 {
|
|
// builder.with(WaveformCollapseBuilder::new());
|
|
// }
|
|
//
|
|
// if rng.roll_dice(1, 20) == 1 {
|
|
// builder.with(PrefabBuilder::sectional(
|
|
// prefab_builder::prefab_sections::UNDERGROUND_FORT,
|
|
// ));
|
|
// }
|
|
//
|
|
// builder.with(PrefabBuilder::vaults());
|
|
|
|
builder
|
|
.start_with(BspDungeonBuilder::new())
|
|
.with(RoomCornerRounder::new())
|
|
.with(AreaStartingPosition::new(XStart::Center, YStart::Center))
|
|
.with(CullUnreachable::new())
|
|
.with(VoronoiSpawning::new())
|
|
.with(DistantExit::new());
|
|
|
|
builder
|
|
}
|