movement depends on monster class now

This commit is contained in:
Joachim Lusiardi 2024-01-10 16:40:46 +01:00
parent 0b08cb41c2
commit efe531f6ce
3 changed files with 63 additions and 8 deletions

View File

@ -129,13 +129,7 @@ impl Level {
} }
loop { loop {
// calculate the direction the monster will try to walk // calculate the direction the monster will try to walk
let (dx, dy) = match self.rng.gen_range(0..5) { let (dx, dy) = self.monsters[index].get_next_move(&self, player.get_immutable_position());
1 => { (1, 0) }
2 => { (-1, 0) }
3 => { (0, 1) }
4 => { (0, -1) }
_ => { (0, 0) }
};
if self.can_monster_move(self.monsters[index].as_ref(), dx, dy) { if self.can_monster_move(self.monsters[index].as_ref(), dx, dy) {
let (new_x, new_y) = self.monsters[index].get_position().change(dx, dy); let (new_x, new_y) = self.monsters[index].get_position().change(dx, dy);
if player.get_immutable_position().get_x() == new_x && player.get_immutable_position().get_y() == new_y { if player.get_immutable_position().get_x() == new_x && player.get_immutable_position().get_y() == new_y {

View File

@ -1,7 +1,10 @@
use ratatui::prelude::Color; use ratatui::prelude::Color;
use crate::dungeon_slayer::MonsterStats; use crate::dungeon_slayer::MonsterStats;
use crate::level::Level;
use crate::position::{HasPosition, Position}; use crate::position::{HasPosition, Position};
use rand::Rng;
pub trait Monster: HasPosition { pub trait Monster: HasPosition {
fn get_name(&self) -> &str; fn get_name(&self) -> &str;
@ -13,6 +16,7 @@ pub trait Monster: HasPosition {
fn get_ticks_between_steps(&self) -> u128; fn get_ticks_between_steps(&self) -> u128;
fn get_defense(&self) -> u8; fn get_defense(&self) -> u8;
fn get_hit(&self) -> u8; fn get_hit(&self) -> u8;
fn get_next_move(&self, level: &Level, player_pos: &Position) -> (i16, i16);
#[cfg(test)] #[cfg(test)]
fn get_life(&self) -> usize; fn get_life(&self) -> usize;
} }
@ -30,6 +34,9 @@ macro_rules! default_monster {
fn get_ticks_between_steps(&self) -> u128 { self.ticks_between_steps } fn get_ticks_between_steps(&self) -> u128 { self.ticks_between_steps }
fn get_defense(&self) -> u8 { self.monster_stats.defense } fn get_defense(&self) -> u8 { self.monster_stats.defense }
fn get_hit(&self) -> u8 { self.monster_stats.hit } fn get_hit(&self) -> u8 { self.monster_stats.hit }
fn get_next_move(&self, level: &Level, player_pos: &Position) -> (i16, i16) {
self.calc_move(level, player_pos)
}
#[cfg(test)] #[cfg(test)]
fn get_life(&self) -> usize { self.life } fn get_life(&self) -> usize { self.life }
} }
@ -90,6 +97,20 @@ impl crate::monster::LowerDaemon {
monster_stats, monster_stats,
} }
} }
fn calc_move(&self, level: &Level, player_pos: &Position) -> (i16, i16) {
let d = self.position.distance(player_pos);
if d == 1 {
return self.position.get_direction(player_pos);
}
match rand::thread_rng().gen_range(0..5) {
1 => { (1, 0) }
2 => { (-1, 0) }
3 => { (0, 1) }
4 => { (0, -1) }
_ => { (0, 0) }
}
}
} }
default_monster!(LowerDaemon); default_monster!(LowerDaemon);
@ -139,6 +160,15 @@ impl Rat {
monster_stats, monster_stats,
} }
} }
fn calc_move(&self, level: &Level, player_pos: &Position) -> (i16, i16) {
match rand::thread_rng().gen_range(0..5) {
1 => { (1, 0) }
2 => { (-1, 0) }
3 => { (0, 1) }
4 => { (0, -1) }
_ => { (0, 0) }
}
}
} }
default_monster!(Rat); default_monster!(Rat);
@ -188,6 +218,15 @@ impl Orc {
monster_stats, monster_stats,
} }
} }
fn calc_move(&self, level: &Level, player_pos: &Position) -> (i16, i16) {
match rand::thread_rng().gen_range(0..5) {
1 => { (1, 0) }
2 => { (-1, 0) }
3 => { (0, 1) }
4 => { (0, -1) }
_ => { (0, 0) }
}
}
} }
default_monster!(Orc); default_monster!(Orc);

View File

@ -1,4 +1,4 @@
use std::cmp::max; use std::cmp::{max, min};
/// describes an character (PC or NPC) in the dungeon that has a position. /// describes an character (PC or NPC) in the dungeon that has a position.
pub trait HasPosition { pub trait HasPosition {
@ -43,6 +43,28 @@ impl Position {
} }
pub fn get_y(&self) -> usize { self.y } pub fn get_y(&self) -> usize { self.y }
/// calculate the distance to the other position using the manhattan metric
pub fn distance(&self, other: &Self) -> usize {
self.x.abs_diff(other.x) + self.y.abs_diff(other.y)
}
/// get the direction (step size 1) towards the other position
pub fn get_direction(&self, other: &Self) -> (i16, i16) {
(
max(min(other.x as i16 - self.x as i16, 1), -1),
max(min(other.y as i16 - self.y as i16, 1), -1)
)
}
}
#[test]
fn test_get_direction() {
let p1 = Position::new(0, 10, 10);
let p2 = Position::new(0, 8, 8);
assert_eq!(p1.get_direction(&p2), (-1, -1));
let p2 = Position::new(0, 11, 10);
assert_eq!(p1.get_direction(&p2), (1, 0));
} }
#[test] #[test]