From 42bff2595f3aa3231bada20dd01ae3c83f107780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20GUEZO?= Date: Tue, 13 Jan 2026 22:33:31 +0100 Subject: [PATCH] feat: assemble weapon and potions into item file --- src/character.rs | 57 +++++++++++++++++++--------------- src/items.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- src/main.rs | 7 ++++- src/weapon.rs | 66 --------------------------------------- 5 files changed, 119 insertions(+), 93 deletions(-) create mode 100644 src/items.rs delete mode 100644 src/weapon.rs diff --git a/src/character.rs b/src/character.rs index 131f3da..fa4fdd8 100644 --- a/src/character.rs +++ b/src/character.rs @@ -1,4 +1,6 @@ -use crate::weapon::Weapon; +use std::f64::consts::E; + +use crate::items::Item; /// # Character /// @@ -24,67 +26,72 @@ use crate::weapon::Weapon; /// for method chaining. /// - `get_name` is only an accessor of `name` pub struct Character { - life: u8, + pub life: u8, name: &'static str, - weapon: Option>, + item: Option>, } impl Character { /// Creates a new `Character` with the given attributes. /// Acts as a "static constructor" returning the /// initialized struct. - pub fn new(life: u8, name: &'static str, weapon: Option>) -> Self { - Character { life, name, weapon } + pub fn new(name: &'static str, life: u8, item: Option>) -> Self { + Character { life, name, item } } - pub fn new_no_weapon(life: u8, name: &'static str) -> Self { + pub fn new_no_weapon(name: &'static str, life: u8) -> Self { Character { life, name, - weapon: None, + item: None, } } - /// Attacks another character, reducing their `life` by - /// self.damage. Returns `self` to allow method chaining. - pub fn attack(&mut self, other: &mut Self) -> &mut Self { - if let Some(w) = &mut self.weapon { - other.life = w - .if_not_broken(|damage: u8| other.life - damage) - .unwrap_or(0); - w.consume(); + pub fn use_item(&mut self, other: Option<&mut Character>) -> () { + let mut item: Option> = self.item.take(); // pop item and replace to None + if let Some(i) = &mut item { + i.apply(other.unwrap_or(self)); } - self + self.item = item; } /// Returns the character's name. pub fn get_name(&self) -> &str { self.name } + + pub fn set_item(&mut self, item: Option>) -> &mut Self { + self.item = item; + self + } } #[cfg(test)] mod tests { use super::*; + use crate::items::{Potion, Weapon}; #[test] /// Tests that a character is correctly initialized. fn character_build() { - let c = Character::new_no_weapon(100, "test"); + let c = Character::new_no_weapon("test", 100); assert_eq!(c.life, 100); assert_eq!(c.name, c.get_name()); } #[test] /// Tests that attacking reduces the target's life correctly. - fn character_attack() { - let w = Box::new(Weapon::new("test", 10, 100)); - let mut c1 = Character::new(100, "test1", Option::Some(w)); - let mut c2 = Character::new_no_weapon(200, "test2"); + fn character_item() { + let w = Box::new(Weapon::new("testw", 10, 100)); + let p = Box::new(Potion::new("testp", 50)); - c1.attack(&mut c2); - assert_eq!(c2.life, 190); - Character::attack(&mut c2, &mut c1); - assert_eq!(c1.life, 100); + let mut c: Character = Character::new_no_weapon("testc", 100); + c.set_item(Some(p)).use_item(None); + + assert_eq!(c.life, 150); + + c.set_item(Some(w)).use_item(None); + + assert_eq!(c.life, 140); } } diff --git a/src/items.rs b/src/items.rs new file mode 100644 index 0000000..458003c --- /dev/null +++ b/src/items.rs @@ -0,0 +1,80 @@ +use crate::character::Character; + +pub trait Item { + fn apply(&mut self, char: &mut Character) -> (); + fn get_name(&self) -> &'static str; +} + +pub struct Weapon { + name: &'static str, + damage: u8, + durability: u8, +} + +// #[warn(dead_code)] +impl Weapon { + pub fn new(name: &'static str, damage: u8, durability: u8) -> Self { + Weapon { + name, + damage, + durability, + } + } + + fn reduce_durability(&mut self) -> () { + self.durability = self.durability.saturating_sub(self.damage / 2); + } + + pub fn is_broken(&self) -> bool { + self.durability == 0 + } +} + +impl Item for Weapon { + fn apply(&mut self, char: &mut Character) -> () { + if !self.is_broken() { + char.life = char.life.saturating_sub(self.damage); + self.reduce_durability(); + } + } + + fn get_name(&self) -> &'static str { + self.name + } +} + +pub struct Potion { + name: &'static str, + heal: u8, +} + +impl Potion { + pub fn new(name: &'static str, heal: u8) -> Self { + Potion { name, heal } + } +} + +impl Item for Potion { + fn apply(&mut self, char: &mut Character) -> () { + char.life += self.heal; + } + + fn get_name(&self) -> &'static str { + self.name + } +} + +#[cfg(test)] +mod tests { + mod weapon { + use super::super::*; + + #[test] + fn build() { + let w = Weapon::new("test", 10, 100); + assert_eq!(w.damage, 10); + assert_eq!(w.durability, 100); + assert_eq!(w.get_name(), w.name); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 85c82de..72d675c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,2 @@ pub mod character; -pub mod weapon; \ No newline at end of file +pub mod items; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index f328e4d..ebdd353 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1 +1,6 @@ -fn main() {} +use bakersadventure::items::{Item, Weapon}; + +fn main() { + let mut list: [Box; 1] = [Box::new(Weapon::new("name", 1, 1))]; + +} diff --git a/src/weapon.rs b/src/weapon.rs deleted file mode 100644 index eb0c03d..0000000 --- a/src/weapon.rs +++ /dev/null @@ -1,66 +0,0 @@ -pub struct Weapon { - name: &'static str, - damage: u8, - durability: u8, -} - -impl Weapon { - pub fn new(name: &'static str, damage: u8, durability: u8) -> Self { - Weapon { - name, - damage, - durability, - } - } - - pub fn consume(&mut self) -> &mut Self { - self.durability -= (self.damage / 2) as u8; - self - } - - fn is_broken(&self) -> bool { - self.durability <= 0 - } - - pub fn if_not_broken(&mut self, fun: F) -> Option - where - F: FnOnce(u8) -> T, - { - if !self.is_broken() { - Some(fun(self.damage)) - } else { - None - } - } - - pub fn get_name(&self) -> &'static str { - self.name - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn weapon_build() { - let w = Weapon::new("test", 10, 100); - assert_eq!(w.damage, 10); - assert_eq!(w.durability, 100); - assert_eq!(w.get_name(), w.name); - } - - #[test] - fn weapon_consumption() { - let mut w = Weapon::new("test", 10, 100); - w.consume(); - assert_eq!(w.durability, 95); - } - - #[test] - fn weapon_if_not_broken() { - let mut w = Weapon::new("test", 10, 100); - let val: u8 = 50; - assert_eq!(w.if_not_broken(|d: u8| { val - d }).unwrap(), 40); - } -}