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 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 common::*; 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 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, pub rooms: Option>, pub history: Vec, } 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>, builders: Vec>, 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) -> &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) -> &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 { self.build_data.starting_position } pub fn get_snapshot_history(&self) -> Vec { 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); } pub fn random_builder(new_depth: i32, rng: &mut RandomNumberGenerator) -> BuilderChain { let mut builder = BuilderChain::new(new_depth); builder .start_with(VoronoiCellBuilder::pythagoras()) .with(WaveformCollapseBuilder::new()) .with(PrefabBuilder::vaults()) .with(AreaStartingPosition::new(XStart::Center, YStart::Center)) .with(CullUnreachable::new()) .with(VoronoiSpawning::new()) .with(PrefabBuilder::sectional( prefab_builder::prefab_sections::UNDERGROUND_FORT, )) .with(DistantExit::new()); builder }