Compare commits

..

No commits in common. "e490011b4e994bb39bda20ed5bbdd0035f470c06" and "38dc7285c2b599d9913d3686fdc4e2baa7bbddad" have entirely different histories.

7 changed files with 99 additions and 224 deletions

76
Cargo.lock generated
View File

@ -104,41 +104,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "darling"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.9.0" version = "1.9.0"
@ -150,7 +115,6 @@ name = "el_diabolo"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"crossterm", "crossterm",
"macros",
"petgraph", "petgraph",
"rand", "rand",
"ratatui", "ratatui",
@ -179,12 +143,6 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.11" version = "0.2.11"
@ -218,12 +176,6 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.1.0" version = "2.1.0"
@ -305,16 +257,6 @@ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]]
name = "macros"
version = "0.1.0"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "1.0.2" version = "1.0.2"
@ -381,18 +323,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.89" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.37" version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -539,12 +481,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.26.3" version = "0.26.3"
@ -569,9 +505,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.85" version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View File

@ -1,6 +1,3 @@
[workspace]
members = ["macros"]
[package] [package]
name = "el_diabolo" name = "el_diabolo"
version = "0.1.0" version = "0.1.0"
@ -14,7 +11,6 @@ crossterm = "0.28.1"
rand = "0.8.5" rand = "0.8.5"
petgraph = "0.6.5" petgraph = "0.6.5"
whoami = "1.5.2" whoami = "1.5.2"
macros = { path = "./macros" }
[package.metadata.deb] [package.metadata.deb]
maintainer = "Joachim Lusiardi <joachim@lusiardi.de>" maintainer = "Joachim Lusiardi <joachim@lusiardi.de>"

View File

@ -1,17 +0,0 @@
[package]
name = "macros"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "macros"
path = "src/lib.rs"
proc-macro = true
[dependencies]
syn = "2.0.85"
quote = "1.0.37"
proc-macro2 = "1.0.89"
darling= "0.20.10"

View File

@ -1,58 +0,0 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
#[proc_macro_derive(CreateMonsters)]
pub fn create_monsters(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as syn::File);
let (enum_item, _) = match &input.items[0] {
syn::Item::Enum(enum_item) => (enum_item, &enum_item.attrs),
_ => panic!("must be an enum"),
};
let structs = enum_item.variants.iter().map(|variant| {
let variant_name = &variant.ident;
let t = quote! {
pub struct #variant_name {
name: String,
life: usize,
position: Position,
symbol: String,
color: Color,
experience_gain: usize,
ticks_between_steps: u128,
damage_range: RangeInclusive<usize>,
}
impl Monster for #variant_name {
fn get_name(&self) -> &str { &self.name }
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_ticks_between_steps(&self) -> u128 { self.ticks_between_steps }
fn damage(&self) -> usize { rand::thread_rng().gen_range(self.damage_range.clone()) }
#[cfg(test)]
fn get_life(&self) -> usize { self.life }
}
impl HasPosition for #variant_name {
fn get_position(&mut self) -> &mut Position {
&mut self.position
}
fn get_immutable_position(&self) -> &Position {
&self.position
}
}
};
t
});
let output = quote::quote! {
#(#structs)*
};
output.into()
}

View File

