summaryrefslogtreecommitdiff
path: root/dungeon
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-10-23 13:09:09 -0400
committerFreya Murphy <freya@freyacat.org>2025-10-23 13:10:55 -0400
commite97c52520b42a1e45e7e198240d1550ccd304ac8 (patch)
tree4a3c5e991b6e22c443a011bbe17661c40dc8f3ab /dungeon
parentdungeon: add FPos for decimial positions (diff)
downloadDungeonCrawl-e97c52520b42a1e45e7e198240d1550ccd304ac8.tar.gz
DungeonCrawl-e97c52520b42a1e45e7e198240d1550ccd304ac8.tar.bz2
DungeonCrawl-e97c52520b42a1e45e7e198240d1550ccd304ac8.zip
dungeon: add hash to to check if it has been changed
Diffstat (limited to 'dungeon')
-rw-r--r--dungeon/src/map.rs55
1 files changed, 47 insertions, 8 deletions
diff --git a/dungeon/src/map.rs b/dungeon/src/map.rs
index d9a4323..a2cdd9a 100644
--- a/dungeon/src/map.rs
+++ b/dungeon/src/map.rs
@@ -2,6 +2,11 @@
//! including the current `Floor`, and map `Tile`.
use crate::wfc::Wfc;
+use std::{
+ cell::RefCell,
+ hash::{DefaultHasher, Hash, Hasher},
+};
+
use crate::{const_pos, pos::Pos};
/// `MAP_SIZE` is the size of the size of the dungeon grid.
@@ -37,7 +42,7 @@ impl Tile {
/// The `Floor` type represents the current playing
/// grid of the dungeon. It contains the tiles of the
/// grid, and the starting position of the player.
-#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Floor {
/// The dungeon grid
tiles: Box<[Tile; TILE_COUNT]>,
@@ -45,8 +50,23 @@ pub struct Floor {
player_start: Pos,
/// The seed used when generating the dungeon grid
seed: u64,
+ /// The computed hash of the tile map
+ hash: RefCell<u64>,
+ /// If the tiles are dirty (hash needs to be recomputed)
+ dirty: RefCell<bool>,
}
impl Floor {
+ /// Internal constructor for `Floor`
+ fn new(tiles: Box<[Tile; TILE_COUNT]>, player_start: Pos, seed: u64) -> Self {
+ Self {
+ tiles,
+ player_start,
+ seed,
+ hash: RefCell::new(0),
+ dirty: RefCell::new(true),
+ }
+ }
+
/// Generates a dungeon `Floor` using wave function collapse.
///
/// # Examples
@@ -107,7 +127,8 @@ impl Floor {
/// Returns a multable reference to a `Tile` on the dungeon grid at `Pos`.
#[must_use]
- pub const fn get_mut(&mut self, pos: Pos) -> &mut Tile {
+ pub fn get_mut(&mut self, pos: Pos) -> &mut Tile {
+ *self.dirty.get_mut() = true;
let idx = pos.idx();
&mut self.tiles[idx]
}
@@ -122,9 +143,31 @@ impl Floor {
/// Returns a mutable reference to all tiles in the `Floor`.
/// The size of this lise will always be `TILE_COUNT` long.
#[must_use]
- pub const fn tiles_mut(&mut self) -> &mut [Tile] {
+ pub fn tiles_mut(&mut self) -> &mut [Tile] {
+ *self.dirty.get_mut() = true;
&mut *self.tiles
}
+
+ /// Computes the hash of the tile map
+ #[must_use]
+ pub fn hash(&self) -> u64 {
+ // initial (immutable) dirty check
+ let dirty = self.dirty.borrow();
+ if *dirty {
+ return *self.hash.borrow();
+ }
+ drop(dirty);
+
+ // recompute hash
+ let mut dirty = self.dirty.borrow_mut();
+ let mut hash = self.hash.borrow_mut();
+ let mut s = DefaultHasher::new();
+ self.tiles.hash(&mut s);
+ *hash = s.finish();
+
+ *dirty = false;
+ *hash
+ }
}
impl Default for Floor {
/// Returns a floor with a single set of walls on the map border
@@ -139,10 +182,6 @@ impl Default for Floor {
}
}
- Self {
- tiles,
- player_start,
- seed,
- }
+ Self::new(tiles, player_start, seed)
}
}