summaryrefslogtreecommitdiff
path: root/dungeon/src/map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'dungeon/src/map.rs')
-rw-r--r--dungeon/src/map.rs97
1 files changed, 52 insertions, 45 deletions
diff --git a/dungeon/src/map.rs b/dungeon/src/map.rs
index c204cac..8d9a391 100644
--- a/dungeon/src/map.rs
+++ b/dungeon/src/map.rs
@@ -7,6 +7,7 @@ use strum_macros::EnumIter;
use std::{
cell::RefCell,
+ fmt::{Display, Write},
hash::{DefaultHasher, Hash, Hasher},
};
@@ -40,12 +41,14 @@ impl Tile {
}
/// Returns if the tile is a wall
- pub fn is_wall(self) -> bool {
- self == Self::Wall
+ #[must_use]
+ pub const fn is_wall(self) -> bool {
+ matches!(self, Self::Wall)
}
/// Returns if the tile is walkable
- pub fn is_walkable(self) -> bool {
+ #[must_use]
+ pub const fn is_walkable(self) -> bool {
matches!(self, Self::Air)
}
}
@@ -54,6 +57,16 @@ impl Default for Tile {
Self::Air
}
}
+impl Display for Tile {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let char = match self {
+ Self::Wall => '#',
+ Self::Air => '.',
+ Self::Stairs => '>',
+ };
+ f.write_char(char)
+ }
+}
/// The `Floor` type represents the current playing
/// grid of the dungeon. It contains the tiles of the
@@ -194,55 +207,22 @@ impl Floor {
*hash
}
- /// Display the floor as a string for debugging
- ///
- /// # Examples
- /// ```no_run
- /// use dungeon::Floor;
- /// let floor = Floor::generate();
- /// println!("{}", floor.display());
- /// ```
- #[must_use]
- pub fn display(&self) -> String {
- let mut output = String::new();
- for pos in Pos::values() {
- // If it's the player start, show 'P'
- if self.player_start == pos {
- output.push('P');
- continue;
- }
- // Otherwise, show the tile character
- let tile = self.get(pos);
- let char = match tile {
- Tile::Wall => '#',
- Tile::Air => '.',
- Tile::Stairs => '>',
- };
- output.push(char);
- // Newline at the end of each row
- if pos.xy().0 == MAP_SIZE - 1 {
- output.push('\n');
- }
- }
- output
- }
-
/// Returns a random open (no wall) position
pub fn random_pos(&mut self) -> Pos {
loop {
- let x = self.rng.random_range(0..MAP_SIZE);
- let y = self.rng.random_range(0..MAP_SIZE);
- let Some(pos) = Pos::new(x, y) else {
- continue;
- };
- if self.get(pos) != Tile::Air {
+ let pos = self.rand().random();
+ if !self.get(pos).is_walkable() {
continue;
}
break pos;
}
}
-}
+ /// Returns the random number gen for the `Floor`
+ pub fn rand(&mut self) -> &mut impl Rng {
+ &mut self.rng
+ }
+}
impl Default for Floor {
/// Returns a floor with a single set of walls on the map border
fn default() -> Self {
@@ -259,6 +239,34 @@ impl Default for Floor {
Self::new(tiles, player_start, seed)
}
}
+impl Display for Floor {
+ /// Display the floor as a string for debugging
+ ///
+ /// # Examples
+ /// ```no_run
+ /// use dungeon::Floor;
+ /// let floor = Floor::generate();
+ /// println!("{floor}");
+ /// ```
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ for pos in Pos::values() {
+ // If it's the player start, show 'P'
+ if self.player_start == pos {
+ f.write_char('P')?;
+ continue;
+ }
+ // Otherwise, show the tile character
+ let tile = self.get(pos);
+ write!(f, "{tile}")?;
+ // Newline at the end of each row
+ if pos.xy().0 == MAP_SIZE - 1 {
+ writeln!(f)?;
+ }
+ }
+
+ Ok(())
+ }
+}
/// Tests
#[cfg(test)]
@@ -269,8 +277,7 @@ mod tests {
#[test]
fn test_floor_display() {
let floor = Floor::generate();
- let display = floor.display();
// Print the display for visual inspection
- println!("{display}");
+ println!("{floor}");
}
}