Compare commits

..

18 Commits

Author SHA1 Message Date
Joachim Lusiardi 3249529f94 cleanup 2024-11-06 09:22:22 +01:00
Joachim Lusiardi 72f7be2ed8 more work on level generators 2024-11-05 12:02:45 +01:00
Joachim Lusiardi 5311f56ca0 extract minimal room size as constant 2024-11-03 10:32:04 +01:00
Joachim Lusiardi df80dfdd8a introduce custom type for the graph 2024-11-01 13:08:02 +01:00
Joachim Lusiardi 8b23c565b8 make connections more variable 2024-11-01 12:06:50 +01:00
Joachim Lusiardi 789a41cb3f make connections more variable 2024-11-01 12:02:11 +01:00
Joachim Lusiardi d42d8a12b4 make spiders more visible 2024-11-01 08:49:12 +01:00
Joachim Lusiardi 8ee142586b make monsters visible 2024-10-31 22:39:11 +01:00
Joachim Lusiardi 1878959e69 Clippy 2024-10-31 22:36:23 +01:00
Joachim Lusiardi 8bae1c7668 formatted 2024-10-31 22:34:35 +01:00
Joachim Lusiardi 3096386ad1 improve paths 2024-10-31 21:52:04 +01:00
Joachim Lusiardi f5d257e826 more work on generator and tests 2024-10-31 15:20:39 +01:00
Joachim Lusiardi a82a847ecd more tests 2024-10-31 09:58:15 +01:00
Joachim Lusiardi 50d98bfb4d work on level generation including tests 2024-10-31 07:48:22 +01:00
Joachim Lusiardi c429784775 run tests on all branches 2024-10-30 13:06:26 +01:00
Joachim Lusiardi e96660cea0 redo some colors 2024-10-30 13:01:28 +01:00
Joachim Lusiardi c6492c28c2 work on level generator 2024-10-30 08:56:45 +01:00
Joachim Lusiardi 7f288dbcd1 first version of the level new generator
monsters and artefact are missing
roomsize is fixed
2024-10-29 06:48:45 +01:00
12 changed files with 1309 additions and 365 deletions

View File

@ -0,0 +1,16 @@
name: publish package
on:
push:
branches-ignore:
- main
jobs:
Explore-Gitea-Actions:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: run tests
run: |
cd ${{ gitea.workspace }}
cargo test

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target /target
*.profraw

10
coverage.md Normal file
View File

@ -0,0 +1,10 @@
```
cargo install grcov
rustup component add llvm-tools-preview
```
```
RUSTFLAGS="-Cinstrument-coverage" cargo clean
RUSTFLAGS="-Cinstrument-coverage" cargo test
grcov . --binary-path ./target/debug/deps/ -s . -t html --branch --ignore-not-existing --ignore '../*' --ignore "/*" -o target/coverage/html
```

View File

