decouples depth from difficulty, and renames depth to ID

for future impl of branches
This commit is contained in:
Llywelwyn 2023-07-27 17:59:46 +01:00
parent 8b2acab576
commit 1239597422
20 changed files with 164 additions and 204 deletions

View file

@ -1,4 +1,4 @@
use super::{BuilderMap, MetaMapBuilder, Position, TileType};
use super::{BuilderMap, MetaMapBuilder, Position};
use rltk::RandomNumberGenerator;
#[allow(dead_code)]

View file

@ -92,13 +92,13 @@ pub struct BuilderChain {
}
impl BuilderChain {
pub fn new(new_depth: i32, width: i32, height: i32) -> BuilderChain {
pub fn new(new_id: i32, width: i32, height: i32, difficulty: i32) -> BuilderChain {
BuilderChain {
starter: None,
builders: Vec::new(),
build_data: BuilderMap {
spawn_list: Vec::new(),
map: Map::new(new_depth, width, height),
map: Map::new(new_id, width, height, difficulty),
starting_position: None,
rooms: None,
corridors: None,
@ -136,9 +136,12 @@ impl BuilderChain {
}
pub fn spawn_entities(&mut self, ecs: &mut World) {
let mut spawned_entities = Vec::new();
for entity in self.build_data.spawn_list.iter() {
spawned_entities.push(&entity.1);
spawner::spawn_entity(ecs, &(&entity.0, &entity.1));
}
rltk::console::log(format!("DEBUGINFO: SPAWNED ENTITIES = {:?}", spawned_entities));
}
}
@ -279,8 +282,15 @@ fn random_shape_builder(rng: &mut rltk::RandomNumberGenerator, builder: &mut Bui
builder.with(DistantExit::new());
}
pub fn random_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator, width: i32, height: i32) -> BuilderChain {
let mut builder = BuilderChain::new(new_depth, width, height);
pub fn random_builder(
new_id: i32,
rng: &mut rltk::RandomNumberGenerator,
width: i32,
height: i32,
difficulty: i32,
) -> BuilderChain {
rltk::console::log(format!("DEBUGINFO: Building random (ID:{}, DIFF:{})", new_id, difficulty));
let mut builder = BuilderChain::new(new_id, width, height, difficulty);
let type_roll = rng.roll_dice(1, 2);
match type_roll {
1 => random_room_builder(rng, &mut builder),
@ -317,10 +327,10 @@ pub fn random_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator, wid
builder
}
pub fn level_builder(new_depth: i32, rng: &mut rltk::RandomNumberGenerator, width: i32, height: i32) -> BuilderChain {
rltk::console::log(format!("DEBUGINFO: Depth: {}", new_depth));
match new_depth {
1 => town_builder(new_depth, rng, width, height),
_ => random_builder(new_depth, rng, width, height),
pub fn level_builder(new_id: i32, rng: &mut rltk::RandomNumberGenerator, width: i32, height: i32) -> BuilderChain {
let difficulty = new_id;
match new_id {
1 => town_builder(new_id, rng, width, height),
_ => random_builder(new_id, rng, width, height, difficulty),
}
}

View file

@ -102,23 +102,23 @@ impl PrefabBuilder {
}
'%' => {
build_data.map.tiles[idx] = TileType::Floor;
build_data.spawn_list.push((idx, spawner::food_table(build_data.map.depth).roll(rng)));
build_data.spawn_list.push((idx, spawner::food_table(build_data.map.difficulty).roll(rng)));
}
'!' => {
build_data.map.tiles[idx] = TileType::Floor;
build_data.spawn_list.push((idx, spawner::potion_table(build_data.map.depth).roll(rng)));
build_data.spawn_list.push((idx, spawner::potion_table(build_data.map.difficulty).roll(rng)));
}
'/' => {
build_data.map.tiles[idx] = TileType::Floor;
build_data.spawn_list.push((idx, spawner::wand_table(build_data.map.depth).roll(rng)));
build_data.spawn_list.push((idx, spawner::wand_table(build_data.map.difficulty).roll(rng)));
}
'?' => {
build_data.map.tiles[idx] = TileType::Floor;
build_data.spawn_list.push((idx, spawner::scroll_table(build_data.map.depth).roll(rng)));
build_data.spawn_list.push((idx, spawner::scroll_table(build_data.map.difficulty).roll(rng)));
}
')' => {
build_data.map.tiles[idx] = TileType::Floor;
build_data.spawn_list.push((idx, spawner::equipment_table(build_data.map.depth).roll(rng)));
build_data.spawn_list.push((idx, spawner::equipment_table(build_data.map.difficulty).roll(rng)));
}
_ => {
rltk::console::log(format!("Unknown glyph '{}' when loading prefab", (ch as u8) as char));
@ -255,7 +255,7 @@ impl PrefabBuilder {
self.apply_previous_iteration(|_x, _y| true, rng, build_data);
// Do we want a vault at all?
let vault_roll = rng.roll_dice(1, 6) + build_data.map.depth;
let vault_roll = rng.roll_dice(1, 6) + build_data.map.difficulty;
if vault_roll < 4 {
return;
}
@ -276,10 +276,10 @@ impl PrefabBuilder {
ORC_HOUSE_8X8,
];
// Filter the vault list down to ones that are applicable to the current depth
// Filter the vault list down to ones that are applicable to the current id
let mut possible_vaults: Vec<&PrefabVault> = master_vault_list
.iter()
.filter(|v| build_data.map.depth >= v.first_depth && build_data.map.depth <= v.last_depth)
.filter(|v| build_data.map.id >= v.first_id && build_data.map.id <= v.last_id)
.collect();
if possible_vaults.is_empty() {

View file

@ -12,8 +12,8 @@ pub struct PrefabVault {
pub template: &'static str,
pub width: usize,
pub height: usize,
pub first_depth: i32,
pub last_depth: i32,
pub first_id: i32,
pub last_id: i32,
pub can_flip: Flipping,
}
@ -21,8 +21,8 @@ pub const CLASSIC_TRAP_5X5: PrefabVault = PrefabVault {
template: CLASSIC_TRAP_5X5_V,
width: 5,
height: 5,
first_depth: 0,
last_depth: 100,
first_id: 0,
last_id: 100,
can_flip: Flipping::None,
};
const CLASSIC_TRAP_5X5_V: &str = "
@ -37,8 +37,8 @@ pub const CLASSIC_TRAP_CARDINALGAP_5X5: PrefabVault = PrefabVault {
template: CLASSIC_TRAP_CARDINALGAP_5X5_V,
width: 5,
height: 5,
first_depth: 0,
last_depth: 100,
first_id: 0,
last_id: 100,
can_flip: Flipping::Both,
};
const CLASSIC_TRAP_CARDINALGAP_5X5_V: &str = "
@ -53,8 +53,8 @@ pub const CLASSIC_TRAP_DIAGONALGAP_5X5: PrefabVault = PrefabVault {
template: CLASSIC_TRAP_DIAGONALGAP_5X5_V,
width: 5,
height: 5,
first_depth: 0,
last_depth: 100,
first_id: 0,
last_id: 100,
can_flip: Flipping::Both,
};
const CLASSIC_TRAP_DIAGONALGAP_5X5_V: &str = "
@ -65,14 +65,8 @@ const CLASSIC_TRAP_DIAGONALGAP_5X5_V: &str = "
     
";
pub const GOBLINS_4X4: PrefabVault = PrefabVault {
template: GOBLINS_4X4_V,
width: 4,
height: 4,
first_depth: 0,
last_depth: 100,
can_flip: Flipping::Both,
};
pub const GOBLINS_4X4: PrefabVault =
PrefabVault { template: GOBLINS_4X4_V, width: 4, height: 4, first_id: 0, last_id: 100, can_flip: Flipping::Both };
const GOBLINS_4X4_V: &str = "
#^  
#G#
@ -80,14 +74,8 @@ const GOBLINS_4X4_V: &str = "
^g^
";
pub const GOBLINS2_4X4: PrefabVault = PrefabVault {
template: GOBLINS2_4X4_V,
width: 4,
height: 4,
first_depth: 0,
last_depth: 100,
can_flip: Flipping::Both,
};
pub const GOBLINS2_4X4: PrefabVault =
PrefabVault { template: GOBLINS2_4X4_V, width: 4, height: 4, first_id: 0, last_id: 100, can_flip: Flipping::Both };
const GOBLINS2_4X4_V: &str = "
#^#g
G# #
@ -95,14 +83,8 @@ G# #
# g^
";
pub const GOBLINS_5X5: PrefabVault = PrefabVault {
template: GOBLINS_5X5_V,
width: 5,
height: 5,
first_depth: 0,
last_depth: 100,
can_flip: Flipping::Both,
};
pub const GOBLINS_5X5: PrefabVault =
PrefabVault { template: GOBLINS_5X5_V, width: 5, height: 5, first_id: 0, last_id: 100, can_flip: Flipping::Both };
const GOBLINS_5X5_V: &str = "
 ^#g 
G#?#^
@ -111,14 +93,8 @@ G#?#^
^# # 
";
pub const GOBLINS_6X6: PrefabVault = PrefabVault {
template: GOBLINS_6X6_V,
width: 6,
height: 6,
first_depth: 0,
last_depth: 100,
can_flip: Flipping::Both,
};
pub const GOBLINS_6X6: PrefabVault =
PrefabVault { template: GOBLINS_6X6_V, width: 6, height: 6, first_id: 0, last_id: 100, can_flip: Flipping::Both };
const GOBLINS_6X6_V: &str = "
   #  
 #^#g 
@ -128,28 +104,16 @@ g##$^
 ^ # ^
";
pub const FLUFF_6X3: PrefabVault = PrefabVault {
template: FLUFF_6X3_V,
width: 6,
height: 3,
first_depth: 0,
last_depth: 100,
can_flip: Flipping::Both,
};
pub const FLUFF_6X3: PrefabVault =
PrefabVault { template: FLUFF_6X3_V, width: 6, height: 3, first_id: 0, last_id: 100, can_flip: Flipping::Both };
const FLUFF_6X3_V: &str = "
###^ 
 ^ #
 ## 
";
pub const FLUFF2_6X3: PrefabVault = PrefabVault {
template: FLUFF2_6X3_V,
width: 6,
height: 3,
first_depth: 0,
last_depth: 100,
can_flip: Flipping::Both,
};
pub const FLUFF2_6X3: PrefabVault =
PrefabVault { template: FLUFF2_6X3_V, width: 6, height: 3, first_id: 0, last_id: 100, can_flip: Flipping::Both };
const FLUFF2_6X3_V: &str = "
 ^###
# ^ 
@ -160,8 +124,8 @@ pub const HOUSE_NOTRAP_7X7: PrefabVault = PrefabVault {
template: HOUSE_NOTRAP_7X7_V,
width: 7,
height: 7,
first_depth: 0,
last_depth: 100,
first_id: 0,
last_id: 100,
can_flip: Flipping::Both,
};
const HOUSE_NOTRAP_7X7_V: &str = "
@ -178,8 +142,8 @@ pub const HOUSE_TRAP_7X7: PrefabVault = PrefabVault {
template: HOUSE_TRAP_7X7_V,
width: 7,
height: 7,
first_depth: 0,
last_depth: 100,
first_id: 0,
last_id: 100,
can_flip: Flipping::Both,
};
const HOUSE_TRAP_7X7_V: &str = "
@ -192,14 +156,8 @@ const HOUSE_TRAP_7X7_V: &str = "
##   ##
";
pub const ORC_HOUSE_8X8: PrefabVault = PrefabVault {
template: ORC_HOUSE_8X8_V,
width: 8,
height: 8,
first_depth: 0,
last_depth: 100,
can_flip: Flipping::Both,
};
pub const ORC_HOUSE_8X8: PrefabVault =
PrefabVault { template: ORC_HOUSE_8X8_V, width: 8, height: 8, first_id: 0, last_id: 100, can_flip: Flipping::Both };
const ORC_HOUSE_8X8_V: &str = "
######

View file

@ -18,7 +18,7 @@ impl RoomBasedSpawner {
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
if let Some(rooms) = &build_data.rooms {
for room in rooms.iter().skip(1) {
spawner::spawn_room(&build_data.map, rng, room, build_data.map.depth, &mut build_data.spawn_list);
spawner::spawn_room(&build_data.map, rng, room, &mut build_data.spawn_list);
}
} else {
panic!("RoomBasedSpawner only works after rooms have been created");

View file

@ -18,8 +18,7 @@ impl CorridorSpawner {
fn build(&mut self, rng: &mut RandomNumberGenerator, build_data: &mut BuilderMap) {
if let Some(corridors) = &build_data.corridors {
for corridor in corridors.iter() {
let depth = build_data.map.depth;
spawner::spawn_region(&build_data.map, rng, &corridor, depth, &mut build_data.spawn_list);
spawner::spawn_region(&build_data.map, rng, &corridor, &mut build_data.spawn_list);
}
} else {
panic!("CorridorSpawner only works after corridors have been created");

View file

@ -9,7 +9,7 @@ use std::collections::HashMap;
pub struct MazeBuilder {
map: Map,
starting_position: Position,
depth: i32,
id: i32,
history: Vec<Map>,
noise_areas: HashMap<i32, Vec<usize>>,
}
@ -20,7 +20,7 @@ impl MapBuilder for MazeBuilder {
}
fn spawn_entities(&mut self, ecs: &mut World) {
for area in self.noise_areas.iter() {
spawner::spawn_region(ecs, area.1, self.depth);
spawner::spawn_region(ecs, area.1, self.id);
}
}
// Getters
@ -46,11 +46,11 @@ impl MapBuilder for MazeBuilder {
}
impl MazeBuilder {
pub fn new(new_depth: i32) -> MazeBuilder {
pub fn new(new_id: i32) -> MazeBuilder {
MazeBuilder {
map: Map::new(new_depth),
map: Map::new(new_id),
starting_position: Position { x: 0, y: 0 },
depth: new_depth,
id: new_id,
history: Vec::new(),
noise_areas: HashMap::new(),
}

View file

@ -1,8 +1,10 @@
use super::{BuilderChain, BuilderMap, InitialMapBuilder, Position, TileType};
use std::collections::HashSet;
pub fn town_builder(new_depth: i32, _rng: &mut rltk::RandomNumberGenerator, width: i32, height: i32) -> BuilderChain {
let mut chain = BuilderChain::new(new_depth, width, height);
pub fn town_builder(new_id: i32, _rng: &mut rltk::RandomNumberGenerator, width: i32, height: i32) -> BuilderChain {
let difficulty = 0;
rltk::console::log(format!("DEBUGINFO: Building town (ID:{}, DIFF:{})", new_id, difficulty));
let mut chain = BuilderChain::new(new_id, width, height, difficulty);
chain.start_with(TownBuilder::new());
return chain;
@ -13,7 +15,7 @@ pub struct TownBuilder {}
impl InitialMapBuilder for TownBuilder {
#[allow(dead_code)]
fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
self.build_rooms(rng, build_data);
self.build_map(rng, build_data);
}
}
@ -22,26 +24,19 @@ impl TownBuilder {
return Box::new(TownBuilder {});
}
pub fn build_rooms(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
pub fn build_map(&mut self, rng: &mut rltk::RandomNumberGenerator, build_data: &mut BuilderMap) {
// Make visible for snapshot
for t in build_data.map.visible_tiles.iter_mut() {
*t = true;
}
self.grass_layer(build_data);
rltk::console::log("Placed grass.");
let piers = self.water_and_piers(rng, build_data);
rltk::console::log("Placed water and piers.");
let (mut available_building_tiles, wall_gap_y) = self.town_walls(rng, build_data);
rltk::console::log("Placed walls.");
let mut buildings = self.buildings(rng, build_data, &mut available_building_tiles);
rltk::console::log("Placed buildings.");
let doors = self.add_doors(rng, build_data, &mut buildings, wall_gap_y);
rltk::console::log("Placed doors.");
self.path_from_tiles_to_nearest_tiletype(build_data, &doors, TileType::Road, TileType::Road, true);
rltk::console::log("Placed path from doors to road.");
self.path_from_tiles_to_nearest_tiletype(build_data, &piers, TileType::Road, TileType::Road, false);
rltk::console::log("Placed path from piers to road.");
build_data.take_snapshot();
@ -107,7 +102,6 @@ impl TownBuilder {
loop {
y = rng.roll_dice(1, build_data.height - 3) - 1;
if !(placed_piers.contains(&y) || placed_piers.contains(&(y + pier_width))) {
rltk::console::log(format!("Placing pier at y {}-{}", y, y + 3));
break;
}
}
@ -166,7 +160,6 @@ impl TownBuilder {
let wall_gap_y =
(build_data.height / 2) + rng.roll_dice(1, PATH_OFFSET_FROM_CENTRE * 2) - 1 - PATH_OFFSET_FROM_CENTRE;
rltk::console::log(format!("Placing road centred at y {}", wall_gap_y));
for y in BORDER..build_data.height - BORDER {
if !(y > wall_gap_y - HALF_PATH_THICKNESS && y < wall_gap_y + HALF_PATH_THICKNESS) {
@ -193,7 +186,7 @@ impl TownBuilder {
}
}
} else {
for x in OFFSET_FROM_LEFT - 1..build_data.width {
for x in OFFSET_FROM_LEFT - 3..build_data.width {
let road_idx = build_data.map.xy_idx(x, y);
build_data.map.tiles[road_idx] = TileType::Road;
}
@ -260,7 +253,6 @@ impl TownBuilder {
}
}
build_data.take_snapshot();
rltk::console::log(format!("Placed building {}", n_buildings));
}
}

View file

@ -42,7 +42,7 @@ impl VoronoiSpawning {
// Spawn the entities
for area in noise_areas.iter() {
spawner::spawn_region(&build_data.map, rng, area.1, build_data.map.depth, &mut build_data.spawn_list);
spawner::spawn_region(&build_data.map, rng, area.1, &mut build_data.spawn_list);
}
}
}

View file

@ -31,7 +31,8 @@ impl WaveFunctionCollapseBuilder {
let constraints = patterns_to_constraints(patterns, CHUNK_SIZE);
self.render_tile_gallery(&constraints, CHUNK_SIZE, build_data);
build_data.map = Map::new(build_data.map.depth, build_data.map.width, build_data.map.height);
build_data.map =
Map::new(build_data.map.id, build_data.map.width, build_data.map.height, build_data.map.difficulty);
loop {
let mut solver = Solver::new(constraints.clone(), CHUNK_SIZE, &build_data.map);
while !solver.iteration(&mut build_data.map, rng) {
@ -46,7 +47,7 @@ impl WaveFunctionCollapseBuilder {
}
fn render_tile_gallery(&mut self, constraints: &[MapChunk], chunk_size: i32, build_data: &mut BuilderMap) {
build_data.map = Map::new(0, build_data.width, build_data.height);
build_data.map = Map::new(0, build_data.width, build_data.height, 0);
let mut counter = 0;
let mut x = 1;
let mut y = 1;
@ -62,7 +63,7 @@ impl WaveFunctionCollapseBuilder {
if y + chunk_size > build_data.map.height {
// Move to the next page
build_data.take_snapshot();
build_data.map = Map::new(0, build_data.width, build_data.height);
build_data.map = Map::new(0, build_data.width, build_data.height, 0);
x = 1;
y = 1;