@ -12,7 +12,7 @@ use rand::Rng;
use crate::artifacts::{Artifact, Chest, Potion}; use crate::artifacts::{Artifact, Chest, Potion};
use crate::level::{Level, StructureElement}; use crate::level::{Level, StructureElement};
use crate::monster::{create_monster_by_type, Monster, MonsterTypes, Orc, Rat, Snake}; use crate::monster::{create_monster_by_type, Monster, Orc, Rat, Snake};
use crate::position::Position; use crate::position::Position;
pub const ROOMS_VERTICAL: usize = 7; pub const ROOMS_VERTICAL: usize = 7;
@ -268,12 +268,11 @@ impl LevelGenerator {
let t = [ let t = [
// level 0 // level 0
HashMap::from([(MonsterTypes::Rat, 1..=100)]), HashMap::from([("Rat", 1..=100)]),
// level 1 // level 1
HashMap::from([(MonsterTypes::Rat, 1..=50), (MonsterTypes::Snake, 51..=100)]), // HashMap::from([("Rat", 1..=50), ("Snake", 51..=100)]),
// level 2 // // level 2
HashMap::from([(MonsterTypes::Orc, 1..=100)]), // HashMap::from([("Rat", 1..=40)]),
HashMap::from([(MonsterTypes::Skeleton, 1..=100)]),
]; ];
if level < t.len() { if level < t.len() {
for (mtype, range) in &t[level] { for (mtype, range) in &t[level] {

View File

@ -1,10 +1,10 @@
use std::ops::RangeInclusive; use std::ops::RangeInclusive;
use crate::position::{HasPosition, Position};
use macros::CreateMonsters;
use rand::Rng; use rand::Rng;
use ratatui::prelude::Color; use ratatui::prelude::Color;
use crate::position::{HasPosition, Position};
pub trait Monster: HasPosition { pub trait Monster: HasPosition {
fn get_name(&self) -> &str; fn get_name(&self) -> &str;
fn is_dead(&self) -> bool; fn is_dead(&self) -> bool;
@ -18,77 +18,99 @@ pub trait Monster: HasPosition {
fn damage(&self) -> usize; fn damage(&self) -> usize;
} }
#[derive(CreateMonsters, PartialEq, Eq, Hash)]
pub enum MonsterTypes {
Rat,
Orc,
Snake,
Skeleton,
}
macro_rules! create_monster { macro_rules! create_monster {
($t:ident $(, $k:ident : $v:expr)*$(,)?) => ( ($($t:ident),+ $(,)?) => ($(
impl $t { pub struct $t {
pub fn new_with_position(position: Position) -> Self { name: String,
Self { life: usize,
position, position: Position,
$($k: $v,)* symbol: String,
} color: Color,
experience_gain: usize,
ticks_between_steps: u128,
damage_range: RangeInclusive<usize>,
}
impl Monster for $t {
fn get_name(&self) -> &str { &self.name }
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_ticks_between_steps(&self) -> u128 { self.ticks_between_steps }
fn damage(&self) -> usize { rand::thread_rng().gen_range(self.damage_range.clone()) }
#[cfg(test)]
fn get_life(&self) -> usize { self.life }
}
impl HasPosition for $t {
fn get_position(&mut self) -> &mut Position {
&mut self.position
}
fn get_immutable_position(&self) -> &Position {
&self.position
} }
} }
) )+)
} }
create_monster!( impl Rat {
Rat, pub fn new_with_position(position: Position) -> Self {
name:"rat".to_string(), Self {
life: 2, name: "rat".to_string(),
symbol: String::from("R"), life: 2,
color: Color::Black, position,
experience_gain: 5, symbol: String::from("R"),
ticks_between_steps: 5, color: Color::Black,
damage_range: 1..=2, experience_gain: 5,
); ticks_between_steps: 5,
damage_range: 1..=2,
}
}
}
create_monster!(Rat);
create_monster!( impl Orc {
Orc, pub fn new_with_position(position: Position) -> Self {
name: "orc".to_string(), Self {
life: 4, name: "orc".to_string(),
symbol: String::from("O"), life: 4,
color: Color::DarkGray, position,
experience_gain: 10, symbol: String::from("O"),
ticks_between_steps: 10, color: Color::DarkGray,
damage_range: 2..=3, experience_gain: 10,
); ticks_between_steps: 10,
damage_range: 2..=3,
}
}
}
create_monster!(Orc);
create_monster!( impl Snake {
Snake, pub fn new_with_position(position: Position) -> Self {
name: "snake".to_string(), Self {
life: 3, name: "snake".to_string(),
symbol: String::from("s"), life: 3,
color: Color::Black, position,
experience_gain: 10, symbol: String::from("S"),
ticks_between_steps: 20, color: Color::DarkGray,
damage_range: 1..=4, experience_gain: 10,
); ticks_between_steps: 20,
damage_range: 1..=4,
}
}
}
create_monster!(Snake);
create_monster!( pub fn create_monster_by_type(mtype: &str, position: Position) -> Box<dyn Monster> {
Skeleton, match mtype {
name: "skeleton".to_string(), "Rat" => Box::new(Rat::new_with_position(position)),
life: 3, "Orc" => Box::new(Orc::new_with_position(position)),
symbol: String::from("S"), "Snake" => Box::new(Snake::new_with_position(position)),
color: Color::DarkGray, &_ => {
experience_gain: 20, panic!("Unknown species: {}", mtype)
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)),
} }
} }

View File

@ -115,7 +115,6 @@ fn test_get_name() {
gold: 0, gold: 0,
experience: 0, experience: 0,
inventory: vec![], inventory: vec![],
inventory_slots: 1,
}; };
assert_eq!(p.get_name(), "Teddy Tester"); assert_eq!(p.get_name(), "Teddy Tester");
} }
@ -140,7 +139,6 @@ fn test_change_life() {
gold: 0, gold: 0,
experience: 0, experience: 0,
inventory: vec![], inventory: vec![],
inventory_slots: 1,
}; };
assert_eq!(p.get_life(), 5); assert_eq!(p.get_life(), 5);
p.change_life(-2); p.change_life(-2);
@ -175,7 +173,6 @@ fn test_max_life() {
gold: 0, gold: 0,
experience: 0, experience: 0,
inventory: vec![], inventory: vec![],
inventory_slots: 1,
}; };
assert_eq!(p.get_max_life(), 10); assert_eq!(p.get_max_life(), 10);
} }