From 8b21e179c217eba7b168bde3b125917b85f2f398 Mon Sep 17 00:00:00 2001 From: Joachim Lusiardi Date: Sun, 17 Dec 2023 16:14:17 +0100 Subject: [PATCH] fight monsters, collect artifacts --- src/artifacts.rs | 9 ++++ src/game.rs | 99 ++++++++++++++++++++++++++---------------- src/level.rs | 19 +++++++- src/level_generator.rs | 2 +- src/main.rs | 28 +++++++----- 5 files changed, 105 insertions(+), 52 deletions(-) diff --git a/src/artifacts.rs b/src/artifacts.rs index 78f1123..70589b2 100644 --- a/src/artifacts.rs +++ b/src/artifacts.rs @@ -9,6 +9,7 @@ pub trait Artifact { fn get_immutable_position(&self) -> &Position; /// call to apply the effects of the artifact to the player fn collect(&mut self, player: &mut Player); + fn was_collected(&self) -> bool; } pub struct Chest { @@ -36,6 +37,10 @@ impl Artifact for Chest { player.retrieve_gold(self.gold); self.gold = 0; } + + fn was_collected(&self) -> bool { + self.gold == 0 + } } pub struct Potion { @@ -62,4 +67,8 @@ impl Artifact for Potion { player.change_life(self.health.try_into().unwrap()); self.health = 0; } + + fn was_collected(&self) -> bool { + self.health == 0 + } } \ No newline at end of file diff --git a/src/game.rs b/src/game.rs index 86df161..4f21fd3 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,3 +1,4 @@ +use std::ops::Deref; use crate::artifacts::Artifact; use crate::level::{Level, StructureElement}; use crate::level_generator::LevelGenerator; @@ -16,7 +17,7 @@ impl Game { pub fn new(p: Player) -> Game { let mut v: Vec = Vec::with_capacity(LEVELS); for d in 0..LEVELS { - v.push(LevelGenerator::generate(d, d==0, d==LEVELS-1).render()); + v.push(LevelGenerator::generate(d, d == 0, d == LEVELS - 1).render()); } let mut g = Game { player: p, @@ -72,53 +73,77 @@ impl Game { let level = &mut self.levels[player_level]; level.get_element(new_x, new_y) } - pub fn move_player(&mut self, mut dx: i16, mut dy: i16) { + + pub fn move_player(&mut self, mut dx: i16, mut dy: i16) -> (i16, i16) { // verify the player can do the move if !self.can_move(dx, dy) { - return; + return (-dx, -dy); } let player_pos = &self.player.get_position(); - // // let new_x: i16 = player_pos.get_x() as i16 + dx; - // // let new_y: i16 = player_pos.get_y() as i16 + dy; let mut player_level = player_pos.get_level(); - // // let level = &mut self.levels[player_level]; - let element = self.next_element(dx, dy); - // - // // use stairs if walked onto one - match element { - (Some(e), None, None) => { - match e { - StructureElement::StairDown => { - (dx, dy) = (0, 0); - let (next_level, x, y) = self.next_start(); - player_level = next_level; - self.get_mutable_player().get_position().set(next_level, x, y); - } - StructureElement::StairUp => { - (dx, dy) = (0, 0); - let (next_level, x, y) = self.prev_end(); - player_level = next_level; - self.get_mutable_player().get_position().set(next_level, x, y); - } - _ => {} - } - } - (_, _, _) => {} + let (structure, _, _) = self.next_element(dx, dy); + + // use stairs if walked onto one + match structure { + Some(e) => { + match e { + StructureElement::StairDown => { + (dx, dy) = (0, 0); + let (next_level, x, y) = self.next_start(); + player_level = next_level; + self.get_mutable_player().get_position().set(next_level, x, y); + } + StructureElement::StairUp => { + (dx, dy) = (0, 0); + let (next_level, x, y) = self.prev_end(); + player_level = next_level; + self.get_mutable_player().get_position().set(next_level, x, y); + } + _ => {} + } + } + _ => {} } - // - // // interact with monsters / artifacts - // match element { - // (_, _, Some(a)) => { - // // a.collect(&mut self.player); - // // level.remove_artifact(&Position::new(player_level, new_x as usize, new_y as usize)).expect("Could not collect artifact"); - // } - // (_, _, _) => {} - // } // update position and discover area on new position let (new_x, new_y) = self.get_mutable_player().get_position().change(dx, dy); self.get_mutable_level(player_level).discover(&Position::new(player_level, new_x, new_y)); + (-dx, -dy) + } + pub fn player_fights_monster(&mut self) -> bool { + let player_pos = &self.player.get_immutable_position(); + let player_level = player_pos.get_level(); + let level = &mut self.levels[player_level]; + let (_, m, _) = level.get_element(player_pos.get_x() as i16, player_pos.get_y() as i16); + match m { + None => {} + Some(m) => { + // TODO fight the monster + self.player.change_life(-1); + m.decrease_life(1); + return m.is_dead(); + } + }; + true + } + pub fn player_collects_artifact(&mut self) { + let player_pos = &self.player.get_immutable_position(); + let player_level = player_pos.get_level(); + let level = &mut self.levels[player_level]; + let (_, _, a) = level.get_element(player_pos.get_x() as i16, player_pos.get_y() as i16); + match a { + None => {} + Some(a) => { + a.collect(&mut self.player); + } + } + } + pub fn update_level(&mut self) { + let player_pos = &self.player.get_immutable_position(); + let player_level = player_pos.get_level(); + let level = &mut self.levels[player_level]; + level.update(); } } diff --git a/src/level.rs b/src/level.rs index edae6a9..9a4420c 100644 --- a/src/level.rs +++ b/src/level.rs @@ -45,8 +45,8 @@ impl Level { discovered: [[false; LEVEL_HEIGHT]; LEVEL_WIDTH], monsters: Vec::with_capacity(10), artifacts: Vec::with_capacity(10), - start: (0,0), - end: (0,0), + start: (0, 0), + end: (0, 0), } } pub fn get_element(&mut self, x: i16, y: i16) -> (Option, Option<&mut Monster>, Option<&mut Box<(dyn Artifact + 'static)>>) { @@ -172,6 +172,21 @@ impl Level { } } } + + pub fn update(&mut self) { + for (index, a) in &mut self.artifacts.iter().enumerate() { + if a.was_collected() { + self.artifacts.remove(index); + break; + } + } + for (index, m) in &mut self.monsters.iter().enumerate() { + if m.is_dead() { + self.monsters.remove(index); + break; + } + } + } } #[test] diff --git a/src/level_generator.rs b/src/level_generator.rs index 315324b..7125b67 100644 --- a/src/level_generator.rs +++ b/src/level_generator.rs @@ -274,7 +274,7 @@ impl LevelGenerator { let t_x = left + room.offset_x + rng.gen_range(0..room.width); let t_y = top + room.offset_y + rng.gen_range(0..room.height); // TODO randomize enemies here - enemies.push(Monster::new_with_position(10, Position::new(self.level, t_x, t_y))); + enemies.push(Monster::new_with_position(2, Position::new(self.level, t_x, t_y))); } if room.kind == RoomType::End || room.kind == RoomType::StairDown { diff --git a/src/main.rs b/src/main.rs index 94fb2e2..74b34dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ mod level_widget; mod level_generator; mod artifacts; mod monster; + // fn main() -> Result<()> { let mut game = Game::new(Player::new(realname().as_str(), 10)); @@ -56,7 +57,7 @@ fn main() -> Result<()> { width: level::LEVEL_WIDTH as u16, height: level::LEVEL_HEIGHT as u16, }; - frame.render_stateful_widget(LevelWidget{}, map_area, &mut game); + frame.render_stateful_widget(LevelWidget {}, map_area, &mut game); let stats_area = Rect { x: area.x + 50, @@ -81,17 +82,20 @@ fn main() -> Result<()> { if key.kind == KeyEventKind::Press && key.code == KeyCode::Char('q') { break; } - if key.kind == KeyEventKind::Press && key.code == KeyCode::Left { - game.move_player(-1, 0); - } - if key.kind == KeyEventKind::Press && key.code == KeyCode::Right { - game.move_player(1, 0); - } - if key.kind == KeyEventKind::Press && key.code == KeyCode::Up { - game.move_player(0, -1); - } - if key.kind == KeyEventKind::Press && key.code == KeyCode::Down { - game.move_player(0, 1); + if key.kind == KeyEventKind::Press { + let new_pos = match key.code { + KeyCode::Left => { game.move_player(-1, 0) } + KeyCode::Right => { game.move_player(1, 0) } + KeyCode::Up => { game.move_player(0, -1) } + KeyCode::Down => { game.move_player(0, 1) } + _ => { (0, 0) } + }; + if !game.player_fights_monster() { + // player attacked monster but did not kill it + game.move_player(new_pos.0, new_pos.1); + } + game.player_collects_artifact(); + game.update_level(); } } }