summaryrefslogtreecommitdiff
path: root/dungeon/src/map.rs
diff options
context:
space:
mode:
authorAudrey L Fuller <alf9310@g.rit.edu>2025-11-10 05:43:24 +0000
committerAudrey L Fuller <alf9310@g.rit.edu>2025-11-10 05:43:24 +0000
commitb897e95c3ae9f423280e65c456ad4371f15ebebe (patch)
tree9cb3c4305b1a714552c37ef6cdd9d3a585840422 /dungeon/src/map.rs
parentAdded many auto-gen test cases for maze connectivity (diff)
parentoops (diff)
downloadDungeonCrawl-b897e95c3ae9f423280e65c456ad4371f15ebebe.tar.gz
DungeonCrawl-b897e95c3ae9f423280e65c456ad4371f15ebebe.tar.bz2
DungeonCrawl-b897e95c3ae9f423280e65c456ad4371f15ebebe.zip
Merge branch 'main' into 'dungeon_generation'
# Conflicts: # dungeon/src/map.rs
Diffstat (limited to 'dungeon/src/map.rs')
-rw-r--r--dungeon/src/map.rs70
1 files changed, 57 insertions, 13 deletions
diff --git a/dungeon/src/map.rs b/dungeon/src/map.rs
index 5004dd7..7d79f7f 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},
};
@@ -42,8 +43,15 @@ 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
+ #[must_use]
+ pub const fn is_walkable(self) -> bool {
+ matches!(self, Self::Air)
}
// Index by u16
@@ -53,6 +61,16 @@ impl Default for Tile {
Self::Wall
}
}
+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
@@ -169,8 +187,7 @@ impl Floor {
/// Returns the neighbors of a tile inside the floor, checking
/// that the neighbor positions are the same tile type as in `pos`.
pub fn neighbors(&self, pos: &Pos) -> impl Iterator<Item = Pos> {
- let tile = self.get(*pos);
- pos.neighbors().filter(move |p| self.get(*p) == tile)
+ pos.neighbors().filter(|p| self.get(*p).is_walkable())
}
/// Computes the hash of the tile map
@@ -231,19 +248,19 @@ impl Floor {
/// 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::Wall {
+ 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 {
@@ -260,6 +277,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)]
@@ -270,8 +315,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}");
}
}