diff --git a/src/game.rs b/src/game.rs index 225ddef..6482dd5 100644 --- a/src/game.rs +++ b/src/game.rs @@ -98,6 +98,12 @@ impl DungeonLevel { DungeonTile::Hallway => '#', } } + + /// Gets a reference to the tile at the given coordinates. Panics + /// of the coordinates are out of bounds. + pub fn tile(&self, x: i32, y: i32) -> &DungeonTile { + &self.tiles[y as usize][x as usize] + } } impl Display for DungeonLevel { diff --git a/src/player.rs b/src/player.rs index fd62ad1..8436b07 100644 --- a/src/player.rs +++ b/src/player.rs @@ -5,7 +5,7 @@ use specs::prelude::*; use crate::{ components::{CharRender, MobAction, Mobile, Player, Position}, - game::DungeonLevel, + game::{DungeonLevel, DungeonTile}, quit, }; @@ -53,7 +53,9 @@ pub fn player_turn(ecs: &mut World, screen: &mut Window) { }; if let Some(action) = action { - break action; + if possible(ecs, &action) { + break action; + } } }; @@ -64,6 +66,23 @@ pub fn player_turn(ecs: &mut World, screen: &mut Window) { } } +/// Checks whether an action is possible for the player to execute in +/// the given world. +fn possible(ecs: &World, action: &MobAction) -> bool { + match action { + MobAction::Nop => true, + MobAction::Move(dx, dy) => { + let players = ecs.read_storage::(); + let positions = ecs.read_storage::(); + let map = ecs.fetch::(); + + (&players, &positions) + .join() + .all(|(_plr, pos)| map.tile(pos.x + dx, pos.y + dy) != &DungeonTile::Wall) + } + } +} + /// Renders the state of the world onto the screen. fn render_screen(ecs: &mut World, screen: &mut Window) { // screen.clear();