Skip to content

Instantly share code, notes, and snippets.

@ProfAndreaPollini
Created July 27, 2023 18:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ProfAndreaPollini/90a993ef8854f28dafe86be24e3b4002 to your computer and use it in GitHub Desktop.
Save ProfAndreaPollini/90a993ef8854f28dafe86be24e3b4002 to your computer and use it in GitHub Desktop.
Entity and Item for a Rust Roguelike
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