@ -3,7 +3,6 @@ extern crate proc_macro;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::quote; use quote::quote;
#[proc_macro_derive(CreateMonsters)] #[proc_macro_derive(CreateMonsters)]
pub fn create_monsters(input: TokenStream) -> TokenStream { pub fn create_monsters(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::File); let input = syn::parse_macro_input!(input as syn::File);

View File

@ -39,7 +39,7 @@ impl Chest {
impl Artifact for Chest { impl Artifact for Chest {
fn get_representation(&self) -> (&str, Color) { fn get_representation(&self) -> (&str, Color) {
("C", Color::Blue) ("C", Color::Cyan)
} }
fn get_immutable_position(&self) -> &Position { fn get_immutable_position(&self) -> &Position {

View File

@ -1,19 +1,25 @@
use std::{collections::HashMap, ops::RangeInclusive}; use std::{collections::HashMap, ops::RangeInclusive};
use crate::monster::MonsterTypes; use crate::{monster::MonsterTypes, room::RoomType};
/// the number of rooms in vertical direction /// the number of rooms in vertical direction
pub const ROOMS_VERTICAL: usize = 7; pub const ROOMS_HORIZONTAL: usize = 8;
/// the number of rooms in horizontal direction /// the number of rooms in horizontal direction
pub const ROOMS_HORIZONTAL: usize = 7; pub const ROOMS_VERTICAL: usize = 7;
/// the width of a room in the grid of rooms (number of characters) /// the width of a room in the grid of rooms (number of characters)
pub const ROOM_WIDTH: usize = 9; pub const ROOM_WIDTH: usize = 9;
/// the height of a room in the grid of rooms (number of characters) /// the height of a room in the grid of rooms (number of characters)
pub const ROOM_HEIGHT: usize = 6; pub const ROOM_HEIGHT: usize = 6;
// the minmal width of a room
pub const ROOM_MIN_WIDTH: usize = 4;
// the minmal height of a room
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 = 3; 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;
@ -24,33 +30,106 @@ pub const MIN_WIDTH: u16 = 120;
pub const MIN_HEIGHT: u16 = LEVEL_HEIGHT as u16; pub const MIN_HEIGHT: u16 = LEVEL_HEIGHT as u16;
/// the calculated width of a level /// the calculated width of a level
pub const LEVEL_WIDTH: usize = 1 + ROOMS_VERTICAL * ROOM_WIDTH; pub const LEVEL_WIDTH: usize = 1 + ROOMS_HORIZONTAL * ROOM_WIDTH;
/// the calculated height of a level /// the calculated height of a level
pub const LEVEL_HEIGHT: usize = 1 + ROOMS_HORIZONTAL * ROOM_HEIGHT; pub const LEVEL_HEIGHT: usize = 1 + ROOMS_VERTICAL * ROOM_HEIGHT;
pub fn get_monsters_per_level() -> Vec<HashMap<MonsterTypes, std::ops::RangeInclusive<u8>>> { pub fn get_monsters_per_level() -> Vec<HashMap<MonsterTypes, std::ops::RangeInclusive<u8>>> {
let tmp =[ let tmp = [
// level 1 // level 1
vec![(MonsterTypes::Rat, 50), (MonsterTypes::Spider, 50)], vec![(MonsterTypes::Rat, 50), (MonsterTypes::Spider, 50)],
// level 2 // level 2
vec![(MonsterTypes::Rat, 50), (MonsterTypes::Snake, 50)], vec![(MonsterTypes::Rat, 50), (MonsterTypes::Snake, 50)],
// level 3 // level 3
vec![(MonsterTypes::Orc, 34), (MonsterTypes::Skeleton, 33), (MonsterTypes::Snake, 33)], vec![
(MonsterTypes::Orc, 34),
(MonsterTypes::Skeleton, 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!("Only {} monster sets defined for {} levels!", tmp.len(), LEVELS); panic!(
"Only {} monster sets defined for {} levels!",
tmp.len(),
LEVELS
);
} }
let mut result: Vec<HashMap<MonsterTypes, std::ops::RangeInclusive<u8>>> = vec![]; let mut result: Vec<HashMap<MonsterTypes, std::ops::RangeInclusive<u8>>> = vec![];
for (idx, level) in tmp.iter().enumerate() { for (idx, level) in tmp.iter().enumerate() {
let mut sum = 0; let mut sum = 0;
let mut map: HashMap<MonsterTypes, RangeInclusive<u8>> = HashMap::new(); let mut map: HashMap<MonsterTypes, RangeInclusive<u8>> = HashMap::new();
for monster in level { for monster in level {
map.insert(monster.0, RangeInclusive::new(sum+1, sum+monster.1)); map.insert(monster.0, RangeInclusive::new(sum + 1, sum + monster.1));
sum += monster.1; sum += monster.1;
} }
if sum != 100 { if sum != 100 {
panic!("all percentages must add to 100 (was {}) per level, error in level {}!", sum, idx+1); panic!(
"all percentages must add to 100 (was {}) per level, error in level {}!",
sum,
idx + 1
);
}
result.push(map);
}
result
}
pub fn get_room_type_per_level() -> Vec<HashMap<RoomType, std::ops::RangeInclusive<u8>>> {
let tmp = [
// level 1
vec![
(RoomType::EmptyRoom, 50),
(RoomType::ArtifactRoom, 10),
(RoomType::MonsterRoom, 20),
(RoomType::BasicRoom, 20),
],
// level 2
vec![
(RoomType::EmptyRoom, 50),
(RoomType::BasicRoom, 25),
(RoomType::MonsterRoom, 12),
(RoomType::ArtifactRoom, 13),
],
// level 3
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 {
panic!(
"Only {} room sets defined for {} levels!",
tmp.len(),
LEVELS
);
}
let mut result: Vec<HashMap<RoomType, std::ops::RangeInclusive<u8>>> = vec![];
for (idx, level) in tmp.iter().enumerate() {
let mut sum = 0;
let mut map: HashMap<RoomType, RangeInclusive<u8>> = HashMap::new();
for room in level {
map.insert(room.0, RangeInclusive::new(sum + 1, sum + room.1));
sum += room.1;
}
if sum != 100 {
panic!(
"all percentages must add to 100 (was {}) per level, error in level {}!",
sum,
idx + 1
);
} }
result.push(map); result.push(map);
} }

View File

@ -57,6 +57,7 @@ impl Level {
return (None, None, None); return (None, None, None);
} }
if !self.discovered[x][y] { if !self.discovered[x][y] {
// #[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);

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,14 @@
use ratatui::buffer::Buffer; use ratatui::buffer::Buffer;
use ratatui::layout::Rect; use ratatui::layout::Rect;
use ratatui::style::Color; use ratatui::style::{Color, Modifier, Style};
use ratatui::widgets::{StatefulWidget, Widget}; use ratatui::widgets::{StatefulWidget, Widget};
use crate::game::Game; use crate::game::Game;
use crate::level::StructureElement; use crate::level::StructureElement;
use crate::position::HasPosition; use crate::position::HasPosition;
const FG_BROWN: Color = Color::Rgb(186, 74, 0); const FG_BROWN: Color = Color::Rgb(140, 34, 0);
const BACKGROUND: Color = Color::Black;
pub struct LevelWidget {} pub struct LevelWidget {}
@ -15,6 +16,13 @@ impl LevelWidget {
fn set_cell(&self, buf: &mut Buffer, x: u16, y: u16, symbol: &str, fg: Color, bg: Color) { fn set_cell(&self, buf: &mut Buffer, x: u16, y: u16, symbol: &str, fg: Color, bg: Color) {
buf[(x, y)].set_symbol(symbol).set_bg(bg).set_fg(fg); buf[(x, y)].set_symbol(symbol).set_bg(bg).set_fg(fg);
} }
fn set_bold_cell(&self, buf: &mut Buffer, x: u16, y: u16, symbol: &str, fg: Color, bg: Color) {
buf[(x, y)]
.set_symbol(symbol)
.set_bg(bg)
.set_fg(fg)
.set_style(Style::new().add_modifier(Modifier::BOLD));
}
} }
impl StatefulWidget for LevelWidget { impl StatefulWidget for LevelWidget {
@ -39,36 +47,36 @@ impl StatefulWidget for LevelWidget {
(Some(structure_element), None, None) => { (Some(structure_element), None, None) => {
match structure_element { match structure_element {
StructureElement::Start => { StructureElement::Start => {
self.set_cell(buf, x, y, "α", Color::Black, Color::Gray); self.set_cell(buf, x, y, "α", Color::White, BACKGROUND);
} }
StructureElement::End => { StructureElement::End => {
self.set_cell(buf, x, y, "Ω", Color::Black, Color::Gray); self.set_cell(buf, x, y, "Ω", Color::White, BACKGROUND);
} }
StructureElement::Wall => { StructureElement::Wall => {
// TODO add fancy walls with https://en.wikipedia.org/wiki/Box-drawing_characters // TODO add fancy walls with https://en.wikipedia.org/wiki/Box-drawing_characters
self.set_cell(buf, x, y, "#", FG_BROWN, Color::Gray); self.set_cell(buf, x, y, "#", FG_BROWN, FG_BROWN);
} }
StructureElement::Floor => { StructureElement::Floor => {
self.set_cell(buf, x, y, " ", FG_BROWN, Color::Gray); self.set_cell(buf, x, y, " ", FG_BROWN, BACKGROUND);
} }
StructureElement::StairDown => { StructureElement::StairDown => {
self.set_cell(buf, x, y, ">", Color::Black, Color::Gray); self.set_cell(buf, x, y, ">", Color::White, BACKGROUND);
} }
StructureElement::StairUp => { StructureElement::StairUp => {
self.set_cell(buf, x, y, "<", Color::Black, Color::Gray); self.set_cell(buf, x, y, "<", Color::White, BACKGROUND);
} }
StructureElement::Unknown => { StructureElement::Unknown => {
self.set_cell(buf, x, y, "", Color::DarkGray, Color::Gray); self.set_cell(buf, x, y, "", Color::Gray, BACKGROUND);
} }
} }
} }
(_, Some(m), _) => { (_, Some(m), _) => {
let (s, c) = m.get_representation(); let (s, c) = m.get_representation();
self.set_cell(buf, x, y, s, c, Color::Gray); self.set_cell(buf, x, y, s, c, BACKGROUND);
} }
(_, _, Some(t)) => { (_, _, Some(t)) => {
let (s, c) = t.get_representation(); let (s, c) = t.get_representation();
self.set_cell(buf, x, y, s, c, Color::Gray); self.set_bold_cell(buf, x, y, s, c, BACKGROUND);
} }
(None, None, None) => {} (None, None, None) => {}
}; };
@ -80,7 +88,7 @@ impl StatefulWidget for LevelWidget {
let player_pos = player.get_immutable_position(); let player_pos = player.get_immutable_position();
let player_x = al + player_pos.get_x() as u16; let player_x = al + player_pos.get_x() as u16;
let player_y = at + player_pos.get_y() as u16; let player_y = at + player_pos.get_y() as u16;
self.set_cell(buf, player_x, player_y, "8", Color::Red, Color::Gray); self.set_cell(buf, player_x, player_y, "8", Color::LightRed, BACKGROUND);
} }
} }
} }

View File

@ -36,6 +36,7 @@ mod level_widget;
mod monster; mod monster;
mod player; mod player;
mod position; mod position;
mod room;
// //
fn main() -> Result<()> { fn main() -> Result<()> {

View File

@ -45,7 +45,7 @@ create_monster!(
name:"rat".to_string(), name:"rat".to_string(),
life: 2, life: 2,
symbol: String::from("r"), symbol: String::from("r"),
color: Color::Black, color: Color::White,
experience_gain: 5, experience_gain: 5,
ticks_between_steps: 5, ticks_between_steps: 5,
damage_range: 1..=2, damage_range: 1..=2,
@ -56,7 +56,7 @@ create_monster!(
name:"spider".to_string(), name:"spider".to_string(),
life: 3, life: 3,
symbol: String::from("s"), symbol: String::from("s"),
color: Color::Blue, color: Color::Yellow,
experience_gain: 7, experience_gain: 7,
ticks_between_steps: 7, ticks_between_steps: 7,
damage_range: 2..=3, damage_range: 2..=3,
@ -67,7 +67,7 @@ create_monster!(
name: "orc".to_string(), name: "orc".to_string(),
life: 4, life: 4,
symbol: String::from("O"), symbol: String::from("O"),
color: Color::DarkGray, color: Color::Gray,
experience_gain: 10, experience_gain: 10,
ticks_between_steps: 10, ticks_between_steps: 10,
damage_range: 2..=3, damage_range: 2..=3,
@ -78,7 +78,7 @@ create_monster!(
name: "snake".to_string(), name: "snake".to_string(),
life: 3, life: 3,
symbol: String::from("s"), symbol: String::from("s"),
color: Color::Black, color: Color::White,
experience_gain: 10, experience_gain: 10,
ticks_between_steps: 20, ticks_between_steps: 20,
damage_range: 1..=4, damage_range: 1..=4,
@ -89,7 +89,7 @@ create_monster!(
name: "skeleton".to_string(), name: "skeleton".to_string(),
life: 3, life: 3,
symbol: String::from("S"), symbol: String::from("S"),
color: Color::DarkGray, color: Color::Gray,
experience_gain: 20, experience_gain: 20,
ticks_between_steps: 10, ticks_between_steps: 10,
damage_range: 1..=5, damage_range: 1..=5,

280
src/room.rs Normal file
View File

@ -0,0 +1,280 @@
use std::{
cmp::{max, min},
ops::RangeInclusive,
};
use crate::{
constants::{
LEVEL_HEIGHT, LEVEL_WIDTH, ROOM_HEIGHT, ROOM_MIN_HEIGHT, ROOM_MIN_WIDTH, ROOM_WIDTH,
},
level::StructureElement,
};
use rand::rngs::ThreadRng;
use rand::Rng;
#[derive(PartialEq, Copy, Clone, Eq, Hash, Debug)]
pub enum RoomType {
Start,
End,
StairUp,
StairDown,
BasicRoom,
ArtifactRoom,
MonsterRoom,
EmptyRoom,
}
#[derive(Copy, Clone, Debug)]
pub struct Connection {
pub start_pos: (usize, usize),
pub end_pos: (usize, usize),
}
impl Connection {
pub fn render(
&self,
rng: &mut ThreadRng,
tgt: &mut [[StructureElement; LEVEL_HEIGHT]; LEVEL_WIDTH],
) {
fn calc_range(a: usize, b: usize) -> RangeInclusive<usize> {
if a > b {
b..=a
} else {
a..=b
}
}
// the tuples are (col, row)
let abs_d_col =
max(self.start_pos.0, self.end_pos.0) - min(self.start_pos.0, self.end_pos.0);
let abs_d_row =
max(self.start_pos.1, self.end_pos.1) - min(self.start_pos.1, self.end_pos.1);
if abs_d_col == 0 {
for row in calc_range(self.end_pos.1, self.start_pos.1) {
tgt[self.end_pos.0][row] = StructureElement::Floor;
}
} else if abs_d_row == 0 {
for col in calc_range(self.end_pos.0, self.start_pos.0) {
tgt[col][self.end_pos.1] = StructureElement::Floor;
}
} else {
let d_row = self.end_pos.1 as i32 - self.start_pos.1 as i32;
if d_row > 0 {
// more up/down
let d_row = self.end_pos.1 - self.start_pos.1;
let vert_offset = if d_row > 3 {
rng.gen_range(1..=d_row - 1)
} else {
d_row / 2
};
for r in self.start_pos.1..=(self.start_pos.1 + vert_offset) {
tgt[self.start_pos.0][r] = StructureElement::Floor;
}
for c in calc_range(self.end_pos.0, self.start_pos.0) {
tgt[c][self.start_pos.1 + vert_offset] = StructureElement::Floor;
}
for r in (self.start_pos.1 + vert_offset)..=self.end_pos.1 {
tgt[self.end_pos.0][r] = StructureElement::Floor;
}
} else {
// more left/right
let d_col = self.end_pos.0 - self.start_pos.0;
let horizont_offset = if d_col > 3 {
rng.gen_range(1..=d_col - 1)
} else {
d_col / 2
};
for tgt_col in tgt
.iter_mut()
.skip(self.start_pos.0)
.take(horizont_offset + 1)
{
tgt_col[self.start_pos.1] = StructureElement::Floor;
}
for r in calc_range(self.end_pos.1, self.start_pos.1) {
tgt[self.start_pos.0 + horizont_offset][r] = StructureElement::Floor;
}
for tgt_col in tgt
.iter_mut()
.take(self.end_pos.0 + 1)
.skip(self.start_pos.0 + horizont_offset)
{
tgt_col[self.end_pos.1] = StructureElement::Floor;
}
}
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct Room {
pub kind: RoomType,
pub offset_x: usize,
pub offset_y: usize,
pub width: usize,
pub height: usize,
pub special: (usize, usize),
pub connection_down: Option<Connection>,
pub connection_right: Option<Connection>,
}
impl Room {
pub fn new(rng: &mut ThreadRng) -> Self {
let width = rng.gen_range(ROOM_MIN_WIDTH..ROOM_WIDTH);
let height = rng.gen_range(ROOM_MIN_HEIGHT..ROOM_HEIGHT);
let offset_x = rng.gen_range(0..(ROOM_WIDTH - width));
let offset_y = rng.gen_range(0..(ROOM_HEIGHT - height));
let sx = offset_x + rng.gen_range(1..width - 1);
let sy = offset_y + rng.gen_range(1..height - 1);
Self {
kind: RoomType::EmptyRoom,
offset_x,
offset_y,
width,
height,
special: (sx, sy),
connection_down: None,
connection_right: None,
}
}
// pub fn get_x_range(&self) -> Range<usize> {
// self.offset_x..self.offset_x + self.width
// }
// pub fn get_y_range(&self) -> Range<usize> {
// self.offset_y..self.offset_y + self.height
// }
pub fn render(
&self,
tgt: &mut [[StructureElement; LEVEL_HEIGHT]; LEVEL_WIDTH],
col: usize,
row: usize,
) -> (usize, usize) {
let top = 1 + row * ROOM_HEIGHT;
let left = 1 + col * ROOM_WIDTH;
for col in tgt.iter_mut().skip(left).take(ROOM_WIDTH) {
//left..left + ROOM_WIDTH {
for row_element in col.iter_mut().skip(top).take(ROOM_HEIGHT) {
// top..top + ROOM_HEIGHT {
*row_element = StructureElement::Wall;
}
}
if self.kind == RoomType::EmptyRoom {
return (0, 0);
}
// render floor elements
for x in 0..self.width {
for y in 0..self.height {
tgt[left + self.offset_x + x][top + self.offset_y + y] = StructureElement::Floor;
}
}
match self.kind {
RoomType::Start => {
tgt[left + self.special.0][top + self.special.1] = StructureElement::Start;
}
RoomType::End => {
tgt[left + self.special.0][top + self.special.1] = StructureElement::End;
}
RoomType::StairUp => {
tgt[left + self.special.0][top + self.special.1] = StructureElement::StairUp;
}
RoomType::StairDown => {
tgt[left + self.special.0][top + self.special.1] = StructureElement::StairDown;
}
_ => {}
};
(left + self.special.0, top + self.special.1)
}
}
#[test]
fn test_room_creation() {
let mut rng = rand::thread_rng();
let room = Room::new(&mut rng);
assert_eq!(room.kind, RoomType::EmptyRoom);
for _ in 0..1000 {
let room = Room::new(&mut rng);
assert!((3..=ROOM_WIDTH).contains(&room.width));
}
}
#[cfg(test)]
fn all_wall(
tgt: &mut [[StructureElement; LEVEL_HEIGHT]; LEVEL_WIDTH],
col: usize,
row: usize,
) -> bool {
let top = 1 + row * ROOM_HEIGHT;
let left = 1 + col * ROOM_WIDTH;
for x in left..left + ROOM_WIDTH {
for y in top..top + ROOM_HEIGHT {
if tgt[x][y] != StructureElement::Wall {
return false;
}
}
}
true
}
#[cfg(test)]
fn has_structure_element(
tgt: &mut [[StructureElement; LEVEL_HEIGHT]; LEVEL_WIDTH],
col: usize,
row: usize,
element: StructureElement,
) -> bool {
let top = 1 + row * ROOM_HEIGHT;
let left = 1 + col * ROOM_WIDTH;
for x in left..left + ROOM_WIDTH {
for y in top..top + ROOM_HEIGHT {
if tgt[x][y] == element {
return true;
}
}
}
false
}
#[test]
fn test_room_render_empty() {
let mut rng = rand::thread_rng();
let room = Room::new(&mut rng);
assert_eq!(room.kind, RoomType::EmptyRoom);
let mut structure = [[StructureElement::Floor; LEVEL_HEIGHT]; LEVEL_WIDTH];
room.render(&mut structure, 0, 0);
assert!(all_wall(&mut structure, 0, 0));
}
#[test]
fn test_room_render_basic() {
let mut rng = rand::thread_rng();
let mut room = Room::new(&mut rng);
room.kind = RoomType::BasicRoom;
let mut structure = [[StructureElement::Floor; LEVEL_HEIGHT]; LEVEL_WIDTH];
room.render(&mut structure, 1, 3);
assert!(!all_wall(&mut structure, 1, 3));
}
#[test]
fn test_room_render_start() {
let mut rng = rand::thread_rng();
let mut room = Room::new(&mut rng);
room.kind = RoomType::Start;
let mut structure = [[StructureElement::Floor; LEVEL_HEIGHT]; LEVEL_WIDTH];
room.render(&mut structure, 1, 3);
assert!(!all_wall(&mut structure, 1, 3));
assert!(has_structure_element(
&mut structure,
1,
3,
StructureElement::Start
));
}