use macros to create monsters
This commit is contained in:
17
macros/Cargo.toml
Normal file
17
macros/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[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"
|
||||
58
macros/src/lib.rs
Normal file
58
macros/src/lib.rs
Normal file
@@ -0,0 +1,58 @@
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user