el_diablo/src/monster.rs

118 lines
3.2 KiB
Rust
Raw Normal View History

2023-12-18 16:11:19 +01:00
use ratatui::prelude::Color;
2023-12-25 13:47:15 +01:00
use crate::position::{HasPosition, Position};
2023-11-27 19:21:10 +01:00
2023-12-25 13:47:15 +01:00
pub trait Monster: HasPosition {
2023-12-31 15:59:52 +01:00
fn get_name(&self) -> &str;
2023-12-18 16:11:19 +01:00
fn is_dead(&self) -> bool;
fn get_representation(&self) -> (&str, Color);
fn decrease_life(&mut self, by: usize);
2023-12-25 13:47:15 +01:00
// fn get_immutable_position(&self) -> &Position;
2023-12-22 20:10:30 +01:00
fn get_experience_gain(&self) -> usize;
2023-12-26 19:11:41 +01:00
fn get_ticks_between_steps(&self) -> u128;
2023-12-18 16:11:19 +01:00
#[cfg(test)]
fn get_life(&self) -> usize;
}
macro_rules! default_monster {
($($t:ty),+ $(,)?) => ($(
impl Monster for $t {
2023-12-31 15:59:52 +01:00
fn get_name(&self) -> &str { &self.name }
2023-12-18 16:11:19 +01:00
fn is_dead(&self) -> bool { self.life <= 0 }
2023-12-22 20:10:30 +01:00
fn get_experience_gain(&self) -> usize { self.experience_gain }
2023-12-18 16:11:19 +01:00
fn get_representation(&self) -> (&str, Color) { (&self.symbol, self.color) }
fn decrease_life(&mut self, by: usize) {
self.life = self.life.saturating_sub(by);
}
2023-12-26 19:11:41 +01:00
fn get_ticks_between_steps(&self) -> u128 { self.ticks_between_steps }
2023-12-18 16:11:19 +01:00
#[cfg(test)]
2023-12-25 13:47:15 +01:00
fn get_life(&self) -> usize { self.life }
}
impl HasPosition for $t {
2023-12-18 16:11:19 +01:00
fn get_position(&mut self) -> &mut Position {
&mut self.position
}
2023-12-25 13:47:15 +01:00
fn get_immutable_position(&self) -> &Position {
&self.position
}
2023-12-18 16:11:19 +01:00
}
)+)
}
pub struct Rat {
2023-12-31 15:59:52 +01:00
name: String,
2023-11-27 19:21:10 +01:00
life: usize,
position: Position,
2023-12-18 16:11:19 +01:00
symbol: String,
color: Color,
2023-12-22 20:10:30 +01:00
experience_gain: usize,
2023-12-26 19:11:41 +01:00
ticks_between_steps: u128,
2023-11-27 19:21:10 +01:00
}
2023-12-18 16:11:19 +01:00
impl Rat {
2023-12-18 17:04:48 +01:00
pub fn new_with_position(position: Position) -> Self {
2023-12-18 16:11:19 +01:00
Self {
2023-12-31 15:59:52 +01:00
name: "rat".to_string(),
2023-12-18 17:04:48 +01:00
life: 2,
2023-12-07 10:12:44 +01:00
position,
2023-12-18 16:11:19 +01:00
symbol: String::from("R"),
2023-12-18 17:04:48 +01:00
color: Color::Black,
2023-12-22 20:10:30 +01:00
experience_gain: 5,
2023-12-26 19:11:41 +01:00
ticks_between_steps: 5,
2023-12-07 10:12:44 +01:00
}
}
2023-12-18 16:11:19 +01:00
}
default_monster!(Rat);
pub struct Orc {
2023-12-31 15:59:52 +01:00
name: String,
2023-12-18 16:11:19 +01:00
life: usize,
position: Position,
symbol: String,
color: Color,
2023-12-22 20:10:30 +01:00
experience_gain: usize,
2023-12-26 19:11:41 +01:00
ticks_between_steps: u128,
2023-12-18 16:11:19 +01:00
}
impl Orc {
2023-12-18 17:04:48 +01:00
pub fn new_with_position(position: Position) -> Self {
2023-12-18 16:11:19 +01:00
Self {
2023-12-31 15:59:52 +01:00
name: "orc".to_string(),
2023-12-18 17:04:48 +01:00
life: 4,
2023-12-18 16:11:19 +01:00
position,
symbol: String::from("O"),
color: Color::DarkGray,
2023-12-22 20:10:30 +01:00
experience_gain: 10,
2023-12-26 19:11:41 +01:00
ticks_between_steps: 10,
2023-12-18 16:11:19 +01:00
}
2023-12-03 10:41:43 +01:00
}
2023-11-27 19:21:10 +01:00
}
2023-12-18 16:11:19 +01:00
default_monster!(Orc);
2023-11-27 19:21:10 +01:00
#[test]
fn monsters_can_move() {
2023-12-31 15:59:52 +01:00
let mut m = Rat::new_with_position(Position::new(0, 0, 0));
2023-11-27 19:21:10 +01:00
assert_eq!(m.get_position(), &Position::new(0, 0, 0));
m.get_position().change(1, 2);
assert_eq!(m.get_position(), &Position::new(0, 1, 2));
m.get_position().change(2, 1);
assert_eq!(m.get_position(), &Position::new(0, 3, 3));
m.get_position().set(1, 2, 3);
m.get_position().change(2, 1);
assert_eq!(m.get_position(), &Position::new(1, 4, 4));
}
#[test]
fn monsters_can_die() {
2023-12-31 15:59:52 +01:00
let mut m = Rat::new_with_position(Position::new(0, 0, 0));
2023-11-27 19:21:10 +01:00
assert_eq!(m.get_life(), 2);
assert_eq!(m.is_dead(), false);
m.decrease_life(1);
assert_eq!(m.get_life(), 1);
m.decrease_life(2);
assert_eq!(m.get_life(), 0);
assert_eq!(m.is_dead(), true);
}