diff options
| author | Freya Murphy <freya@freyacat.org> | 2025-10-23 13:09:09 -0400 |
|---|---|---|
| committer | Freya Murphy <freya@freyacat.org> | 2025-10-23 13:10:55 -0400 |
| commit | e97c52520b42a1e45e7e198240d1550ccd304ac8 (patch) | |
| tree | 4a3c5e991b6e22c443a011bbe17661c40dc8f3ab /dungeon | |
| parent | dungeon: add FPos for decimial positions (diff) | |
| download | DungeonCrawl-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.rs | 55 |
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) } } |