more work on level generators

This commit is contained in:
Joachim Lusiardi 2024-11-05 12:02:45 +01:00
parent 5311f56ca0
commit 72f7be2ed8
3 changed files with 58 additions and 11 deletions

View File

@ -19,7 +19,7 @@ pub const ROOM_MIN_WIDTH: usize = 4;
pub const ROOM_MIN_HEIGHT: usize = 4; pub const ROOM_MIN_HEIGHT: usize = 4;
/// How many levels does the dungeon have? /// How many levels does the dungeon have?
pub const LEVELS: usize = 2; pub const LEVELS: usize = 4;
/// length of a game frame in ms /// length of a game frame in ms
pub const FRAME_LENGTH: u64 = 100; pub const FRAME_LENGTH: u64 = 100;
@ -46,6 +46,12 @@ pub fn get_monsters_per_level() -> Vec<HashMap<MonsterTypes, std::ops::RangeIncl
(MonsterTypes::Skeleton, 33), (MonsterTypes::Skeleton, 33),
(MonsterTypes::Snake, 33), (MonsterTypes::Snake, 33),
], ],
// level 4
vec![
(MonsterTypes::Orc, 34),
(MonsterTypes::Skeleton, 33),
(MonsterTypes::Snake, 33),
],
]; ];
if tmp.len() < LEVELS { if tmp.len() < LEVELS {
panic!( panic!(
@ -79,8 +85,8 @@ pub fn get_room_type_per_level() -> Vec<HashMap<RoomType, std::ops::RangeInclusi
// level 1 // level 1
vec![ vec![
(RoomType::EmptyRoom, 50), (RoomType::EmptyRoom, 50),
(RoomType::ArtifactRoom, 25), (RoomType::ArtifactRoom, 10),
(RoomType::MonsterRoom, 5), (RoomType::MonsterRoom, 20),
(RoomType::BasicRoom, 20), (RoomType::BasicRoom, 20),
], ],
// level 2 // level 2
@ -91,7 +97,17 @@ pub fn get_room_type_per_level() -> Vec<HashMap<RoomType, std::ops::RangeInclusi
(RoomType::ArtifactRoom, 13), (RoomType::ArtifactRoom, 13),
], ],
// level 3 // level 3
vec![(RoomType::EmptyRoom, 50), (RoomType::MonsterRoom, 50)], vec![
(RoomType::EmptyRoom, 50),
(RoomType::BasicRoom, 25),
(RoomType::MonsterRoom, 25),
],
// level 4
vec![
(RoomType::BasicRoom, 33),
(RoomType::MonsterRoom, 33),
(RoomType::ArtifactRoom, 34),
],
]; ];
if tmp.len() < LEVELS { if tmp.len() < LEVELS {
panic!( panic!(

View File

@ -57,7 +57,7 @@ impl Level {
return (None, None, None); return (None, None, None);
} }
if !self.discovered[x][y] { if !self.discovered[x][y] {
#[cfg(test)] // #[cfg(test)]
return (Some(StructureElement::Unknown), None, None); return (Some(StructureElement::Unknown), None, None);
} }
let search_pos = &Position::new(self.level, x, y); let search_pos = &Position::new(self.level, x, y);

View File

@ -1,5 +1,6 @@
use petgraph::algo::min_spanning_tree; use petgraph::algo::min_spanning_tree;
use petgraph::data::*; use petgraph::data::*;
use petgraph::graph::Edge;
use petgraph::graph::Graph; use petgraph::graph::Graph;
use petgraph::graph::UnGraph; use petgraph::graph::UnGraph;
@ -139,6 +140,11 @@ impl LevelGenerator {
rng: &mut ThreadRng, rng: &mut ThreadRng,
rooms: &[[Room; ROOMS_VERTICAL]; ROOMS_HORIZONTAL], rooms: &[[Room; ROOMS_VERTICAL]; ROOMS_HORIZONTAL],
) -> GeneratorGraph { ) -> GeneratorGraph {
// calculate the weight of an edge
fn calc_edge_weight(delta: usize) -> usize {
delta * delta
}
let mut graph: GeneratorGraph = UnGraph::<(usize, usize), usize>::default(); let mut graph: GeneratorGraph = UnGraph::<(usize, usize), usize>::default();
for (col, tgt_col) in rooms.iter().enumerate().take(ROOMS_HORIZONTAL) { for (col, tgt_col) in rooms.iter().enumerate().take(ROOMS_HORIZONTAL) {
for (row, room) in tgt_col.iter().enumerate().take(ROOMS_VERTICAL) { for (row, room) in tgt_col.iter().enumerate().take(ROOMS_VERTICAL) {
@ -166,8 +172,7 @@ impl LevelGenerator {
graph.add_edge( graph.add_edge(
src_index, src_index,
tgt_index, tgt_index,
(rng.gen_range(0..5) as f32 / 5.0) as usize calc_edge_weight(col.abs_diff(col_1)),
* col.abs_diff(col_1),
); );
break; break;
} }
@ -181,8 +186,7 @@ impl LevelGenerator {
graph.add_edge( graph.add_edge(
src_index, src_index,
tgt_index, tgt_index,
(rng.gen_range(0..5) as f32 / 5.0) as usize calc_edge_weight(row.abs_diff(row_1)),
* row.abs_diff(row_1),
); );
break; break;
} }
@ -191,8 +195,35 @@ impl LevelGenerator {
} }
} }
} }
Graph::from_elements(min_spanning_tree(&graph)) let mut mst: GeneratorGraph = Graph::from_elements(min_spanning_tree(&graph));
// graph
// readd some of the short edges that were remove (all between a weight of 1 to 10)
let initial_edges = graph.raw_edges();
let minimal_edges = mst.raw_edges();
let mut extra_edges: Vec<Edge<usize>> = vec![];
for init_edge in initial_edges {
let start_node = init_edge.source();
let end_node = init_edge.target();
let mut found = false;
for min_edge in minimal_edges {
if min_edge.source() == start_node && min_edge.target() == end_node {
found = true;
break;
}
}
if !found {
extra_edges.push(init_edge.clone());
}
}
extra_edges.sort_by(|a, b| a.weight.cmp(&b.weight));
for e in extra_edges
.iter()
.filter(|x| x.weight > 1)
.filter(|x| x.weight < 7)
{
mst.add_edge(e.source(), e.target(), e.weight);
}
mst
} }
fn create_connections( fn create_connections(