make monsters more like players

This commit is contained in:
Joachim Lusiardi 2023-12-26 11:38:23 +01:00
parent c0d51f501f
commit 2098bedabe
3 changed files with 70 additions and 64 deletions

View File

@ -80,19 +80,8 @@ impl Game {
/// limitation as walls. /// limitation as walls.
fn can_move(&mut self, dx: i16, dy: i16) -> bool { fn can_move(&mut self, dx: i16, dy: i16) -> bool {
let player_pos = &self.player.get_position(); let player_pos = &self.player.get_position();
let new_x: i16 = player_pos.get_x() as i16 + dx;
let new_y: i16 = player_pos.get_y() as i16 + dy;
let level = &mut self.levels[player_pos.get_level()]; let level = &mut self.levels[player_pos.get_level()];
match level.get_element(new_x, new_y) { level.can_player_move(&self.player, dx, dy)
(None, _, _) => { return false; }
(Some(t), _, _) => {
match t {
StructureElement::Wall => { return false; }
_ => {}
}
}
};
true
} }
/// returns the position (as tuple) of the next level's start point. /// returns the position (as tuple) of the next level's start point.
fn next_start(&self) -> (usize, usize, usize) { fn next_start(&self) -> (usize, usize, usize) {

View File

@ -6,7 +6,7 @@ use crate::artifacts::Artifact;
#[cfg(test)] #[cfg(test)]
use crate::monster::{Orc, Rat}; use crate::monster::{Orc, Rat};
use crate::monster::Monster; use crate::monster::Monster;
#[cfg(test)] use crate::player::Player;
use crate::position::HasPosition; use crate::position::HasPosition;
use crate::position::Position; use crate::position::Position;
@ -37,24 +37,6 @@ pub struct Level {
} }
impl Level { impl Level {
#[cfg(test)]
pub fn new(level: usize) -> Level {
let mut s = [[StructureElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH];
for x in 2..LEVEL_WIDTH - 2 {
for y in 2..LEVEL_HEIGHT - 2 {
s[x][y] = StructureElement::Floor;
}
}
Level {
level,
structure: s,
discovered: [[false; LEVEL_HEIGHT]; LEVEL_WIDTH],
monsters: Vec::with_capacity(10),
artifacts: Vec::with_capacity(10),
start: (0, 0),
end: (0, 0),
}
}
pub fn get_element(&mut self, x: i16, y: i16) -> (Option<StructureElement>, Option<&mut Box<(dyn Monster + 'static)>>, Option<&mut Box<(dyn Artifact + 'static)>>) { pub fn get_element(&mut self, x: i16, y: i16) -> (Option<StructureElement>, Option<&mut Box<(dyn Monster + 'static)>>, Option<&mut Box<(dyn Artifact + 'static)>>) {
if x < 0 || y < 0 { if x < 0 || y < 0 {
return (None, None, None); return (None, None, None);
@ -82,33 +64,6 @@ impl Level {
} }
(Some(self.structure[x][y]), res_m, res_a) (Some(self.structure[x][y]), res_m, res_a)
} }
#[cfg(test)]
pub fn add_monster(&mut self, mut monster: impl Monster + 'static) -> Result<(), String> {
if self.level != monster.get_position().get_level() {
return Err("Wrong Level".to_string());
}
for m in &mut self.monsters {
if m.get_position() == monster.get_position() {
return Err("Position already used".to_string());
}
}
self.monsters.push(Box::new(monster));
Ok(())
}
#[cfg(test)]
pub fn add_artifact(&mut self, artifact: impl Artifact + 'static) -> Result<(), String> {
if self.level != artifact.get_immutable_position().get_level() {
return Err("Wrong Level".to_string());
}
for a in &mut self.artifacts {
if a.get_immutable_position() == artifact.get_immutable_position() {
return Err("Position already used".to_string());
}
}
self.artifacts.push(Box::new(artifact));
Ok(())
}
/// discover the area with in the level around the given position /// discover the area with in the level around the given position
pub fn discover(&mut self, pos: &Position) { pub fn discover(&mut self, pos: &Position) {
let x = pos.get_x(); let x = pos.get_x();
@ -153,7 +108,6 @@ impl Level {
} }
} }
} }
pub fn update(&mut self) { pub fn update(&mut self) {
for (index, a) in &mut self.artifacts.iter().enumerate() { for (index, a) in &mut self.artifacts.iter().enumerate() {
if a.was_collected() { if a.was_collected() {
@ -167,6 +121,69 @@ impl Level {
break; break;
} }
} }
for index in 0..self.monsters.len() {
if self.can_monster_move(self.monsters[index].as_ref(), 0, 1) {
self.monsters[index].get_position().change(0, 1);
} else if self.can_monster_move(self.monsters[index].as_ref(), 0, -1) {
self.monsters[index].get_position().change(0, -1);
}
}
}
pub fn can_monster_move(&self, agent: &dyn Monster, dx: i16, dy: i16) -> bool {
let agent_pos = agent.get_immutable_position();
let new_x: usize = (agent_pos.get_x() as i16 + dx) as usize;
let new_y: usize = (agent_pos.get_y() as i16 + dy) as usize;
self.structure[new_x][new_y] != StructureElement::Wall
}
pub fn can_player_move(&self, agent: &Player, dx: i16, dy: i16) -> bool {
let agent_pos = agent.get_immutable_position();
let new_x: usize = (agent_pos.get_x() as i16 + dx) as usize;
let new_y: usize = (agent_pos.get_y() as i16 + dy) as usize;
self.structure[new_x][new_y] != StructureElement::Wall
}
#[cfg(test)]
pub fn new(level: usize) -> Level {
let mut s = [[StructureElement::Wall; LEVEL_HEIGHT]; LEVEL_WIDTH];
for x in 2..LEVEL_WIDTH - 2 {
for y in 2..LEVEL_HEIGHT - 2 {
s[x][y] = StructureElement::Floor;
}
}
Level {
level,
structure: s,
discovered: [[false; LEVEL_HEIGHT]; LEVEL_WIDTH],
monsters: Vec::with_capacity(10),
artifacts: Vec::with_capacity(10),
start: (0, 0),
end: (0, 0),
}
}
#[cfg(test)]
pub fn add_monster(&mut self, mut monster: impl Monster + 'static) -> Result<(), String> {
if self.level != monster.get_position().get_level() {
return Err("Wrong Level".to_string());
}
for m in &mut self.monsters {
if m.get_position() == monster.get_position() {
return Err("Position already used".to_string());
}
}
self.monsters.push(Box::new(monster));
Ok(())
}
#[cfg(test)]
pub fn add_artifact(&mut self, artifact: impl Artifact + 'static) -> Result<(), String> {
if self.level != artifact.get_immutable_position().get_level() {
return Err("Wrong Level".to_string());
}
for a in &mut self.artifacts {
if a.get_immutable_position() == artifact.get_immutable_position() {
return Err("Position already used".to_string());
}
}
self.artifacts.push(Box::new(artifact));
Ok(())
} }
} }

View File

@ -96,7 +96,7 @@ fn main() -> Result<()> {
stats_area, stats_area,
); );
})?; })?;
if event::poll(std::time::Duration::from_millis(16))? { if event::poll(std::time::Duration::from_millis(100))? {
if let event::Event::Key(key) = event::read()? { if let event::Event::Key(key) = event::read()? {
if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') {
break; break;
@ -114,13 +114,13 @@ fn main() -> Result<()> {
game.move_player(new_pos.0, new_pos.1); game.move_player(new_pos.0, new_pos.1);
} }
game.player_collects_artifact(); game.player_collects_artifact();
game.update_level();
if game.get_game_state() != GameState::RUNNING {
break;
}
} }
} }
} }
game.update_level();
if game.get_game_state() != GameState::RUNNING {
break;
}
} }
loop { loop {
let _ = terminal.draw(|frame| { let _ = terminal.draw(|frame| {