diff options
Diffstat (limited to 'dungeon/src/map.rs')
| -rw-r--r-- | dungeon/src/map.rs | 97 |
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}"); } } |