diff --git a/src/artifacts.rs b/src/artifacts.rs index 2d3270c..9c3043f 100644 --- a/src/artifacts.rs +++ b/src/artifacts.rs @@ -1,16 +1,56 @@ use crate::position::Position; +use crate::player::Player; -pub struct Artifact { - position: Position, +pub trait Artifact { + //! An artifact that can be collected by the player + /// get the position of the artifact in the level + fn get_immutable_position(&self) -> &Position; + /// call to apply the effects of the artifact to the player + fn collect(&mut self, player: &mut Player); } -impl Artifact { +pub struct Chest { + /// a chest that contains some gold + position: Position, + gold: usize, +} + +impl Chest { pub fn new(position: Position) -> Self { - Artifact { + Self { position, + gold: 10, } } - pub fn get_immutable_position(&self) -> &Position { - &self.position +} + +impl Artifact for Chest { + fn get_immutable_position(&self) -> &Position { &self.position } + fn collect(&mut self, player: &mut Player) { + player.retrieve_gold(self.gold); + self.gold = 0; } } + +pub struct Potion { + /// a potion that restores some health + position: Position, + health: usize, +} + +impl Potion { + pub fn new(position: Position) -> Self { + Self { + position, + health: 5, + } + } +} + +impl Artifact for Potion { + fn get_immutable_position(&self) -> &Position { &self.position } + fn collect(&mut self, player: &mut Player) { + player.change_life(self.health.try_into().unwrap()); + self.health = 0; + } +} \ No newline at end of file diff --git a/src/level.rs b/src/level.rs index 4b478f0..91839f1 100644 --- a/src/level.rs +++ b/src/level.rs @@ -1,5 +1,5 @@ use std::cmp::{max, min}; -use crate::artifacts::Artifact; +use crate::artifacts::{Artifact, Chest, Potion}; use crate::monster::Monster; use crate::position::Position; @@ -20,7 +20,7 @@ pub struct Level { structure: [[StructureElement; LEVEL_HEIGHT]; LEVEL_WIDTH], discovered: [[bool; LEVEL_HEIGHT]; LEVEL_WIDTH], monsters: Vec, - artifacts: Vec, + artifacts: Vec>, } impl Level { @@ -39,7 +39,7 @@ impl Level { artifacts: Vec::with_capacity(10), } } - pub fn get_element(&mut self, x: i16, y: i16) -> (Option, Option<&mut Monster>, Option<&mut Artifact>) { + pub fn get_element(&mut self, x: i16, y: i16) -> (Option, Option<&mut Monster>, Option<&mut Box<(dyn Artifact + 'static)>>) { if x < 0 || y < 0 { return (None, None, None); } @@ -58,7 +58,7 @@ impl Level { res_m = Some(m); } } - let mut res_a: Option<&mut Artifact> = None; + let mut res_a: Option<&mut Box> = None; for a in &mut self.artifacts { if a.get_immutable_position() == search_pos { res_a = Some(a); @@ -94,7 +94,7 @@ impl Level { } Ok(()) } - pub fn add_artifact(&mut self, mut artifact: Artifact) -> Result<(), String> { + pub fn add_artifact(&mut self, artifact: impl Artifact + 'static) -> Result<(), String> { if self.level != artifact.get_immutable_position().get_level() { return Err("Wrong Level".to_string()); } @@ -103,7 +103,7 @@ impl Level { return Err("Position already used".to_string()); } } - self.artifacts.push(artifact); + self.artifacts.push(Box::new(artifact)); Ok(()) } pub fn remove_artifact(&mut self, position: &Position) -> Result<(), String> { @@ -209,16 +209,16 @@ fn test_discover_can_add_monster() { #[test] fn test_discover_can_add_artifact() { let mut l = Level::new(0); - let a = Artifact::new(Position::new(1, 2, 3)); + let a = Chest::new(Position::new(1, 2, 3)); assert_eq!(l.add_artifact(a), Err("Wrong Level".to_string())); - let a = Artifact::new(Position::new(0, 2, 3)); + let a = Chest::new(Position::new(0, 2, 3)); assert_eq!(l.add_artifact(a), Ok(())); - let a = Artifact::new(Position::new(0, 2, 3)); + let a = Potion::new(Position::new(0, 2, 3)); assert_eq!(l.add_artifact(a), Err("Position already used".to_string())); - let a = Artifact::new(Position::new(0, 1, 3)); + let a = Chest::new(Position::new(0, 1, 3)); assert_eq!(l.add_artifact(a), Ok(())); } @@ -252,13 +252,12 @@ fn test_discover_get_artifact() { assert_eq!(l.get_element(10, 10).0.unwrap(), StructureElement::Floor); assert!(l.get_element(10, 10).2.is_none()); - let a = Artifact::new(Position::new(0, 10, 10)); + let a = Chest::new(Position::new(0, 10, 10)); assert_eq!(l.add_artifact(a), Ok(())); let elem = l.get_element(10, 10); assert_eq!(elem.0.unwrap(), StructureElement::Floor); assert!(elem.2.is_some()); - let a = elem.2.unwrap(); } #[test]