added start and end to exports
This commit is contained in:
+3
-175
@@ -2,6 +2,7 @@ mod exporter;
|
||||
mod layout;
|
||||
mod seed;
|
||||
mod settings;
|
||||
mod startend;
|
||||
mod ui;
|
||||
|
||||
use std::collections::HashSet;
|
||||
@@ -14,6 +15,7 @@ use layout::{
|
||||
DoorSettings, DungeonLayout, WindowSettings, blocked_room_cells, corridor_cells,
|
||||
shortest_path_cells,
|
||||
};
|
||||
use startend::{manual_marker_size, populate_random_markers};
|
||||
use ui::{AddTool, UiSettings, draw_side_panel};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -848,7 +850,7 @@ impl DungeonApp {
|
||||
return;
|
||||
}
|
||||
|
||||
let size = manual_marker_size(&self.settings, kind);
|
||||
let size = manual_marker_size(&self.settings, matches!(kind, MarkerKind::Start));
|
||||
let origin = centered_marker_origin(cell, size, self.settings.cols, self.settings.rows);
|
||||
let marker = layout::AreaMarker { cell: origin, size };
|
||||
|
||||
@@ -2004,180 +2006,6 @@ fn centered_marker_origin(
|
||||
(cell.0.saturating_sub(half).min(max_x), cell.1.saturating_sub(half).min(max_y))
|
||||
}
|
||||
|
||||
fn populate_random_markers(
|
||||
mut layout: DungeonLayout,
|
||||
settings: &UiSettings,
|
||||
) -> DungeonLayout {
|
||||
layout.start_markers.clear();
|
||||
layout.end_markers.clear();
|
||||
|
||||
if layout.rooms.is_empty() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
let start_count = random_range_inclusive(
|
||||
settings.min_start_marker_count,
|
||||
settings.max_start_marker_count,
|
||||
seed::derive_seed(settings.seed, 10_001),
|
||||
);
|
||||
let end_count = random_range_inclusive(
|
||||
settings.min_end_marker_count,
|
||||
settings.max_end_marker_count,
|
||||
seed::derive_seed(settings.seed, 10_002),
|
||||
);
|
||||
let pair_count = start_count.min(end_count);
|
||||
|
||||
let mut available_start_rooms: Vec<usize> = (0..layout.rooms.len()).collect();
|
||||
let mut available_end_rooms: Vec<usize> = (0..layout.rooms.len()).collect();
|
||||
|
||||
for pair_idx in 0..pair_count {
|
||||
let (start_room_idx, end_room_idx) =
|
||||
farthest_room_pair(&layout.rooms, &available_start_rooms, &available_end_rooms);
|
||||
let start_room = &layout.rooms[start_room_idx];
|
||||
let end_room = &layout.rooms[end_room_idx];
|
||||
layout.start_markers.push(marker_in_room(
|
||||
start_room,
|
||||
settings.min_start_marker_size,
|
||||
settings.max_start_marker_size,
|
||||
seed::derive_seed(settings.seed, 11_000 + pair_idx as u64),
|
||||
));
|
||||
layout.end_markers.push(marker_in_room(
|
||||
end_room,
|
||||
settings.min_end_marker_size,
|
||||
settings.max_end_marker_size,
|
||||
seed::derive_seed(settings.seed, 12_000 + pair_idx as u64),
|
||||
));
|
||||
consume_room(&mut available_start_rooms, start_room_idx);
|
||||
consume_room(&mut available_end_rooms, end_room_idx);
|
||||
}
|
||||
|
||||
for idx in pair_count..start_count {
|
||||
let room_idx = pick_room_index(
|
||||
&available_start_rooms,
|
||||
layout.rooms.len(),
|
||||
seed::derive_seed(settings.seed, 13_000 + idx as u64),
|
||||
);
|
||||
let room = &layout.rooms[room_idx];
|
||||
layout.start_markers.push(marker_in_room(
|
||||
room,
|
||||
settings.min_start_marker_size,
|
||||
settings.max_start_marker_size,
|
||||
seed::derive_seed(settings.seed, 14_000 + idx as u64),
|
||||
));
|
||||
consume_room(&mut available_start_rooms, room_idx);
|
||||
}
|
||||
|
||||
for idx in pair_count..end_count {
|
||||
let room_idx = pick_room_index(
|
||||
&available_end_rooms,
|
||||
layout.rooms.len(),
|
||||
seed::derive_seed(settings.seed, 15_000 + idx as u64),
|
||||
);
|
||||
let room = &layout.rooms[room_idx];
|
||||
layout.end_markers.push(marker_in_room(
|
||||
room,
|
||||
settings.min_end_marker_size,
|
||||
settings.max_end_marker_size,
|
||||
seed::derive_seed(settings.seed, 16_000 + idx as u64),
|
||||
));
|
||||
consume_room(&mut available_end_rooms, room_idx);
|
||||
}
|
||||
|
||||
layout
|
||||
}
|
||||
|
||||
fn random_range_inclusive(min: usize, max: usize, seed_value: u64) -> usize {
|
||||
let min = min.max(1);
|
||||
let max = max.max(min);
|
||||
let span = max - min + 1;
|
||||
min + (seed_value as usize % span)
|
||||
}
|
||||
|
||||
fn manual_marker_size(settings: &UiSettings, kind: MarkerKind) -> usize {
|
||||
match kind {
|
||||
MarkerKind::Start => settings.min_start_marker_size.min(settings.max_start_marker_size),
|
||||
MarkerKind::End => settings.min_end_marker_size.min(settings.max_end_marker_size),
|
||||
}
|
||||
.clamp(1, 10)
|
||||
}
|
||||
|
||||
fn marker_in_room(room: &layout::Room, min_size: usize, max_size: usize, seed_value: u64) -> layout::AreaMarker {
|
||||
let room_limit = room.width.min(room.height).max(1);
|
||||
let min_size = min_size.clamp(1, 10).min(room_limit);
|
||||
let max_size = max_size.clamp(min_size, 10).min(room_limit);
|
||||
let size = random_range_inclusive(min_size, max_size, seed_value.rotate_left(7));
|
||||
let x_span = room.width.saturating_sub(size);
|
||||
let y_span = room.height.saturating_sub(size);
|
||||
let x = room.x
|
||||
+ if x_span == 0 {
|
||||
0
|
||||
} else {
|
||||
(seed_value as usize) % (x_span + 1)
|
||||
};
|
||||
let y = room.y
|
||||
+ if y_span == 0 {
|
||||
0
|
||||
} else {
|
||||
(seed_value.rotate_left(19) as usize) % (y_span + 1)
|
||||
};
|
||||
layout::AreaMarker { cell: (x, y), size }
|
||||
}
|
||||
|
||||
fn farthest_room_pair(
|
||||
rooms: &[layout::Room],
|
||||
available_start_rooms: &[usize],
|
||||
available_end_rooms: &[usize],
|
||||
) -> (usize, usize) {
|
||||
let start_rooms = if available_start_rooms.is_empty() {
|
||||
(0..rooms.len()).collect::<Vec<_>>()
|
||||
} else {
|
||||
available_start_rooms.to_vec()
|
||||
};
|
||||
let end_rooms = if available_end_rooms.is_empty() {
|
||||
(0..rooms.len()).collect::<Vec<_>>()
|
||||
} else {
|
||||
available_end_rooms.to_vec()
|
||||
};
|
||||
|
||||
let mut best = (start_rooms[0], end_rooms[0]);
|
||||
let mut best_dist = 0usize;
|
||||
for &start_idx in &start_rooms {
|
||||
for &end_idx in &end_rooms {
|
||||
if rooms.len() > 1 && start_idx == end_idx {
|
||||
continue;
|
||||
}
|
||||
let dist = room_distance_sq(&rooms[start_idx], &rooms[end_idx]);
|
||||
if dist > best_dist {
|
||||
best = (start_idx, end_idx);
|
||||
best_dist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
best
|
||||
}
|
||||
|
||||
fn room_distance_sq(a: &layout::Room, b: &layout::Room) -> usize {
|
||||
let ac = a.center_cell();
|
||||
let bc = b.center_cell();
|
||||
let dx = ac.0.abs_diff(bc.0);
|
||||
let dy = ac.1.abs_diff(bc.1);
|
||||
dx * dx + dy * dy
|
||||
}
|
||||
|
||||
fn consume_room(available_rooms: &mut Vec<usize>, room_idx: usize) {
|
||||
if let Some(pos) = available_rooms.iter().position(|&idx| idx == room_idx) {
|
||||
available_rooms.remove(pos);
|
||||
}
|
||||
}
|
||||
|
||||
fn pick_room_index(available_rooms: &[usize], room_count: usize, seed_value: u64) -> usize {
|
||||
if !available_rooms.is_empty() {
|
||||
available_rooms[seed_value as usize % available_rooms.len()]
|
||||
} else {
|
||||
seed_value as usize % room_count.max(1)
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_area_marker(
|
||||
painter: &egui::Painter,
|
||||
geometry: &GridGeometry,
|
||||
|
||||
Reference in New Issue
Block a user