2023-12-04 18:41:21 +01:00
|
|
|
use petgraph::algo::min_spanning_tree;
|
|
|
|
use petgraph::data::*;
|
2024-11-05 12:02:45 +01:00
|
|
|
use petgraph::graph::Edge;
|
2023-12-04 18:41:21 +01:00
|
|
|
use petgraph::graph::Graph;
|
|
|
|
use petgraph::graph::UnGraph;
|
2024-10-29 06:48:45 +01:00
|
|
|
|
2024-10-20 14:59:20 +02:00
|
|
|
use rand::Rng;
|
2024-10-29 06:48:45 +01:00
|
|
|
use rand::{rngs::ThreadRng, seq::SliceRandom};
|
2023-12-04 18:41:21 +01:00
|
|
|
|
2024-10-30 08:56:45 +01:00
|
|
|
use crate::artifacts::Artifact;
|
|
|
|
use crate::artifacts::Chest;
|
|
|
|
use crate::artifacts::Potion;
|
|
|
|
use crate::constants::get_monsters_per_level;
|
2024-10-29 06:48:45 +01:00
|
|
|
use crate::constants::ROOM_HEIGHT;
|
|
|
|
use crate::constants::ROOM_WIDTH;
|
2024-10-30 08:56:45 +01:00
|
|
|
use crate::monster::create_monster_by_type;
|
|
|
|
use crate::monster::Monster;
|
|
|
|
use crate::position::Position;
|
2024-10-29 06:48:45 +01:00
|
|
|
use crate::room::Connection;
|
|
|
|
use crate::{
|
|
|
|
constants::{
|
2024-10-31 07:48:22 +01:00
|
|
|
get_room_type_per_level, LEVEL_HEIGHT, LEVEL_WIDTH, ROOMS_HORIZONTAL, ROOMS_VERTICAL,
|
2024-10-29 06:48:45 +01:00
|
|
|
},
|
|
|
|
level::{Level, StructureElement},
|
|
|
|
room::{Room, RoomType},
|
2024-10-26 17:00:51 +02:00
|
|
|
};
|
2023-12-04 18:41:21 +01:00
|
|
|
|
2024-11-01 13:08:02 +01:00
|
|
|
type GeneratorGraph = Graph<(usize, usize), usize, petgraph::Undirected>;
|
2023-12-04 18:41:21 +01:00
|
|
|
pub struct LevelGenerator {
|
2023-12-07 10:12:44 +01:00
|
|
|
level: usize,
|
2024-10-31 07:48:22 +01:00
|
|
|
rooms: [[Room; ROOMS_VERTICAL]; ROOMS_HORIZONTAL],
|
2024-10-30 08:56:45 +01:00
|
|
|
rng: ThreadRng,
|
2024-10-29 06:48:45 +01:00
|
|
|
}
|
|
|
|
enum Direction {
|
|
|
|
Horizontal,
|
|
|
|
Vertical,
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl LevelGenerator {
|
2024-10-31 09:58:15 +01:00
|
|
|
fn generate_rooms_to_place(
|
2024-10-31 07:48:22 +01:00
|
|
|
rng: &mut ThreadRng,
|
|
|
|
level: usize,
|
|
|
|
first: bool,
|
|
|
|
last: bool,
|
|
|
|
) -> Vec<Room> {
|
|
|
|
let mut rooms_to_place: Vec<Room> = Vec::with_capacity(ROOMS_VERTICAL * ROOMS_HORIZONTAL);
|
2023-12-04 18:41:21 +01:00
|
|
|
|
2024-10-31 07:48:22 +01:00
|
|
|
let mut start_room = Room::new(rng);
|
2024-10-29 06:48:45 +01:00
|
|
|
if first {
|
|
|
|
start_room.kind = RoomType::Start;
|
|
|
|
} else {
|
|
|
|
start_room.kind = RoomType::StairUp;
|
|
|
|
}
|
|
|
|
rooms_to_place.push(start_room);
|
2024-10-31 07:48:22 +01:00
|
|
|
for _ in 2..ROOMS_HORIZONTAL * ROOMS_VERTICAL {
|
|
|
|
let mut room = Room::new(rng);
|
|
|
|
room.kind = LevelGenerator::select_room_type(level, rng);
|
|
|
|
if room.kind != RoomType::EmptyRoom {
|
|
|
|
rooms_to_place.push(room);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let mut end_room = Room::new(rng);
|
2024-10-29 06:48:45 +01:00
|
|
|
if last {
|
|
|
|
end_room.kind = RoomType::End;
|
|
|
|
} else {
|
|
|
|
end_room.kind = RoomType::StairDown;
|
|
|
|
}
|
|
|
|
rooms_to_place.push(end_room);
|
2024-10-31 07:48:22 +01:00
|
|
|
rooms_to_place
|
|
|
|
}
|
|
|
|
|
2024-10-31 09:58:15 +01:00
|
|
|
fn place_rooms(
|
2024-10-31 07:48:22 +01:00
|
|
|
rng: &mut ThreadRng,
|
|
|
|
rooms_to_place: &mut Vec<Room>,
|
|
|
|
) -> [[Room; ROOMS_VERTICAL]; ROOMS_HORIZONTAL] {
|
|
|
|
let mut rooms: [[Room; 7]; 8] = [[Room::new(rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
let mut room_row = rng.gen_range(0..ROOMS_VERTICAL);
|
|
|
|
let mut room_col = rng.gen_range(0..ROOMS_HORIZONTAL);
|
2024-10-29 06:48:45 +01:00
|
|
|
rooms[room_col][room_row] = rooms_to_place.pop().unwrap();
|
|
|
|
while let Some(room) = rooms_to_place.pop() {
|
2024-10-31 07:48:22 +01:00
|
|
|
let mut placed = false;
|
|
|
|
// randomize going horizontal or vertical
|
2024-10-29 06:48:45 +01:00
|
|
|
let mut directions_to_try = vec![Direction::Horizontal, Direction::Vertical];
|
2024-10-31 07:48:22 +01:00
|
|
|
directions_to_try.shuffle(rng);
|
2024-10-29 06:48:45 +01:00
|
|
|
while !directions_to_try.is_empty() {
|
|
|
|
match directions_to_try.pop().unwrap() {
|
|
|
|
Direction::Horizontal => {
|
|
|
|
let mut free_cols: Vec<usize> = vec![];
|
2024-10-31 22:36:23 +01:00
|
|
|
for (col, room_col) in rooms.iter().enumerate().take(ROOMS_HORIZONTAL) {
|
|
|
|
if room_col[room_row].kind == RoomType::EmptyRoom {
|
2024-10-29 06:48:45 +01:00
|
|
|
free_cols.push(col);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if free_cols.is_empty() {
|
|
|
|
continue;
|
|
|
|
}
|
2024-10-31 07:48:22 +01:00
|
|
|
free_cols.shuffle(rng);
|
2024-10-29 06:48:45 +01:00
|
|
|
room_col = *free_cols.first().unwrap();
|
|
|
|
rooms[room_col][room_row] = room;
|
2024-10-31 07:48:22 +01:00
|
|
|
placed = true;
|
2023-12-04 18:41:21 +01:00
|
|
|
break;
|
|
|
|
}
|
2024-10-29 06:48:45 +01:00
|
|
|
Direction::Vertical => {
|
|
|
|
let mut free_rows: Vec<usize> = vec![];
|
|
|
|
for row in 0..ROOMS_VERTICAL {
|
|
|
|
if rooms[room_col][row].kind == RoomType::EmptyRoom {
|
|
|
|
free_rows.push(row);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if free_rows.is_empty() {
|
|
|
|
continue;
|
|
|
|
}
|
2024-10-31 07:48:22 +01:00
|
|
|
free_rows.shuffle(rng);
|
2024-10-29 06:48:45 +01:00
|
|
|
room_row = *free_rows.first().unwrap();
|
|
|
|
rooms[room_col][room_row] = room;
|
2024-10-31 07:48:22 +01:00
|
|
|
placed = true;
|
2023-12-04 18:41:21 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-31 07:48:22 +01:00
|
|
|
// all fields in the row/column was full so we can place it at any empty position
|
|
|
|
if !placed {
|
|
|
|
let mut free_pos: Vec<(usize, usize)> = vec![];
|
2024-10-31 22:36:23 +01:00
|
|
|
for (col, room_col) in rooms.iter().enumerate().take(ROOMS_HORIZONTAL) {
|
|
|
|
for (row, room) in room_col.iter().enumerate().take(ROOMS_VERTICAL) {
|
|
|
|
if room.kind == RoomType::EmptyRoom {
|
2024-10-31 07:48:22 +01:00
|
|
|
free_pos.push((col, row));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let selected_pos = free_pos[rng.gen_range(0..free_pos.len())];
|
|
|
|
rooms[selected_pos.0][selected_pos.1] = room;
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
2024-10-29 06:48:45 +01:00
|
|
|
}
|
2024-10-31 07:48:22 +01:00
|
|
|
rooms
|
|
|
|
}
|
2024-10-29 06:48:45 +01:00
|
|
|
|
2024-11-06 09:22:22 +01:00
|
|
|
fn create_mst(rooms: &[[Room; ROOMS_VERTICAL]; ROOMS_HORIZONTAL]) -> GeneratorGraph {
|
2024-11-05 12:02:45 +01:00
|
|
|
// calculate the weight of an edge
|
|
|
|
fn calc_edge_weight(delta: usize) -> usize {
|
|
|
|
delta * delta
|
|
|
|
}
|
|
|
|
|
2024-11-01 13:08:02 +01:00
|
|
|
let mut graph: GeneratorGraph = UnGraph::<(usize, usize), usize>::default();
|
2024-10-31 22:36:23 +01:00
|
|
|
for (col, tgt_col) in rooms.iter().enumerate().take(ROOMS_HORIZONTAL) {
|
|
|
|
for (row, room) in tgt_col.iter().enumerate().take(ROOMS_VERTICAL) {
|
|
|
|
if room.kind != RoomType::EmptyRoom {
|
2024-10-29 06:48:45 +01:00
|
|
|
graph.add_node((col, row));
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-31 07:48:22 +01:00
|
|
|
for col in 0..ROOMS_HORIZONTAL {
|
2024-10-29 06:48:45 +01:00
|
|
|
for row in 0..ROOMS_VERTICAL {
|
|
|
|
if rooms[col][row].kind == RoomType::EmptyRoom {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if let Some(src_index) = graph.node_indices().find(|i| graph[*i] == (col, row)) {
|
2024-10-31 22:36:23 +01:00
|
|
|
for (col_1, tgt_col) in rooms
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.take(ROOMS_HORIZONTAL)
|
|
|
|
.skip(col + 1)
|
|
|
|
{
|
|
|
|
if tgt_col[row].kind != RoomType::EmptyRoom {
|
2024-10-29 06:48:45 +01:00
|
|
|
if let Some(tgt_index) =
|
|
|
|
graph.node_indices().find(|i| graph[*i] == (col_1, row))
|
|
|
|
{
|
2024-11-01 13:08:02 +01:00
|
|
|
graph.add_edge(
|
|
|
|
src_index,
|
|
|
|
tgt_index,
|
2024-11-05 12:02:45 +01:00
|
|
|
calc_edge_weight(col.abs_diff(col_1)),
|
2024-11-01 13:08:02 +01:00
|
|
|
);
|
2024-10-29 06:48:45 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
|
|
|
}
|
2024-10-29 06:48:45 +01:00
|
|
|
for row_1 in row + 1..ROOMS_VERTICAL {
|
|
|
|
if rooms[col][row_1].kind != RoomType::EmptyRoom {
|
|
|
|
if let Some(tgt_index) =
|
|
|
|
graph.node_indices().find(|i| graph[*i] == (col, row_1))
|
|
|
|
{
|
2024-11-01 13:08:02 +01:00
|
|
|
graph.add_edge(
|
|
|
|
src_index,
|
|
|
|
tgt_index,
|
2024-11-05 12:02:45 +01:00
|
|
|
calc_edge_weight(row.abs_diff(row_1)),
|
2024-11-01 13:08:02 +01:00
|
|
|
);
|
2024-10-29 06:48:45 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-11-05 12:02:45 +01:00
|
|
|
let mut mst: GeneratorGraph = Graph::from_elements(min_spanning_tree(&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
|
2024-10-31 07:48:22 +01:00
|
|
|
}
|
|
|
|
|
2024-10-31 09:58:15 +01:00
|
|
|
fn create_connections(
|
|
|
|
rooms: &mut [[Room; ROOMS_VERTICAL]; ROOMS_HORIZONTAL],
|
2024-11-01 13:08:02 +01:00
|
|
|
mst: &GeneratorGraph,
|
2024-10-31 09:58:15 +01:00
|
|
|
) {
|
|
|
|
for edge in mst.raw_edges() {
|
|
|
|
// the tuples are (col, row)
|
|
|
|
let (src_node_col, src_node_row) = mst[edge.source()];
|
|
|
|
let (tgt_node_col, tgt_node_row) = mst[edge.target()];
|
|
|
|
let src_room = rooms[src_node_col][src_node_row];
|
|
|
|
let tgt_room = rooms[tgt_node_col][tgt_node_row];
|
|
|
|
|
|
|
|
if src_node_col == tgt_node_col {
|
2024-10-31 22:36:23 +01:00
|
|
|
// Right
|
2024-10-31 15:20:39 +01:00
|
|
|
let start_col =
|
2024-10-31 09:58:15 +01:00
|
|
|
src_node_col * ROOM_WIDTH + src_room.offset_x + (src_room.width + 1) / 2;
|
|
|
|
let start_row =
|
|
|
|
src_node_row * ROOM_HEIGHT + src_room.offset_y + src_room.height + 1;
|
|
|
|
let end_col =
|
|
|
|
tgt_node_col * ROOM_WIDTH + tgt_room.offset_x + (tgt_room.width + 1) / 2;
|
2024-10-31 15:20:39 +01:00
|
|
|
let end_row = 1 + tgt_node_row * ROOM_HEIGHT - 1 + tgt_room.offset_y;
|
2024-10-31 09:58:15 +01:00
|
|
|
rooms[src_node_col][src_node_row].connection_down = Some(Connection {
|
|
|
|
start_pos: (start_col, start_row),
|
|
|
|
end_pos: (end_col, end_row),
|
|
|
|
});
|
|
|
|
} else {
|
2024-10-31 22:36:23 +01:00
|
|
|
// Down
|
2024-10-31 21:52:04 +01:00
|
|
|
let start_col =
|
|
|
|
1 + (src_node_col * ROOM_WIDTH) + src_room.offset_x + src_room.width;
|
2024-10-31 09:58:15 +01:00
|
|
|
let start_row =
|
2024-10-31 21:52:04 +01:00
|
|
|
1 + src_node_row * ROOM_HEIGHT + src_room.offset_y + (src_room.height - 1) / 2;
|
2024-10-31 15:20:39 +01:00
|
|
|
let end_col = 1 + tgt_node_col * ROOM_WIDTH - 1 + tgt_room.offset_x;
|
2024-10-31 09:58:15 +01:00
|
|
|
let end_row =
|
2024-10-31 21:52:04 +01:00
|
|
|
1 + tgt_node_row * ROOM_HEIGHT + tgt_room.offset_y + (tgt_room.height - 1) / 2;
|
2024-10-31 09:58:15 +01:00
|
|
|
rooms[src_node_col][src_node_row].connection_right = Some(Connection {
|
|
|
|
start_pos: (start_col, start_row),
|
|
|
|
end_pos: (end_col, end_row),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-31 07:48:22 +01:00
|
|
|
pub fn generate(level: usize, first: bool, last: bool) -> Self {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
|
|
|
|
let mut rooms_to_place: Vec<Room> =
|
|
|
|
LevelGenerator::generate_rooms_to_place(&mut rng, level, first, last);
|
|
|
|
let mut rooms: [[Room; 7]; 8] = LevelGenerator::place_rooms(&mut rng, &mut rooms_to_place);
|
|
|
|
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
2024-10-31 07:48:22 +01:00
|
|
|
LevelGenerator { level, rooms, rng }
|
2024-10-30 08:56:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fn select_monster(position: Position, rng: &mut ThreadRng) -> Box<dyn Monster> {
|
|
|
|
let level = position.get_level();
|
|
|
|
let value = rng.gen_range(1..=100);
|
|
|
|
|
|
|
|
let t = get_monsters_per_level();
|
|
|
|
if level < t.len() {
|
|
|
|
for (mtype, range) in &t[level] {
|
|
|
|
if range.contains(&value) {
|
|
|
|
return create_monster_by_type(mtype, position);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic!("no monster selectable!");
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
2024-10-24 08:57:52 +02:00
|
|
|
|
2024-10-29 06:48:45 +01:00
|
|
|
fn select_room_type(level: usize, rng: &mut ThreadRng) -> RoomType {
|
2024-10-24 08:57:52 +02:00
|
|
|
let value = rng.gen_range(1..=100);
|
|
|
|
|
2024-10-29 06:48:45 +01:00
|
|
|
let t = get_room_type_per_level();
|
2024-10-24 08:57:52 +02:00
|
|
|
if level < t.len() {
|
|
|
|
for (mtype, range) in &t[level] {
|
|
|
|
if range.contains(&value) {
|
2024-10-29 06:48:45 +01:00
|
|
|
return *mtype;
|
2024-10-24 08:57:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-29 06:48:45 +01:00
|
|
|
panic!("no room selectable!");
|
2024-10-24 08:57:52 +02:00
|
|
|
}
|
|
|
|
|
2024-10-29 06:48:45 +01:00
|
|
|
pub fn render(&mut self) -> Level {
|
|
|
|
let mut structure = [[StructureElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH];
|
|
|
|
let mut start_pos = (0, 0);
|
|
|
|
let mut end_pos = (0, 0);
|
2024-10-30 08:56:45 +01:00
|
|
|
let mut monsters: Vec<Box<dyn Monster>> = Vec::with_capacity(10);
|
|
|
|
let mut artifacts: Vec<Box<dyn Artifact>> = Vec::with_capacity(10);
|
2024-10-31 07:48:22 +01:00
|
|
|
for col in 0..ROOMS_HORIZONTAL {
|
2024-10-29 06:48:45 +01:00
|
|
|
for row in 0..ROOMS_VERTICAL {
|
2024-10-30 08:56:45 +01:00
|
|
|
let room = self.rooms[col][row];
|
|
|
|
let position = room.render(&mut structure, col, row);
|
|
|
|
match room.kind {
|
2024-10-31 07:48:22 +01:00
|
|
|
RoomType::Start => start_pos = position,
|
|
|
|
RoomType::End => end_pos = position,
|
|
|
|
RoomType::StairUp => start_pos = position,
|
|
|
|
RoomType::StairDown => end_pos = position,
|
|
|
|
RoomType::BasicRoom => {}
|
2024-10-30 08:56:45 +01:00
|
|
|
RoomType::ArtifactRoom => {
|
|
|
|
match self.rng.gen_range(1..=100) {
|
|
|
|
1..=50 => {
|
2024-10-31 07:48:22 +01:00
|
|
|
artifacts.push(Box::new(Chest::new(Position::new(
|
|
|
|
self.level, position.0, position.1,
|
|
|
|
))));
|
2024-10-30 08:56:45 +01:00
|
|
|
}
|
|
|
|
_ => {
|
2024-10-31 07:48:22 +01:00
|
|
|
artifacts.push(Box::new(Potion::new(Position::new(
|
|
|
|
self.level, position.0, position.1,
|
|
|
|
))));
|
2024-10-30 08:56:45 +01:00
|
|
|
}
|
|
|
|
};
|
2024-10-31 07:48:22 +01:00
|
|
|
}
|
2024-10-30 08:56:45 +01:00
|
|
|
RoomType::MonsterRoom => {
|
|
|
|
monsters.push(LevelGenerator::select_monster(
|
|
|
|
Position::new(self.level, position.0, position.1),
|
|
|
|
&mut self.rng,
|
|
|
|
));
|
2024-10-31 07:48:22 +01:00
|
|
|
}
|
|
|
|
RoomType::EmptyRoom => {}
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-31 07:48:22 +01:00
|
|
|
for col in 0..ROOMS_HORIZONTAL {
|
2024-10-29 06:48:45 +01:00
|
|
|
for row in 0..ROOMS_VERTICAL {
|
|
|
|
if let Some(connection) = self.rooms[col][row].connection_down {
|
|
|
|
// println!("down");
|
2024-11-01 12:02:11 +01:00
|
|
|
connection.render(&mut self.rng, &mut structure);
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
2024-10-29 06:48:45 +01:00
|
|
|
if let Some(connection) = self.rooms[col][row].connection_right {
|
|
|
|
// println!("right");
|
2024-11-01 13:08:02 +01:00
|
|
|
connection.render(&mut self.rng, &mut structure);
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Level {
|
2023-12-07 10:12:44 +01:00
|
|
|
level: self.level,
|
2023-12-04 18:41:21 +01:00
|
|
|
structure,
|
2024-10-29 06:48:45 +01:00
|
|
|
discovered: [[false; LEVEL_HEIGHT]; LEVEL_WIDTH],
|
2024-10-30 08:56:45 +01:00
|
|
|
monsters,
|
|
|
|
artifacts,
|
2024-10-29 06:48:45 +01:00
|
|
|
start: start_pos,
|
|
|
|
end: end_pos,
|
2023-12-26 19:11:41 +01:00
|
|
|
rng: rand::thread_rng(),
|
2023-12-04 18:41:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-01 12:02:11 +01:00
|
|
|
#[test]
|
|
|
|
fn test_level_gen() {
|
|
|
|
for _ in 0..1000 {
|
|
|
|
LevelGenerator::generate(0, true, false).render();
|
|
|
|
}
|
|
|
|
}
|
2024-10-31 07:48:22 +01:00
|
|
|
|
2024-11-01 12:02:11 +01:00
|
|
|
#[test]
|
|
|
|
fn test_level_gen_respects_level() {
|
|
|
|
let level = LevelGenerator::generate(0, true, false).render();
|
|
|
|
assert_eq!(0, level.level);
|
|
|
|
let level = LevelGenerator::generate(1, true, false).render();
|
|
|
|
assert_eq!(1, level.level);
|
|
|
|
}
|
2024-10-31 07:48:22 +01:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
fn find_room_types(rooms: &Vec<Room>) -> (bool, bool, bool, bool) {
|
|
|
|
let mut start_found = false;
|
|
|
|
let mut end_found: bool = false;
|
|
|
|
let mut down_found: bool = false;
|
|
|
|
let mut up_found: bool = false;
|
|
|
|
for room in rooms {
|
|
|
|
if room.kind == RoomType::Start {
|
|
|
|
start_found = true;
|
|
|
|
}
|
|
|
|
if room.kind == RoomType::End {
|
|
|
|
end_found = true;
|
|
|
|
}
|
|
|
|
if room.kind == RoomType::StairDown {
|
|
|
|
down_found = true;
|
|
|
|
}
|
|
|
|
if room.kind == RoomType::StairUp {
|
|
|
|
up_found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(start_found, up_found, down_found, end_found)
|
|
|
|
}
|
2023-12-07 10:12:44 +01:00
|
|
|
#[test]
|
2024-10-31 07:48:22 +01:00
|
|
|
fn test_rooms_to_place_first_level() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let res = LevelGenerator::generate_rooms_to_place(&mut rng, 0, true, false);
|
|
|
|
assert!(
|
|
|
|
res.len() <= ROOMS_HORIZONTAL * ROOMS_VERTICAL,
|
|
|
|
"too many rooms created"
|
|
|
|
);
|
|
|
|
assert!(0 < res.len(), "too many rooms created");
|
|
|
|
|
|
|
|
let (start_found, up_found, down_found, end_found) = find_room_types(&res);
|
|
|
|
assert!(start_found);
|
|
|
|
assert!(!end_found);
|
|
|
|
assert!(down_found);
|
|
|
|
assert!(!up_found);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rooms_to_place_middle_level() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let res = LevelGenerator::generate_rooms_to_place(&mut rng, 1, false, false);
|
|
|
|
assert!(
|
|
|
|
res.len() <= ROOMS_HORIZONTAL * ROOMS_VERTICAL,
|
|
|
|
"too many rooms created"
|
|
|
|
);
|
|
|
|
assert!(0 < res.len(), "too many rooms created");
|
|
|
|
|
|
|
|
let (start_found, up_found, down_found, end_found) = find_room_types(&res);
|
|
|
|
assert!(!start_found);
|
|
|
|
assert!(!end_found);
|
|
|
|
assert!(down_found);
|
|
|
|
assert!(up_found);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_rooms_to_place_last_level() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let res = LevelGenerator::generate_rooms_to_place(&mut rng, 2, false, true);
|
|
|
|
assert!(
|
|
|
|
res.len() <= ROOMS_HORIZONTAL * ROOMS_VERTICAL,
|
|
|
|
"too many rooms created"
|
|
|
|
);
|
|
|
|
assert!(0 < res.len(), "too many rooms created");
|
|
|
|
|
|
|
|
let (start_found, up_found, down_found, end_found) = find_room_types(&res);
|
|
|
|
assert!(!start_found);
|
|
|
|
assert!(end_found);
|
|
|
|
assert!(!down_found);
|
|
|
|
assert!(up_found);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
fn check_valid_placement(rooms: &[[Room; ROOMS_VERTICAL]; ROOMS_HORIZONTAL]) -> bool {
|
|
|
|
for col in 0..ROOMS_HORIZONTAL {
|
|
|
|
for row in 0..ROOMS_VERTICAL {
|
|
|
|
if rooms[col][row].kind != RoomType::EmptyRoom {
|
|
|
|
let mut count = 0;
|
|
|
|
for test_col in 0..ROOMS_HORIZONTAL {
|
|
|
|
if rooms[test_col][row].kind != RoomType::EmptyRoom {
|
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for test_row in 0..ROOMS_VERTICAL {
|
|
|
|
if rooms[col][test_row].kind != RoomType::EmptyRoom {
|
|
|
|
count += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if count < 3 {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
fn count_rooms(rooms: &[[Room; ROOMS_VERTICAL]; ROOMS_HORIZONTAL]) -> usize {
|
|
|
|
let mut res = 0;
|
|
|
|
for col in 0..ROOMS_HORIZONTAL {
|
|
|
|
for row in 0..ROOMS_VERTICAL {
|
|
|
|
if rooms[col][row].kind != RoomType::EmptyRoom {
|
|
|
|
res += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
res
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_place_rooms() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
for count in 2..ROOMS_HORIZONTAL * ROOMS_VERTICAL {
|
|
|
|
let mut rooms: Vec<Room> = vec![Room::new(&mut rng), Room::new(&mut rng)];
|
|
|
|
rooms[0].kind = RoomType::Start;
|
|
|
|
rooms[1].kind = RoomType::End;
|
|
|
|
for t in 2..count {
|
|
|
|
rooms.push(Room::new(&mut rng));
|
|
|
|
rooms[t].kind = RoomType::BasicRoom;
|
|
|
|
}
|
|
|
|
let res = LevelGenerator::place_rooms(&mut rng, &mut rooms);
|
|
|
|
|
|
|
|
assert_eq!(count_rooms(&res), count, "counting {}", count);
|
|
|
|
assert!(check_valid_placement(&res));
|
2024-10-29 06:48:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2024-10-31 07:48:22 +01:00
|
|
|
fn test_create_mst() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
2024-11-06 09:22:22 +01:00
|
|
|
let res: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 07:48:22 +01:00
|
|
|
assert_eq!(res.node_count(), 0);
|
|
|
|
assert_eq!(res.edge_count(), 0);
|
|
|
|
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let res = LevelGenerator::create_mst(&rooms);
|
2024-10-31 07:48:22 +01:00
|
|
|
assert_eq!(res.node_count(), 1);
|
|
|
|
assert_eq!(res.edge_count(), 0);
|
|
|
|
|
|
|
|
rooms[1][3].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let res = LevelGenerator::create_mst(&rooms);
|
2024-10-31 07:48:22 +01:00
|
|
|
assert_eq!(res.node_count(), 2);
|
|
|
|
assert_eq!(res.edge_count(), 1);
|
|
|
|
|
|
|
|
rooms[3][1].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let res = LevelGenerator::create_mst(&rooms);
|
2024-10-31 07:48:22 +01:00
|
|
|
assert_eq!(res.node_count(), 3);
|
|
|
|
assert_eq!(res.edge_count(), 2);
|
|
|
|
|
|
|
|
rooms[3][3].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let res = LevelGenerator::create_mst(&rooms);
|
2024-10-31 07:48:22 +01:00
|
|
|
assert_eq!(res.node_count(), 4);
|
2024-11-06 14:29:30 +01:00
|
|
|
assert_eq!(res.edge_count(), 4);
|
2024-10-31 07:48:22 +01:00
|
|
|
|
|
|
|
rooms[3][5].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let res = LevelGenerator::create_mst(&rooms);
|
2024-10-31 07:48:22 +01:00
|
|
|
assert_eq!(res.node_count(), 5);
|
2024-11-06 14:29:30 +01:00
|
|
|
assert_eq!(res.edge_count(), 5);
|
2023-12-09 22:43:06 +01:00
|
|
|
}
|
2024-10-31 07:48:22 +01:00
|
|
|
|
2024-10-31 09:58:15 +01:00
|
|
|
#[test]
|
2024-10-31 15:20:39 +01:00
|
|
|
fn test_create_connections() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][0].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[1][0].offset_x = 0;
|
|
|
|
rooms[1][0].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][0].offset_y = 0;
|
|
|
|
rooms[1][0].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[3][0].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[3][0].offset_x = 0;
|
|
|
|
rooms[3][0].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[3][0].offset_y = 0;
|
|
|
|
rooms[3][0].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 15:20:39 +01:00
|
|
|
println!("{:?}", mst);
|
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][0].connection_right.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][0].connection_right.unwrap().start_pos,
|
|
|
|
(18, 3),
|
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][0].connection_right.unwrap().end_pos,
|
|
|
|
(27, 3),
|
|
|
|
"wrong end"
|
|
|
|
);
|
|
|
|
assert!(rooms[1][0].connection_down.is_none());
|
|
|
|
assert!(rooms[3][0].connection_down.is_none());
|
|
|
|
assert!(rooms[3][0].connection_right.is_none());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_connections_2() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][0].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[1][0].offset_x = 0;
|
|
|
|
rooms[1][0].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][0].offset_y = 0;
|
|
|
|
rooms[1][0].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[3][0].width = ROOM_WIDTH - 2;
|
|
|
|
rooms[3][0].offset_x = 1;
|
|
|
|
rooms[3][0].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[3][0].offset_y = 0;
|
|
|
|
rooms[3][0].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 15:20:39 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][0].connection_right.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][0].connection_right.unwrap().start_pos,
|
|
|
|
(18, 3),
|
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][0].connection_right.unwrap().end_pos,
|
|
|
|
(28, 3),
|
|
|
|
"wrong end"
|
|
|
|
);
|
|
|
|
assert!(rooms[1][0].connection_down.is_none());
|
|
|
|
assert!(rooms[3][0].connection_down.is_none());
|
|
|
|
assert!(rooms[3][0].connection_right.is_none());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_connections_d_1() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[0][1].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[0][1].offset_x = 0;
|
|
|
|
rooms[0][1].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[0][1].offset_y = 0;
|
|
|
|
rooms[0][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[0][3].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[0][3].offset_x = 0;
|
|
|
|
rooms[0][3].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[0][3].offset_y = 0;
|
|
|
|
rooms[0][3].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 15:20:39 +01:00
|
|
|
println!("{:?}", mst);
|
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[0][1].connection_down.is_some());
|
|
|
|
assert!(rooms[0][1].connection_right.is_none());
|
|
|
|
assert!(rooms[0][3].connection_down.is_none());
|
|
|
|
assert!(rooms[0][3].connection_right.is_none());
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
rooms[0][1].connection_down.unwrap().start_pos,
|
|
|
|
(4, 12),
|
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[0][1].connection_down.unwrap().end_pos,
|
|
|
|
(4, 18),
|
|
|
|
"wrong end"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_connections_d_2() {
|
2024-10-31 09:58:15 +01:00
|
|
|
// test full sized rooms for downwards connection
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][1].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[1][1].offset_x = 0;
|
|
|
|
rooms[1][1].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][1].offset_y = 0;
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[1][3].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[1][3].offset_x = 0;
|
|
|
|
rooms[1][3].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][3].offset_y = 0;
|
|
|
|
rooms[1][3].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][1].connection_down.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_down.unwrap().start_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(13, 12),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_down.unwrap().end_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(13, 18),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong end"
|
|
|
|
);
|
|
|
|
assert!(rooms[1][1].connection_right.is_none());
|
|
|
|
assert!(rooms[1][2].connection_down.is_none());
|
|
|
|
assert!(rooms[1][2].connection_right.is_none());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2024-10-31 15:20:39 +01:00
|
|
|
fn test_create_connections_d_3() {
|
2024-10-31 09:58:15 +01:00
|
|
|
// test reduced width rooms (with overlap) for downwards connection
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][1].width = 5;
|
|
|
|
rooms[1][1].offset_x = 0;
|
|
|
|
rooms[1][1].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][1].offset_y = 0;
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[1][3].width = 5;
|
|
|
|
rooms[1][3].offset_x = 4;
|
|
|
|
rooms[1][3].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][3].offset_y = 0;
|
|
|
|
rooms[1][3].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][1].connection_down.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_down.unwrap().start_pos,
|
|
|
|
(ROOM_WIDTH + 3, ROOM_HEIGHT * 2),
|
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_down.unwrap().end_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(ROOM_WIDTH + 7, ROOM_HEIGHT * 3),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong end"
|
|
|
|
);
|
|
|
|
assert!(rooms[1][1].connection_right.is_none());
|
2024-10-31 15:20:39 +01:00
|
|
|
assert!(rooms[1][3].connection_down.is_none());
|
|
|
|
assert!(rooms[1][3].connection_right.is_none());
|
2024-10-31 09:58:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2024-10-31 15:20:39 +01:00
|
|
|
fn test_create_connections_d_4() {
|
2024-10-31 09:58:15 +01:00
|
|
|
// test reduced width rooms (with NO overlap) for downwards connection
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][1].width = 3;
|
|
|
|
rooms[1][1].offset_x = 0;
|
|
|
|
rooms[1][1].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][1].offset_y = 0;
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[1][3].width = 3;
|
|
|
|
rooms[1][3].offset_x = 5;
|
|
|
|
rooms[1][3].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][3].offset_y = 0;
|
|
|
|
rooms[1][3].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][1].connection_down.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_down.unwrap().start_pos,
|
|
|
|
(ROOM_WIDTH + 2, ROOM_HEIGHT * 2),
|
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_down.unwrap().end_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(ROOM_WIDTH + 7, ROOM_HEIGHT * 3),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong end"
|
|
|
|
);
|
|
|
|
assert!(rooms[1][1].connection_right.is_none());
|
2024-10-31 15:20:39 +01:00
|
|
|
assert!(rooms[1][3].connection_down.is_none());
|
|
|
|
assert!(rooms[1][3].connection_right.is_none());
|
2024-10-31 09:58:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2024-10-31 15:20:39 +01:00
|
|
|
fn test_create_connections_d_5() {
|
2024-10-31 09:58:15 +01:00
|
|
|
// test reduced and moved width rooms (with NO overlap) for downwards connection
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][1].width = 3;
|
|
|
|
rooms[1][1].offset_x = 0;
|
|
|
|
rooms[1][1].height = 4;
|
|
|
|
rooms[1][1].offset_y = 0;
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[1][3].width = 3;
|
|
|
|
rooms[1][3].offset_x = 5;
|
|
|
|
rooms[1][3].height = 4;
|
|
|
|
rooms[1][3].offset_y = 1;
|
|
|
|
rooms[1][3].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][1].connection_down.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_down.unwrap().start_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(11, 11),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_down.unwrap().end_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(16, 19),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong end"
|
|
|
|
);
|
|
|
|
assert!(rooms[1][1].connection_right.is_none());
|
2024-10-31 15:20:39 +01:00
|
|
|
assert!(rooms[1][3].connection_down.is_none());
|
|
|
|
assert!(rooms[1][3].connection_right.is_none());
|
2024-10-31 09:58:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_connections_right_1() {
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][1].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[1][1].offset_x = 0;
|
|
|
|
rooms[1][1].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[1][1].offset_y = 0;
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[3][1].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[3][1].offset_x = 0;
|
|
|
|
rooms[3][1].height = ROOM_HEIGHT - 1;
|
|
|
|
rooms[3][1].offset_y = 0;
|
|
|
|
rooms[3][1].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][1].connection_down.is_none());
|
|
|
|
assert!(rooms[1][1].connection_right.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_right.unwrap().start_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(18, 9),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_right.unwrap().end_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(27, 9),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong end"
|
|
|
|
);
|
2024-10-31 15:20:39 +01:00
|
|
|
assert!(rooms[3][1].connection_down.is_none());
|
|
|
|
assert!(rooms[3][1].connection_right.is_none());
|
2024-10-31 09:58:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_connections_right_2() {
|
|
|
|
// test reduced width rooms (with overlap) for downwards connection
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][1].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[1][1].offset_x = 0;
|
|
|
|
rooms[1][1].height = 4;
|
|
|
|
rooms[1][1].offset_y = 0;
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[3][1].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[3][1].offset_x = 0;
|
|
|
|
rooms[3][1].height = 4;
|
|
|
|
rooms[3][1].offset_y = 2;
|
|
|
|
rooms[3][1].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][1].connection_down.is_none());
|
|
|
|
assert!(rooms[1][1].connection_right.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_right.unwrap().start_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(18, 8),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_right.unwrap().end_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(27, 10),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong end"
|
|
|
|
);
|
|
|
|
assert!(rooms[1][2].connection_down.is_none());
|
|
|
|
assert!(rooms[1][2].connection_right.is_none());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_connections_right_3() {
|
|
|
|
// test reduced width rooms (with NO overlap) for downwards connection
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][1].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[1][1].offset_x = 0;
|
|
|
|
rooms[1][1].height = 2;
|
|
|
|
rooms[1][1].offset_y = 0;
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[3][1].width = ROOM_WIDTH - 1;
|
|
|
|
rooms[3][1].offset_x = 0;
|
|
|
|
rooms[3][1].height = 2;
|
|
|
|
rooms[3][1].offset_y = 4;
|
|
|
|
rooms[3][1].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][1].connection_down.is_none());
|
|
|
|
assert!(rooms[1][1].connection_right.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_right.unwrap().start_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(18, 7),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_right.unwrap().end_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(27, 11),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong end"
|
|
|
|
);
|
2024-10-31 15:20:39 +01:00
|
|
|
assert!(rooms[1][3].connection_down.is_none());
|
|
|
|
assert!(rooms[1][3].connection_right.is_none());
|
2024-10-31 09:58:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_create_connections_right_4() {
|
|
|
|
// test reduced width rooms (with NO overlap) for downwards connection
|
|
|
|
let mut rng = rand::thread_rng();
|
|
|
|
let mut rooms = [[Room::new(&mut rng); ROOMS_VERTICAL]; ROOMS_HORIZONTAL];
|
|
|
|
rooms[1][1].width = 4;
|
|
|
|
rooms[1][1].offset_x = 3;
|
|
|
|
rooms[1][1].height = 2;
|
|
|
|
rooms[1][1].offset_y = 0;
|
|
|
|
rooms[1][1].kind = RoomType::BasicRoom;
|
|
|
|
|
|
|
|
rooms[3][1].width = 3;
|
|
|
|
rooms[3][1].offset_x = 3;
|
|
|
|
rooms[3][1].height = 2;
|
|
|
|
rooms[3][1].offset_y = 4;
|
|
|
|
rooms[3][1].kind = RoomType::BasicRoom;
|
2024-11-06 09:22:22 +01:00
|
|
|
let mst: GeneratorGraph = LevelGenerator::create_mst(&rooms);
|
2024-10-31 09:58:15 +01:00
|
|
|
LevelGenerator::create_connections(&mut rooms, &mst);
|
|
|
|
|
|
|
|
assert!(rooms[1][1].connection_down.is_none());
|
|
|
|
assert!(rooms[1][1].connection_right.is_some());
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_right.unwrap().start_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(17, 7),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong start"
|
|
|
|
);
|
|
|
|
assert_eq!(
|
|
|
|
rooms[1][1].connection_right.unwrap().end_pos,
|
2024-10-31 15:20:39 +01:00
|
|
|
(30, 11),
|
2024-10-31 09:58:15 +01:00
|
|
|
"wrong end"
|
|
|
|
);
|
2024-10-31 15:20:39 +01:00
|
|
|
assert!(rooms[1][3].connection_down.is_none());
|
|
|
|
assert!(rooms[1][3].connection_right.is_none());
|
2024-10-31 09:58:15 +01:00
|
|
|
}
|
|
|
|
|
2024-10-31 15:20:39 +01:00
|
|
|
// /*
|
|
|
|
// println!(" 0 1 2 3 4 5 6 7");
|
|
|
|
// for r in 0..ROOMS_VERTICAL {
|
|
|
|
// print!("{} ", r);
|
|
|
|
// for c in 0..ROOMS_HORIZONTAL {
|
|
|
|
// match res[c][r].kind {
|
|
|
|
// RoomType::Start => print!("S "),
|
|
|
|
// RoomType::End => print!("E "),
|
|
|
|
// RoomType::StairUp => print!("< "),
|
|
|
|
// RoomType::StairDown => print!("> "),
|
|
|
|
// RoomType::BasicRoom => print!("_ "),
|
|
|
|
// RoomType::ArtifactRoom => print!("A "),
|
|
|
|
// RoomType::MonsterRoom => print!("M "),
|
|
|
|
// RoomType::EmptyRoom => print!(" "),
|
|
|
|
// };
|
|
|
|
// }
|
|
|
|
// println!();
|
|
|
|
// }
|
|
|
|
// println!();
|
|
|
|
// */
|