2022-02-03 15:16:41 -05:00
|
|
|
use ::rltk::prelude::*;
|
2022-01-28 10:24:00 -05:00
|
|
|
|
|
|
|
use super::{
|
|
|
|
AreaEndingPosition, AreaStartingPosition, BspCorridors, BspDungeonBuilder, BuilderChain,
|
|
|
|
BuilderMap, CorridorSpawner, CullUnreachable, DLABuilder, DistantExit, MetaMapBuilder,
|
|
|
|
RoomDrawer, RoomSort, RoomSorter, VoronoiSpawning, XEnd, XStart, YEnd, YStart,
|
|
|
|
};
|
2022-01-28 10:54:19 -05:00
|
|
|
use crate::{tile_walkable, TileType};
|
2022-01-28 10:24:00 -05:00
|
|
|
|
2022-02-03 14:59:35 -05:00
|
|
|
pub fn dwarf_fort_builder(new_depth: i32, width: i32, height: i32) -> BuilderChain {
|
2022-01-28 10:24:00 -05:00
|
|
|
let mut chain = BuilderChain::new(new_depth, width, height, "Dwarven Fortress");
|
|
|
|
chain
|
|
|
|
.start_with(BspDungeonBuilder::new())
|
|
|
|
.with(RoomSorter::new(RoomSort::Central))
|
|
|
|
.with(RoomDrawer::new())
|
|
|
|
.with(BspCorridors::new())
|
|
|
|
.with(CorridorSpawner::new())
|
|
|
|
.with(DragonsLair::new())
|
|
|
|
.with(AreaStartingPosition::new(XStart::Left, YStart::Top))
|
|
|
|
.with(CullUnreachable::new())
|
|
|
|
.with(AreaEndingPosition::new(XEnd::Right, YEnd::Bottom))
|
|
|
|
.with(VoronoiSpawning::new())
|
2022-01-28 10:54:19 -05:00
|
|
|
.with(DistantExit::new())
|
|
|
|
.with(DragonSpawner::new());
|
2022-01-28 10:24:00 -05:00
|
|
|
|
|
|
|
chain
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct DragonsLair {}
|
|
|
|
|
|
|
|
impl MetaMapBuilder for DragonsLair {
|
2022-02-03 14:59:35 -05:00
|
|
|
fn build_map(&mut self, build_data: &mut BuilderMap) {
|
|
|
|
self.build(build_data);
|
2022-01-28 10:24:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DragonsLair {
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub fn new() -> Box<DragonsLair> {
|
|
|
|
Box::new(DragonsLair {})
|
|
|
|
}
|
|
|
|
|
2022-02-03 14:59:35 -05:00
|
|
|
fn build(&mut self, build_data: &mut BuilderMap) {
|
2022-01-28 10:24:00 -05:00
|
|
|
build_data.map.depth = 7;
|
|
|
|
build_data.take_snapshot();
|
|
|
|
|
|
|
|
let mut builder = BuilderChain::new(6, build_data.width, build_data.height, "New Map");
|
|
|
|
builder.start_with(DLABuilder::insectoid());
|
2022-02-03 14:59:35 -05:00
|
|
|
builder.build_map();
|
2022-01-28 10:24:00 -05:00
|
|
|
|
|
|
|
// Add the history to our history
|
|
|
|
for h in builder.build_data.history.iter() {
|
|
|
|
build_data.history.push(h.clone());
|
|
|
|
}
|
|
|
|
build_data.take_snapshot();
|
|
|
|
|
|
|
|
// Merge the maps
|
|
|
|
for (idx, tt) in build_data.map.tiles.iter_mut().enumerate() {
|
|
|
|
if *tt == TileType::Wall && builder.build_data.map.tiles[idx] == TileType::Floor {
|
|
|
|
*tt = TileType::Floor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
build_data.take_snapshot();
|
|
|
|
}
|
|
|
|
}
|
2022-01-28 10:54:19 -05:00
|
|
|
|
|
|
|
pub struct DragonSpawner {}
|
|
|
|
|
|
|
|
impl MetaMapBuilder for DragonSpawner {
|
2022-02-03 14:59:35 -05:00
|
|
|
fn build_map(&mut self, build_data: &mut BuilderMap) {
|
|
|
|
self.build(build_data);
|
2022-01-28 10:54:19 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DragonSpawner {
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub fn new() -> Box<DragonSpawner> {
|
|
|
|
Box::new(DragonSpawner {})
|
|
|
|
}
|
|
|
|
|
2022-02-03 14:59:35 -05:00
|
|
|
fn build(&mut self, build_data: &mut BuilderMap) {
|
2022-01-28 10:54:19 -05:00
|
|
|
// Find a central location that isn't occupied
|
|
|
|
let seed_x = build_data.map.width / 2;
|
|
|
|
let seed_y = build_data.map.height / 2;
|
|
|
|
let mut available_floors: Vec<(usize, f32)> = Vec::new();
|
|
|
|
for (idx, tiletype) in build_data.map.tiles.iter().enumerate() {
|
|
|
|
if tile_walkable(*tiletype) {
|
|
|
|
available_floors.push((
|
|
|
|
idx,
|
|
|
|
DistanceAlg::PythagorasSquared.distance2d(
|
|
|
|
Point::new(
|
|
|
|
idx as i32 % build_data.map.width,
|
|
|
|
idx as i32 / build_data.map.width,
|
|
|
|
),
|
|
|
|
Point::new(seed_x, seed_y),
|
|
|
|
),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if available_floors.is_empty() {
|
|
|
|
panic!("No valid floors to start on.");
|
|
|
|
}
|
|
|
|
|
|
|
|
available_floors.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap());
|
|
|
|
|
|
|
|
let start_x = available_floors[0].0 as i32 % build_data.map.width;
|
|
|
|
let start_y = available_floors[0].0 as i32 / build_data.map.width;
|
|
|
|
let dragon_pt = Point::new(start_x, start_y);
|
|
|
|
|
|
|
|
// Remove all spawns within 25 tiles of the drake
|
|
|
|
let w = build_data.map.width as i32;
|
|
|
|
build_data.spawn_list.retain(|spawn| {
|
|
|
|
let spawn_pt = Point::new(spawn.0 as i32 % w, spawn.0 as i32 / 2);
|
|
|
|
let distance = DistanceAlg::Pythagoras.distance2d(dragon_pt, spawn_pt);
|
|
|
|
|
|
|
|
distance > 25.0
|
|
|
|
});
|
|
|
|
|
|
|
|
// Add the dragon
|
|
|
|
let dragon_idx = build_data.map.xy_idx(start_x, start_y);
|
|
|
|
build_data
|
|
|
|
.spawn_list
|
|
|
|
.push((dragon_idx, "Black Dragon".to_string()));
|
|
|
|
}
|
|
|
|
}
|