feat(character.rs): replace inner weapon var to weapon "class"

This commit is contained in:
2026-01-13 00:01:40 +01:00
parent f32414d377
commit 1120aa04b8

View File

@@ -1,3 +1,5 @@
use crate::weapon::Weapon;
/// # Character /// # Character
/// ///
/// Originally, there were two python classes: `Heroes` /// Originally, there were two python classes: `Heroes`
@@ -7,54 +9,48 @@
/// ///
/// It consists of: /// It consists of:
/// - `life` as unsigned 8-bit integer /// - `life` as unsigned 8-bit integer
/// - `damage` as unsigned 8-bit integer /// - `weapon` as Option heap weapon struct
/// - `mana` as unsigned 8-bit integer
/// - `name` as rodata str (string stored in /// - `name` as rodata str (string stored in
/// read-only memory) /// read-only memory)
/// ///
/// It also provides the following methods: /// It also provides the following methods:
/// - `new(u8, u8, u8, &'static str)` function is used /// - `new(u8, &'static str, Option<Box<Weapon>>)`
/// to be a static constructor of `Character` that return /// function is used to be a static constructor of
/// the struct initialized. /// `Character` that return the struct initialized.
/// - `attack(&mut self, &mut self)` function removes /// - `attack(&mut self, &mut self)` function removes
/// other's life based on self damage and return self /// other's life based on self damage and return self
/// for method chaining. /// for method chaining.
/// - `comsume_mana(&mut self, u8)` function reduces mana
/// with the `u8` second parameter.
/// - `get_name` is only an accessor of `name` /// - `get_name` is only an accessor of `name`
pub struct Character { pub struct Character {
life: u8, life: u8,
damage: u8,
mana: u8,
name: &'static str, name: &'static str,
weapon: Option<Box<Weapon>>,
} }
impl Character { impl Character {
/// Creates a new `Character` with the given attributes. /// Creates a new `Character` with the given attributes.
/// Acts as a "static constructor" returning the /// Acts as a "static constructor" returning the
/// initialized struct. /// initialized struct.
pub fn new(life: u8, damage: u8, mana: u8, name: &'static str) -> Self { pub fn new(life: u8, name: &'static str, weapon: Option<Box<Weapon>>) -> Self {
Character { Character { life, name, weapon }
life, }
damage,
mana, pub fn new_no_weapon(life: u8, name: &'static str) -> Self {
name, Character { life, name, weapon: None }
}
} }
/// Attacks another character, reducing their `life` by /// Attacks another character, reducing their `life` by
/// self.damage. Returns `self` to allow method chaining. /// self.damage. Returns `self` to allow method chaining.
pub fn attack(&mut self, other: &mut Self) -> &mut Self { pub fn attack(&mut self, other: &mut Self) -> &mut Self {
other.life -= self.damage; if let Some(w) = &mut self.weapon {
w.if_not_broken(|damage: u8| other.life -= damage);
w.consume();
}
self self
} }
/// Consumes `consumption` amount of mana.
/// Returns `self` to allow method chaining.
pub fn consume_mana(&mut self, consumption: u8) -> &mut Self {
self.mana -= consumption;
self
}
/// Returns the character's name. /// Returns the character's name.
pub fn get_name(&self) -> &str { pub fn get_name(&self) -> &str {
self.name self.name
@@ -68,42 +64,21 @@ mod tests {
#[test] #[test]
/// Tests that a character is correctly initialized. /// Tests that a character is correctly initialized.
fn character_build() { fn character_build() {
let c = Character::new(10, 5, 3, "test1"); let c = Character::new_no_weapon(100, "test");
assert_eq!(c.life, 10); assert_eq!(c.life, 100);
assert_eq!(c.damage, 5);
assert_eq!(c.mana, 3);
assert_eq!(c.name, c.get_name()); assert_eq!(c.name, c.get_name());
} }
#[test] #[test]
/// Tests that attacking reduces the target's life correctly. /// Tests that attacking reduces the target's life correctly.
fn character_attack() { fn character_attack() {
let mut c1 = Character::new(10, 3, 5, "test1"); let w = Box::new(Weapon::new("test", 10, 100));
let mut c2 = Character::new(10, 2, 5, "test2"); let mut c1 = Character::new(100, "test1", Option::Some(w));
let mut c2 = Character::new_no_weapon(200, "test2");
c1.attack(&mut c2); c1.attack(&mut c2);
assert_eq!(c2.life, 7); assert_eq!(c2.life, 190);
Character::attack(&mut c2, &mut c1); Character::attack(&mut c2, &mut c1);
assert_eq!(c1.life, 8); assert_eq!(c1.life, 100);
}
#[test]
/// Tests that consuming mana reduces it correctly.
fn character_mana() {
let mut c = Character::new(10, 3, 15, "test1");
c.consume_mana(10);
assert_eq!(c.mana, 5);
}
#[test]
/// Tests method chaining: attack -> consume mana
/// -> attack.
fn character_chaining() {
let mut c1 = Character::new(10, 3, 15, "test1");
let mut c2 = Character::new(10, 2, 15, "test2");
c1.attack(&mut c2).consume_mana(10).attack(&mut c2);
assert_eq!(c2.life, 4);
assert_eq!(c1.mana, 5);
} }
} }