Created
July 27, 2023 18:30
-
-
Save ProfAndreaPollini/90a993ef8854f28dafe86be24e3b4002 to your computer and use it in GitHub Desktop.
Entity and Item for a Rust Roguelike
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fmt::Display; | |
#[derive(Debug)] | |
pub struct Entity { | |
// id: Option<EntityKey>, | |
name: String, | |
health: i32, | |
xp: i32, | |
// inventory: Option<Inventory>, | |
} | |
#[derive(Debug)] | |
pub struct Weapon { | |
damage: Option<Damage>, | |
defense: Option<Defense>, | |
} | |
#[derive(Debug)] | |
pub struct Food {} | |
#[derive(Debug)] | |
pub enum ItemClass { | |
Weapon(Weapon), | |
Food(Food), | |
} | |
struct Item { | |
name: String, | |
class: ItemClass, | |
activations: Vec<Activation>, | |
} | |
impl Display for Item { | |
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
let mut s = format!("Item: {}", self.name); | |
match &self.class { | |
ItemClass::Weapon(weapon) => { | |
s.push_str(&format!("\nDamage: {:?}", weapon.damage)); | |
s.push_str(&format!("\nDefense: {:?}", weapon.defense)); | |
} | |
ItemClass::Food(_) => {} | |
} | |
write!(f, "{}", s) | |
} | |
} | |
#[derive(Debug, Clone, PartialEq)] | |
pub enum UseResult { | |
Ok, | |
Failed, | |
} | |
pub enum UseKind { | |
Attack, | |
Defense, | |
} | |
struct Activation { | |
kind: UseKind, | |
activate: fn(&Entity) -> UseResult, | |
} | |
impl Activation { | |
pub fn can_use(&self, entity: &Entity) -> UseResult { | |
(self.activate)(entity) | |
} | |
} | |
#[derive(Debug)] | |
struct Damage { | |
value: i32, | |
} | |
#[derive(Debug)] | |
struct Defense { | |
value: i32, | |
} | |
#[cfg(test)] | |
mod tests { | |
use crate::entity; | |
use super::*; | |
#[test] | |
fn test_sword() { | |
let sword = Item { | |
name: "Sword".to_string(), | |
class: ItemClass::Weapon(Weapon { | |
damage: Some(Damage { value: 10 }), | |
defense: None, | |
}), | |
activations: vec![Activation { | |
kind: UseKind::Attack, | |
activate: |entity: &Entity| { | |
if entity.health > 50 { | |
UseResult::Ok | |
} else { | |
UseResult::Failed | |
} | |
}, | |
}], | |
}; | |
let mut player = Entity { | |
name: "Player".to_string(), | |
health: 100, | |
xp: 5, | |
}; | |
let check_is_weapon = |item: &Item| matches!(&item.class, ItemClass::Weapon(_)); | |
let can_attack = |item: &Item, entity: &Entity| match &item.class { | |
ItemClass::Weapon(_) => entity.health > 50, | |
_ => false, | |
}; | |
let decrease_health = |entity: &mut Entity, health: i32| { | |
entity.health -= health; | |
}; | |
assert!(check_is_weapon(&sword)); | |
assert!(can_attack(&sword, &player)); | |
assert_eq!( | |
sword.activations.first().unwrap().can_use(&player), | |
UseResult::Ok | |
); | |
decrease_health(&mut player, 70); | |
assert!(!can_attack(&sword, &player)); | |
assert_eq!( | |
sword.activations.first().unwrap().can_use(&player), | |
UseResult::Failed | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment