132 lines
3.3 KiB
Rust
132 lines
3.3 KiB
Rust
use std::ops::RangeInclusive;
|
|
|
|
use crate::position::{HasPosition, Position};
|
|
use macros::CreateMonsters;
|
|
use rand::Rng;
|
|
use ratatui::prelude::Color;
|
|
|
|
pub trait Monster: HasPosition {
|
|
fn get_name(&self) -> &str;
|
|
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;
|
|
fn get_ticks_between_steps(&self) -> u128;
|
|
#[cfg(test)]
|
|
fn get_life(&self) -> usize;
|
|
fn damage(&self) -> usize;
|
|
}
|
|
|
|
#[derive(CreateMonsters, PartialEq, Eq, Hash, Clone, Copy)]
|
|
pub enum MonsterTypes {
|
|
Rat,
|
|
Orc,
|
|
Snake,
|
|
Skeleton,
|
|
Spider,
|
|
}
|
|
|
|
macro_rules! create_monster {
|
|
($t:ident $(, $k:ident : $v:expr)*$(,)?) => (
|
|
impl $t {
|
|
pub fn new_with_position(position: Position) -> Self {
|
|
Self {
|
|
position,
|
|
$($k: $v,)*
|
|
}
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
create_monster!(
|
|
Rat,
|
|
name:"rat".to_string(),
|
|
life: 2,
|
|
symbol: String::from("r"),
|
|
color: Color::White,
|
|
experience_gain: 5,
|
|
ticks_between_steps: 5,
|
|
damage_range: 1..=2,
|
|
);
|
|
|
|
create_monster!(
|
|
Spider,
|
|
name:"spider".to_string(),
|
|
life: 3,
|
|
symbol: String::from("s"),
|
|
color: Color::Yellow,
|
|
experience_gain: 7,
|
|
ticks_between_steps: 7,
|
|
damage_range: 2..=3,
|
|
);
|
|
|
|
create_monster!(
|
|
Orc,
|
|
name: "orc".to_string(),
|
|
life: 4,
|
|
symbol: String::from("O"),
|
|
color: Color::Gray,
|
|
experience_gain: 10,
|
|
ticks_between_steps: 10,
|
|
damage_range: 2..=3,
|
|
);
|
|
|
|
create_monster!(
|
|
Snake,
|
|
name: "snake".to_string(),
|
|
life: 3,
|
|
symbol: String::from("s"),
|
|
color: Color::White,
|
|
experience_gain: 10,
|
|
ticks_between_steps: 20,
|
|
damage_range: 1..=4,
|
|
);
|
|
|
|
create_monster!(
|
|
Skeleton,
|
|
name: "skeleton".to_string(),
|
|
life: 3,
|
|
symbol: String::from("S"),
|
|
color: Color::Gray,
|
|
experience_gain: 20,
|
|
ticks_between_steps: 10,
|
|
damage_range: 1..=5,
|
|
);
|
|
|
|
pub fn create_monster_by_type(monster_type: &MonsterTypes, position: Position) -> Box<dyn Monster> {
|
|
match monster_type {
|
|
MonsterTypes::Rat => Box::new(Rat::new_with_position(position)),
|
|
MonsterTypes::Orc => Box::new(Orc::new_with_position(position)),
|
|
MonsterTypes::Snake => Box::new(Snake::new_with_position(position)),
|
|
MonsterTypes::Skeleton => Box::new(Skeleton::new_with_position(position)),
|
|
MonsterTypes::Spider => Box::new(Spider::new_with_position(position)),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn monsters_can_move() {
|
|
let mut m = Rat::new_with_position(Position::new(0, 0, 0));
|
|
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_with_position(Position::new(0, 0, 0));
|
|
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);
|
|
}
|