130 lines
3.3 KiB
Rust
130 lines
3.3 KiB
Rust
use ratatui::prelude::Color;
|
|
|
|
use crate::position::Position;
|
|
|
|
pub trait Monster {
|
|
fn is_dead(&self) -> bool;
|
|
fn get_representation(&self) -> (&str, Color);
|
|
fn decrease_life(&mut self, by: usize);
|
|
fn get_immutable_position(&self) -> &Position;
|
|
fn get_experience_gain(&self) -> usize;
|
|
#[cfg(test)]
|
|
fn get_position(&mut self) -> &mut Position;
|
|
#[cfg(test)]
|
|
fn get_life(&self) -> usize;
|
|
}
|
|
|
|
macro_rules! default_monster {
|
|
($($t:ty),+ $(,)?) => ($(
|
|
impl Monster for $t {
|
|
fn is_dead(&self) -> bool { self.life <= 0 }
|
|
fn get_experience_gain(&self) -> usize { self.experience_gain }
|
|
fn get_representation(&self) -> (&str, Color) { (&self.symbol, self.color) }
|
|
fn decrease_life(&mut self, by: usize) {
|
|
self.life = self.life.saturating_sub(by);
|
|
}
|
|
fn get_immutable_position(&self) -> &Position {
|
|
&self.position
|
|
}
|
|
#[cfg(test)]
|
|
fn get_position(&mut self) -> &mut Position {
|
|
&mut self.position
|
|
}
|
|
#[cfg(test)]
|
|
fn get_life(&self) -> usize { self.life }
|
|
}
|
|
)+)
|
|
}
|
|
|
|
pub struct Rat {
|
|
life: usize,
|
|
position: Position,
|
|
symbol: String,
|
|
color: Color,
|
|
experience_gain: usize,
|
|
}
|
|
|
|
impl Rat {
|
|
#[cfg(test)]
|
|
pub fn new(life: usize) -> Self {
|
|
Self {
|
|
life,
|
|
position: Position::new(0, 0, 0),
|
|
symbol: String::from("R"),
|
|
color: Color::Black,
|
|
experience_gain: 5,
|
|
}
|
|
}
|
|
pub fn new_with_position(position: Position) -> Self {
|
|
Self {
|
|
life: 2,
|
|
position,
|
|
symbol: String::from("R"),
|
|
color: Color::Black,
|
|
experience_gain: 5,
|
|
}
|
|
}
|
|
#[cfg(test)]
|
|
pub fn get_life(&self) -> usize { self.life }
|
|
}
|
|
default_monster!(Rat);
|
|
|
|
pub struct Orc {
|
|
life: usize,
|
|
position: Position,
|
|
symbol: String,
|
|
color: Color,
|
|
experience_gain: usize,
|
|
}
|
|
|
|
impl Orc {
|
|
#[cfg(test)]
|
|
pub fn new(life: usize) -> Self {
|
|
Self {
|
|
life,
|
|
position: Position::new(0, 0, 0),
|
|
symbol: String::from("O"),
|
|
color: Color::DarkGray,
|
|
experience_gain: 10,
|
|
}
|
|
}
|
|
pub fn new_with_position(position: Position) -> Self {
|
|
Self {
|
|
life: 4,
|
|
position,
|
|
symbol: String::from("O"),
|
|
color: Color::DarkGray,
|
|
experience_gain: 10,
|
|
}
|
|
}
|
|
#[cfg(test)]
|
|
pub fn get_life(&self) -> usize { self.life }
|
|
}
|
|
|
|
default_monster!(Orc);
|
|
|
|
|
|
#[test]
|
|
fn monsters_can_move() {
|
|
let mut m = Rat::new(2);
|
|
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() {
|
|
let mut m = Rat::new(2);
|
|
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);
|
|
} |