summaryrefslogtreecommitdiff
path: root/dungeon/src/map.rs
blob: cb602e8dc3d6380d37e6826e94d7aa8f9b72f24c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
//! The `map` module contains structures of the dungeon game map
//! including the current `Floor`, map `Tile`, and `Entity`.

use crate::pos::{Direction, Pos};

/// `MAP_SIZE` is the size of the size of the dungeon grid.
pub const MAP_SIZE: u16 = 100;

/// The number of tiles in the dungeon grid
pub const TILE_COUNT: usize = MAP_SIZE as usize * MAP_SIZE as usize;

/// The `EntityKind` represents what kind of entity this is.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum EntityKind {
	Player,
}

/// The `Entity` kind represents the main player, or any other
/// ai autonomous character that can move freely across the
/// dungeon.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Entity {
	pos: Pos,
	dir: Direction,
	kind: EntityKind,
}
impl Entity {
	/// Creates a new `Entity` at a given `Pos`, `Direction`, and `EntityKind`.
	///
	/// # Examples
	///
	/// ```
	/// use dungeon::{Pos, Direction, Entity, EntityKind};
	///
	/// let pos = Pos::new(0, 0).unwrap();
	/// let dir = Direction::North;
	/// let kind = EntityKind::Player;
	/// let entity = Entity::new(pos, dir, kind);
	/// ```
	#[must_use]
	pub const fn new(pos: Pos, dir: Direction, kind: EntityKind) -> Self {
		Self { pos, dir, kind }
	}

	/// Creates the Player version of the `Entity`
	///
	/// # Examples
	///
	/// ```
	/// use dungeon::{Pos, Entity};
	///
	/// let pos = Pos::new(0, 0).unwrap();
	/// let player = Entity::player(pos);
	/// ```
	#[must_use]
	pub const fn player(pos: Pos) -> Self {
		let dir = Direction::East;
		let kind = EntityKind::Player;
		Self::new(pos, dir, kind)
	}

	/// Returns the `Pos` of the entity
	#[must_use]
	pub const fn pos(&self) -> Pos {
		self.pos
	}

	/// Returns a mutable referense to the `Pos` of the entity
	#[must_use]
	pub const fn pos_mut(&mut self) -> &mut Pos {
		&mut self.pos
	}

	/// Returns the `Direction` of the entity
	#[must_use]
	pub const fn dir(&self) -> Direction {
		self.dir
	}

	/// Returns a mutable referense to the `Direction` of the entity
	#[must_use]
	pub const fn dir_mut(&mut self) -> &mut Direction {
		&mut self.dir
	}

	/// Returns the `EntityKind` of this entity
	#[must_use]
	pub const fn kind(&self) -> EntityKind {
		self.kind
	}
}

/// The `Tile` enum represents what is (or is not) at
/// any given spot in the dungeon grid.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Tile {
	/// `Wall` represents an impassible wall
	Wall,
	/// `Air` represents empty walkable space
	Air,
}

/// 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)]
pub struct Floor {
	/// The dungeon grid
	tiles: Box<[Tile; TILE_COUNT]>,
	/// The position the player starts at
	player_start: Pos,
	/// The seed used when generating the dungeon grid
	seed: u64,
}
impl Floor {
	/// Generates a dungeon `Floor` using wave function collapse.
	///
	/// # Examples
	///
	/// ```no_run
	/// use dungeon::Floor;
	///
	/// let floor = Floor::generate();
	/// ```
	#[must_use]
	pub fn generate() -> Self {
		let seed = rand::random();
		Self::generate_seeded(seed)
	}

	/// Genreates a dungeon `Floor` using wave function collapse provided with a seed.
	///
	/// The provided seed is used for randomness in the wave function
	/// collapse algorithm.
	///
	/// # Examples
	///
	/// ```no_run
	/// use dungeon::Floor;
	///
	/// /// here is our very seedy seed
	/// let seed = 2893249402u64;
	/// let floor = Floor::generate_seeded(seed);
	/// ```
	#[must_use]
	pub fn generate_seeded(_seed: u64) -> Self {
		unimplemented!()
	}

	/// Returns the start position of the player
	#[must_use]
	pub const fn player_start(&self) -> Pos {
		self.player_start
	}

	/// Returns the seed used to generate the map
	#[must_use]
	pub const fn seed(&self) -> u64 {
		self.seed
	}

	/// Returns a `Tile` on the dungeon grid at `Pos`.
	#[must_use]
	pub const fn get(&self, pos: Pos) -> Tile {
		let idx = pos.idx();
		self.tiles[idx]
	}

	/// 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 {
		let idx = pos.idx();
		&mut self.tiles[idx]
	}

	/// Returns a reference to all tiles in the `Floor`.
	/// The size of this lise will always be `TILE_COUNT` long.
	#[must_use]
	pub const fn tiles(&self) -> &[Tile] {
		&*self.tiles
	}

	/// 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] {
		&mut *self.tiles
	}
}
impl Default for Floor {
	/// Returns a floor with a single set of walls on the map border
	fn default() -> Self {
		const PLAYER_START: Pos = Pos::new_const::<1, 1>();
		let mut tiles = Box::new([Tile::Air; TILE_COUNT]);
		let seed = 0u64;

		for pos in Pos::values() {
			if pos.is_border() {
				tiles[pos.idx()] = Tile::Wall;
			}
		}

		Self {
			tiles,
			player_start: PLAYER_START,
			seed,
		}
	}
}