refactor to remove duplicate/redundant code
This commit is contained in:
+29
-65
@@ -128,6 +128,30 @@ impl Default for DungeonLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DungeonLayout {
|
||||||
|
// Build an empty layout for the current packing mode.
|
||||||
|
pub(crate) fn empty(packed_rooms: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
packed_rooms,
|
||||||
|
..Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build a layout from generated rooms and corridors.
|
||||||
|
fn from_generated_parts(
|
||||||
|
rooms: Vec<Room>,
|
||||||
|
corridors: Vec<Corridor>,
|
||||||
|
packed_rooms: bool,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
rooms,
|
||||||
|
corridors,
|
||||||
|
packed_rooms,
|
||||||
|
..Self::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect all room cells except those belonging to excluded room ids.
|
// Collect all room cells except those belonging to excluded room ids.
|
||||||
pub fn blocked_room_cells(rooms: &[Room], excluded_room_ids: &[usize]) -> HashSet<(usize, usize)> {
|
pub fn blocked_room_cells(rooms: &[Room], excluded_room_ids: &[usize]) -> HashSet<(usize, usize)> {
|
||||||
let excluded: HashSet<usize> = excluded_room_ids.iter().copied().collect();
|
let excluded: HashSet<usize> = excluded_room_ids.iter().copied().collect();
|
||||||
@@ -184,19 +208,7 @@ pub fn generate_layout(
|
|||||||
let mut corridors = Vec::new();
|
let mut corridors = Vec::new();
|
||||||
|
|
||||||
if cols < 2 || rows < 2 || target_room_count == 0 {
|
if cols < 2 || rows < 2 || target_room_count == 0 {
|
||||||
return DungeonLayout {
|
return DungeonLayout::empty(pack_rooms_without_corridors);
|
||||||
rooms,
|
|
||||||
corridors,
|
|
||||||
doors: Vec::new(),
|
|
||||||
windows: Vec::new(),
|
|
||||||
text_labels: Vec::new(),
|
|
||||||
start_markers: Vec::new(),
|
|
||||||
end_markers: Vec::new(),
|
|
||||||
trap_markers: Vec::new(),
|
|
||||||
monster_markers: Vec::new(),
|
|
||||||
packed_rooms: pack_rooms_without_corridors,
|
|
||||||
stairs: Vec::new(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut min_size = min_room_size.max(2);
|
let mut min_size = min_room_size.max(2);
|
||||||
@@ -212,19 +224,7 @@ pub fn generate_layout(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if min_size == 0 || max_size < min_size {
|
if min_size == 0 || max_size < min_size {
|
||||||
return DungeonLayout {
|
return DungeonLayout::empty(pack_rooms_without_corridors);
|
||||||
rooms,
|
|
||||||
corridors,
|
|
||||||
doors: Vec::new(),
|
|
||||||
windows: Vec::new(),
|
|
||||||
text_labels: Vec::new(),
|
|
||||||
start_markers: Vec::new(),
|
|
||||||
end_markers: Vec::new(),
|
|
||||||
trap_markers: Vec::new(),
|
|
||||||
monster_markers: Vec::new(),
|
|
||||||
packed_rooms: pack_rooms_without_corridors,
|
|
||||||
stairs: Vec::new(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let room_sizes = generate_room_sizes(
|
let room_sizes = generate_room_sizes(
|
||||||
@@ -245,19 +245,7 @@ pub fn generate_layout(
|
|||||||
|
|
||||||
if pack_rooms_without_corridors {
|
if pack_rooms_without_corridors {
|
||||||
rooms = place_packed_rooms(&room_sizes, &room_edges, cols, rows, &mut room_rng);
|
rooms = place_packed_rooms(&room_sizes, &room_edges, cols, rows, &mut room_rng);
|
||||||
let mut layout = DungeonLayout {
|
let mut layout = DungeonLayout::from_generated_parts(rooms, corridors, true);
|
||||||
stairs: Vec::new(),
|
|
||||||
rooms,
|
|
||||||
corridors,
|
|
||||||
doors: Vec::new(),
|
|
||||||
windows: Vec::new(),
|
|
||||||
text_labels: Vec::new(),
|
|
||||||
start_markers: Vec::new(),
|
|
||||||
end_markers: Vec::new(),
|
|
||||||
trap_markers: Vec::new(),
|
|
||||||
monster_markers: Vec::new(),
|
|
||||||
packed_rooms: true,
|
|
||||||
};
|
|
||||||
apply_doors(&mut layout, seed, door_settings, cols, rows);
|
apply_doors(&mut layout, seed, door_settings, cols, rows);
|
||||||
apply_windows(&mut layout, seed, window_settings, cols, rows);
|
apply_windows(&mut layout, seed, window_settings, cols, rows);
|
||||||
return layout;
|
return layout;
|
||||||
@@ -307,19 +295,7 @@ pub fn generate_layout(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if rooms.len() < 2 {
|
if rooms.len() < 2 {
|
||||||
return DungeonLayout {
|
return DungeonLayout::from_generated_parts(rooms, corridors, false);
|
||||||
rooms,
|
|
||||||
corridors,
|
|
||||||
doors: Vec::new(),
|
|
||||||
windows: Vec::new(),
|
|
||||||
text_labels: Vec::new(),
|
|
||||||
start_markers: Vec::new(),
|
|
||||||
end_markers: Vec::new(),
|
|
||||||
trap_markers: Vec::new(),
|
|
||||||
monster_markers: Vec::new(),
|
|
||||||
packed_rooms: false,
|
|
||||||
stairs: Vec::new(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut min_width = min_corridor_width.max(1);
|
let mut min_width = min_corridor_width.max(1);
|
||||||
@@ -366,19 +342,7 @@ pub fn generate_layout(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut layout = DungeonLayout {
|
let mut layout = DungeonLayout::from_generated_parts(rooms, corridors, false);
|
||||||
stairs: Vec::new(),
|
|
||||||
rooms,
|
|
||||||
corridors,
|
|
||||||
doors: Vec::new(),
|
|
||||||
windows: Vec::new(),
|
|
||||||
text_labels: Vec::new(),
|
|
||||||
start_markers: Vec::new(),
|
|
||||||
end_markers: Vec::new(),
|
|
||||||
trap_markers: Vec::new(),
|
|
||||||
monster_markers: Vec::new(),
|
|
||||||
packed_rooms: false,
|
|
||||||
};
|
|
||||||
apply_doors(&mut layout, seed, door_settings, cols, rows);
|
apply_doors(&mut layout, seed, door_settings, cols, rows);
|
||||||
apply_windows(&mut layout, seed, window_settings, cols, rows);
|
apply_windows(&mut layout, seed, window_settings, cols, rows);
|
||||||
layout
|
layout
|
||||||
|
|||||||
+32
-52
@@ -72,11 +72,9 @@ impl Default for DungeonApp {
|
|||||||
// Build the app with persisted settings and a generated layout.
|
// Build the app with persisted settings and a generated layout.
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let settings = settings::load_settings().unwrap_or_default();
|
let settings = settings::load_settings().unwrap_or_default();
|
||||||
let layouts = generate_all_levels(&settings);
|
|
||||||
let results = populate_stairs(layouts, &settings);
|
|
||||||
let mut app = Self {
|
let mut app = Self {
|
||||||
settings,
|
settings,
|
||||||
levels: results.iter().map(|(l, _)| l.clone()).collect(),
|
levels: Vec::new(),
|
||||||
suppressed_auto_door_edges: HashSet::new(),
|
suppressed_auto_door_edges: HashSet::new(),
|
||||||
undo_stack: Vec::new(),
|
undo_stack: Vec::new(),
|
||||||
redo_stack: Vec::new(),
|
redo_stack: Vec::new(),
|
||||||
@@ -93,11 +91,8 @@ impl Default for DungeonApp {
|
|||||||
hover_level_idx: None,
|
hover_level_idx: None,
|
||||||
hover_stair_idx: None,
|
hover_stair_idx: None,
|
||||||
};
|
};
|
||||||
for (i, (_, modified)) in results.into_iter().enumerate() {
|
app.levels = generate_all_levels(&app.settings);
|
||||||
if modified {
|
app.refresh_stairs();
|
||||||
app.refresh_level(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
app
|
app
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,33 +165,9 @@ impl eframe::App for DungeonApp {
|
|||||||
}
|
}
|
||||||
} else if panel_result.new_level_clicked {
|
} else if panel_result.new_level_clicked {
|
||||||
self.push_undo_snapshot();
|
self.push_undo_snapshot();
|
||||||
let level_index = self.levels.len();
|
self.levels
|
||||||
let level_seed = seed::derive_seed(self.settings.seed, level_index as u64);
|
.push(generate_level(&self.settings, self.levels.len()));
|
||||||
let layout = layout::generate_layout(
|
self.refresh_stairs();
|
||||||
self.settings.cols,
|
|
||||||
self.settings.rows,
|
|
||||||
self.settings.room_count,
|
|
||||||
level_seed,
|
|
||||||
self.settings.min_room_size,
|
|
||||||
self.settings.max_room_size,
|
|
||||||
self.settings.square_rooms_only,
|
|
||||||
self.settings.min_corridor_width,
|
|
||||||
self.settings.max_corridor_width,
|
|
||||||
self.settings.corridor_randomness,
|
|
||||||
self.settings.dead_end_rooms_percent,
|
|
||||||
self.settings.pack_rooms_without_corridors,
|
|
||||||
door_settings_from_ui(&self.settings),
|
|
||||||
window_settings_from_ui(&self.settings),
|
|
||||||
);
|
|
||||||
let layout = populate_random_markers(layout, &self.settings);
|
|
||||||
self.levels.push(layout);
|
|
||||||
let results = populate_stairs(self.levels.clone(), &self.settings);
|
|
||||||
self.levels = results.iter().map(|(l, _)| l.clone()).collect();
|
|
||||||
for (i, (_, modified)) in results.into_iter().enumerate() {
|
|
||||||
if modified {
|
|
||||||
self.refresh_level(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.settings.active_level_index = self.levels.len() - 1;
|
self.settings.active_level_index = self.levels.len() - 1;
|
||||||
}
|
}
|
||||||
if ctx.input(|i| i.key_pressed(egui::Key::Delete) || i.key_pressed(egui::Key::Backspace)) {
|
if ctx.input(|i| i.key_pressed(egui::Key::Delete) || i.key_pressed(egui::Key::Backspace)) {
|
||||||
@@ -385,7 +356,14 @@ fn generate_all_levels(settings: &UiSettings) -> Vec<DungeonLayout> {
|
|||||||
|
|
||||||
let mut levels = Vec::with_capacity(level_count);
|
let mut levels = Vec::with_capacity(level_count);
|
||||||
for i in 0..level_count {
|
for i in 0..level_count {
|
||||||
let level_seed = seed::derive_seed(settings.seed, i as u64);
|
levels.push(generate_level(settings, i));
|
||||||
|
}
|
||||||
|
levels
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate one dungeon level from the current settings.
|
||||||
|
fn generate_level(settings: &UiSettings, level_index: usize) -> DungeonLayout {
|
||||||
|
let level_seed = seed::derive_seed(settings.seed, level_index as u64);
|
||||||
let layout = layout::generate_layout(
|
let layout = layout::generate_layout(
|
||||||
settings.cols,
|
settings.cols,
|
||||||
settings.rows,
|
settings.rows,
|
||||||
@@ -402,10 +380,8 @@ fn generate_all_levels(settings: &UiSettings) -> Vec<DungeonLayout> {
|
|||||||
door_settings_from_ui(settings),
|
door_settings_from_ui(settings),
|
||||||
window_settings_from_ui(settings),
|
window_settings_from_ui(settings),
|
||||||
);
|
);
|
||||||
let layout = populate_random_markers(layout, settings);
|
|
||||||
levels.push(layout);
|
populate_random_markers(layout, settings)
|
||||||
}
|
|
||||||
levels
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clamp_dependent_settings(settings: &mut UiSettings) {
|
fn clamp_dependent_settings(settings: &mut UiSettings) {
|
||||||
@@ -514,10 +490,8 @@ impl DungeonApp {
|
|||||||
if self.settings.active_level_index >= self.levels.len() {
|
if self.settings.active_level_index >= self.levels.len() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.levels[self.settings.active_level_index] = DungeonLayout {
|
self.levels[self.settings.active_level_index] =
|
||||||
packed_rooms: self.settings.pack_rooms_without_corridors,
|
DungeonLayout::empty(self.settings.pack_rooms_without_corridors);
|
||||||
..DungeonLayout::default()
|
|
||||||
};
|
|
||||||
self.suppressed_auto_door_edges.clear();
|
self.suppressed_auto_door_edges.clear();
|
||||||
self.reset_transient_state();
|
self.reset_transient_state();
|
||||||
}
|
}
|
||||||
@@ -526,14 +500,8 @@ impl DungeonApp {
|
|||||||
fn regenerate_layout(&mut self) {
|
fn regenerate_layout(&mut self) {
|
||||||
self.drag_state = None;
|
self.drag_state = None;
|
||||||
self.suppressed_auto_door_edges.clear();
|
self.suppressed_auto_door_edges.clear();
|
||||||
let layouts = generate_all_levels(&self.settings);
|
self.levels = generate_all_levels(&self.settings);
|
||||||
let results = populate_stairs(layouts, &self.settings);
|
self.refresh_stairs();
|
||||||
self.levels = results.iter().map(|(l, _)| l.clone()).collect();
|
|
||||||
for (i, (_, modified)) in results.into_iter().enumerate() {
|
|
||||||
if modified {
|
|
||||||
self.refresh_level(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if self.settings.active_level_index >= self.levels.len() {
|
if self.settings.active_level_index >= self.levels.len() {
|
||||||
self.settings.active_level_index = 0;
|
self.settings.active_level_index = 0;
|
||||||
}
|
}
|
||||||
@@ -882,6 +850,18 @@ impl DungeonApp {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync stair placement across all generated levels.
|
||||||
|
fn refresh_stairs(&mut self) {
|
||||||
|
let results = populate_stairs(self.levels.clone(), &self.settings);
|
||||||
|
self.levels = results.iter().map(|(layout, _)| layout.clone()).collect();
|
||||||
|
|
||||||
|
for (level_idx, (_, modified)) in results.into_iter().enumerate() {
|
||||||
|
if modified {
|
||||||
|
self.refresh_level(level_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn refresh_doors(&mut self) {
|
fn refresh_doors(&mut self) {
|
||||||
if self.settings.active_level_index >= self.levels.len() {
|
if self.settings.active_level_index >= self.levels.len() {
|
||||||
return;
|
return;
|
||||||
|
|||||||
+97
-74
@@ -242,101 +242,124 @@ fn pick_room_index(available_rooms: &[usize], room_count: usize, seed_value: u64
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn populate_random_traps(mut layout: DungeonLayout, settings: &UiSettings) -> DungeonLayout {
|
pub fn populate_random_traps(mut layout: DungeonLayout, settings: &UiSettings) -> DungeonLayout {
|
||||||
if settings.trap_frequency_percent == 0 {
|
layout.trap_markers = populate_random_area_markers(
|
||||||
return layout;
|
&layout,
|
||||||
}
|
settings.seed,
|
||||||
|
settings.trap_frequency_percent,
|
||||||
let mut trap_markers = Vec::new();
|
|
||||||
|
|
||||||
// Rooms
|
|
||||||
for (idx, room) in layout.rooms.iter().enumerate() {
|
|
||||||
let seed = seed::derive_seed(settings.seed, TRAP_ROOM_STREAM_BASE + idx as u64);
|
|
||||||
if (seed % 100) < settings.trap_frequency_percent as u64 {
|
|
||||||
let count = random_range_inclusive(
|
|
||||||
settings.min_traps_per_area,
|
settings.min_traps_per_area,
|
||||||
settings.max_traps_per_area,
|
settings.max_traps_per_area,
|
||||||
seed.rotate_left(13),
|
TRAP_ROOM_STREAM_BASE,
|
||||||
|
TRAP_CORRIDOR_STREAM_BASE,
|
||||||
);
|
);
|
||||||
for i in 0..count {
|
|
||||||
trap_markers.push(marker_in_room(
|
|
||||||
room,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
seed.wrapping_add(i as u64).rotate_right(7),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Corridors
|
|
||||||
for (idx, corridor) in layout.corridors.iter().enumerate() {
|
|
||||||
let seed = seed::derive_seed(settings.seed, TRAP_CORRIDOR_STREAM_BASE + idx as u64);
|
|
||||||
if (seed % 100) < settings.trap_frequency_percent as u64 {
|
|
||||||
let count = random_range_inclusive(
|
|
||||||
settings.min_traps_per_area,
|
|
||||||
settings.max_traps_per_area,
|
|
||||||
seed.rotate_left(13),
|
|
||||||
);
|
|
||||||
for i in 0..count {
|
|
||||||
if let Some(cell) = pick_random_corridor_cell(corridor, seed.wrapping_add(i as u64))
|
|
||||||
{
|
|
||||||
trap_markers.push(layout::AreaMarker { cell, size: 1 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.trap_markers = trap_markers;
|
|
||||||
layout
|
layout
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn populate_random_monsters(mut layout: DungeonLayout, settings: &UiSettings) -> DungeonLayout {
|
pub fn populate_random_monsters(mut layout: DungeonLayout, settings: &UiSettings) -> DungeonLayout {
|
||||||
if settings.monster_frequency_percent == 0 {
|
layout.monster_markers = populate_random_area_markers(
|
||||||
return layout;
|
&layout,
|
||||||
}
|
settings.seed,
|
||||||
|
settings.monster_frequency_percent,
|
||||||
let mut monster_markers = Vec::new();
|
|
||||||
|
|
||||||
// Rooms
|
|
||||||
for (idx, room) in layout.rooms.iter().enumerate() {
|
|
||||||
let seed = seed::derive_seed(settings.seed, MONSTER_ROOM_STREAM_BASE + idx as u64);
|
|
||||||
if (seed % 100) < settings.monster_frequency_percent as u64 {
|
|
||||||
let count = random_range_inclusive(
|
|
||||||
settings.min_monsters_per_area,
|
settings.min_monsters_per_area,
|
||||||
settings.max_monsters_per_area,
|
settings.max_monsters_per_area,
|
||||||
seed.rotate_left(13),
|
MONSTER_ROOM_STREAM_BASE,
|
||||||
|
MONSTER_CORRIDOR_STREAM_BASE,
|
||||||
);
|
);
|
||||||
for i in 0..count {
|
layout
|
||||||
monster_markers.push(marker_in_room(
|
}
|
||||||
|
|
||||||
|
// Populate simple one-cell area markers in rooms and corridors.
|
||||||
|
fn populate_random_area_markers(
|
||||||
|
layout: &DungeonLayout,
|
||||||
|
master_seed: u64,
|
||||||
|
frequency_percent: usize,
|
||||||
|
min_count: usize,
|
||||||
|
max_count: usize,
|
||||||
|
room_stream_base: u64,
|
||||||
|
corridor_stream_base: u64,
|
||||||
|
) -> Vec<layout::AreaMarker> {
|
||||||
|
if frequency_percent == 0 {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut markers = Vec::new();
|
||||||
|
|
||||||
|
for (idx, room) in layout.rooms.iter().enumerate() {
|
||||||
|
let area_seed = seed::derive_seed(master_seed, room_stream_base + idx as u64);
|
||||||
|
append_room_markers(
|
||||||
|
&mut markers,
|
||||||
|
room,
|
||||||
|
area_seed,
|
||||||
|
frequency_percent,
|
||||||
|
min_count,
|
||||||
|
max_count,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (idx, corridor) in layout.corridors.iter().enumerate() {
|
||||||
|
let area_seed = seed::derive_seed(master_seed, corridor_stream_base + idx as u64);
|
||||||
|
append_corridor_markers(
|
||||||
|
&mut markers,
|
||||||
|
corridor,
|
||||||
|
area_seed,
|
||||||
|
frequency_percent,
|
||||||
|
min_count,
|
||||||
|
max_count,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
markers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add room markers when the room passes the frequency roll.
|
||||||
|
fn append_room_markers(
|
||||||
|
markers: &mut Vec<layout::AreaMarker>,
|
||||||
|
room: &layout::Room,
|
||||||
|
area_seed: u64,
|
||||||
|
frequency_percent: usize,
|
||||||
|
min_count: usize,
|
||||||
|
max_count: usize,
|
||||||
|
) {
|
||||||
|
if !passes_frequency_roll(area_seed, frequency_percent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let count = random_range_inclusive(min_count, max_count, area_seed.rotate_left(13));
|
||||||
|
for offset in 0..count {
|
||||||
|
markers.push(marker_in_room(
|
||||||
room,
|
room,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
seed.wrapping_add(i as u64).rotate_right(7),
|
area_seed.wrapping_add(offset as u64).rotate_right(7),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add corridor markers when the corridor passes the frequency roll.
|
||||||
|
fn append_corridor_markers(
|
||||||
|
markers: &mut Vec<layout::AreaMarker>,
|
||||||
|
corridor: &layout::Corridor,
|
||||||
|
area_seed: u64,
|
||||||
|
frequency_percent: usize,
|
||||||
|
min_count: usize,
|
||||||
|
max_count: usize,
|
||||||
|
) {
|
||||||
|
if !passes_frequency_roll(area_seed, frequency_percent) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Corridors
|
let count = random_range_inclusive(min_count, max_count, area_seed.rotate_left(13));
|
||||||
for (idx, corridor) in layout.corridors.iter().enumerate() {
|
for offset in 0..count {
|
||||||
let seed = seed::derive_seed(settings.seed, MONSTER_CORRIDOR_STREAM_BASE + idx as u64);
|
if let Some(cell) =
|
||||||
if (seed % 100) < settings.monster_frequency_percent as u64 {
|
pick_random_corridor_cell(corridor, area_seed.wrapping_add(offset as u64))
|
||||||
let count = random_range_inclusive(
|
|
||||||
settings.min_monsters_per_area,
|
|
||||||
settings.max_monsters_per_area,
|
|
||||||
seed.rotate_left(13),
|
|
||||||
);
|
|
||||||
for i in 0..count {
|
|
||||||
if let Some(cell) = pick_random_corridor_cell(corridor, seed.wrapping_add(i as u64))
|
|
||||||
{
|
{
|
||||||
monster_markers.push(layout::AreaMarker { cell, size: 1 });
|
markers.push(layout::AreaMarker { cell, size: 1 });
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
layout.monster_markers = monster_markers;
|
// Check whether an area spawns markers.
|
||||||
layout
|
fn passes_frequency_roll(area_seed: u64, frequency_percent: usize) -> bool {
|
||||||
|
(area_seed % 100) < frequency_percent as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pick_random_corridor_cell(
|
fn pick_random_corridor_cell(
|
||||||
|
|||||||
Reference in New Issue
Block a user