diff --git a/src/artifacts.rs b/src/artifacts.rs new file mode 100644 index 0000000..2d3270c --- /dev/null +++ b/src/artifacts.rs @@ -0,0 +1,16 @@ +use crate::position::Position; + +pub struct Artifact { + position: Position, +} + +impl Artifact { + pub fn new(position: Position) -> Self { + Artifact { + position, + } + } + pub fn get_immutable_position(&self) -> &Position { + &self.position + } +} diff --git a/src/level.rs b/src/level.rs index dc42346..4b478f0 100644 --- a/src/level.rs +++ b/src/level.rs @@ -1,4 +1,5 @@ use std::cmp::{max, min}; +use crate::artifacts::Artifact; use crate::monster::Monster; use crate::position::Position; @@ -19,6 +20,7 @@ pub struct Level { structure: [[StructureElement; LEVEL_HEIGHT]; LEVEL_WIDTH], discovered: [[bool; LEVEL_HEIGHT]; LEVEL_WIDTH], monsters: Vec, + artifacts: Vec, } impl Level { @@ -34,30 +36,49 @@ impl Level { structure: s, discovered: [[false; LEVEL_HEIGHT]; LEVEL_WIDTH], monsters: Vec::with_capacity(10), + artifacts: Vec::with_capacity(10), } } - pub fn get_element(&mut self, x: i16, y: i16) -> (Option, Option<&mut Monster>) { + pub fn get_element(&mut self, x: i16, y: i16) -> (Option, Option<&mut Monster>, Option<&mut Artifact>) { if x < 0 || y < 0 { - return (None, None); + return (None, None, None); } let x = x as usize; let y = y as usize; if x >= LEVEL_WIDTH || y >= LEVEL_HEIGHT { - return (None, None); + return (None, None, None); } if !self.discovered[x][y] { - return (Some(StructureElement::Unknown), None); + return (Some(StructureElement::Unknown), None, None); } + let search_pos = &Position::new(self.level, x, y); let mut res_m: Option<&mut Monster> = None; for m in &mut self.monsters { - if m.get_position() == &mut Position::new(self.level, x, y) { + if m.get_immutable_position() == search_pos { res_m = Some(m); } } - - (Some(self.structure[x][y]), res_m) + let mut res_a: Option<&mut Artifact> = None; + for a in &mut self.artifacts { + if a.get_immutable_position() == search_pos { + res_a = Some(a); + } + } + (Some(self.structure[x][y]), res_m, res_a) } - // pub fn remove_monster(&mut self, mut monster: Monster) -> Result<(), String> { + pub fn add_monster(&mut self, mut monster: Monster) -> Result<(), String> { + if self.level != monster.get_position().get_level() { + return Err("Wrong Level".to_string()); + } + for m in &mut self.monsters { + if m.get_position() == monster.get_position() { + return Err("Position already used".to_string()); + } + } + self.monsters.push(monster); + Ok(()) + } + pub fn remove_dead_monster(&mut self, position: &Position) -> Result<(), String> { if self.level != position.get_level() { return Err("Wrong Level".to_string()); @@ -73,19 +94,30 @@ impl Level { } Ok(()) } - pub fn add_monster(&mut self, mut monster: Monster) -> Result<(), String> { - if self.level != monster.get_position().get_level() { + pub fn add_artifact(&mut self, mut artifact: Artifact) -> Result<(), String> { + if self.level != artifact.get_immutable_position().get_level() { return Err("Wrong Level".to_string()); } - for m in &mut self.monsters { - if m.get_position() == monster.get_position() { + for a in &mut self.artifacts { + if a.get_immutable_position() == artifact.get_immutable_position() { return Err("Position already used".to_string()); } } - self.monsters.push(monster); + self.artifacts.push(artifact); + Ok(()) + } + pub fn remove_artifact(&mut self, position: &Position) -> Result<(), String> { + if self.level != position.get_level() { + return Err("Wrong Level".to_string()); + } + for (index, a) in &mut self.artifacts.iter().enumerate() { + if a.get_immutable_position() == position { + self.monsters.remove(index); + break; + } + } Ok(()) } - /// discover the area with in the level around the given position pub fn discover(&mut self, pos: &Position) { let x = pos.get_x(); @@ -174,6 +206,22 @@ fn test_discover_can_add_monster() { assert_eq!(l.add_monster(m), Ok(())); } +#[test] +fn test_discover_can_add_artifact() { + let mut l = Level::new(0); + let a = Artifact::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)); + assert_eq!(l.add_artifact(a), Ok(())); + + let a = Artifact::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)); + assert_eq!(l.add_artifact(a), Ok(())); +} + #[test] fn test_discover_get_monster() { let mut l = Level::new(0); @@ -196,6 +244,23 @@ fn test_discover_get_monster() { assert_eq!(l.get_element(10, 10).1.unwrap().get_life(), 21); } +#[test] +fn test_discover_get_artifact() { + let mut l = Level::new(0); + let p = Position::new(0, 10, 10); + l.discover(&p); + 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)); + 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] fn test_discover_get_monster_can_move() { let mut l = Level::new(0); @@ -228,7 +293,7 @@ fn test_monster_can_be_removed() { let m = level.get_element(10, 10).1.unwrap(); m.decrease_life(3); - assert_eq!(level.remove_dead_monster( &Position::new(0, 10, 10)), Ok(())); + assert_eq!(level.remove_dead_monster(&Position::new(0, 10, 10)), Ok(())); assert!(level.get_element(10, 10).1.is_none()); } diff --git a/src/main.rs b/src/main.rs index 75796ea..c529ea5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ mod player; mod level; mod position; mod monster; +mod artifacts; fn main() { let mut p = Player::new("Teddy Tester", 10); diff --git a/src/monster.rs b/src/monster.rs index 8444a43..2fdf08a 100644 --- a/src/monster.rs +++ b/src/monster.rs @@ -1,5 +1,3 @@ -use std::cmp::max; - use crate::position::Position; pub struct Monster { @@ -16,8 +14,8 @@ impl Monster { } pub fn get_life(&self) -> usize { self.life } pub fn is_dead(&self) -> bool { self.life <= 0 } - pub fn decrease_life(&mut self, by: i16) { - self.life = max(0, self.life as i16 - by) as usize; + pub fn decrease_life(&mut self, by: usize) { + self.life = self.life.saturating_sub(by); } pub fn get_position(&mut self) -> &mut Position { &mut self.position