el_diablo/src/artifacts.rs

113 lines
3.2 KiB
Rust
Raw Normal View History

use rand::Rng;
use ratatui::style::Color;
2023-12-18 16:11:19 +01:00
2023-12-03 23:59:05 +01:00
use crate::player::Player;
2023-12-18 16:11:19 +01:00
use crate::position::Position;
2023-12-03 13:44:29 +01:00
2023-12-03 23:59:05 +01:00
pub trait Artifact {
//! An artifact that can be collected by the player
fn get_representation(&self) -> (&str, Color);
2023-12-03 23:59:05 +01:00
/// 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
2023-12-31 15:59:52 +01:00
fn collect(&mut self, player: &mut Player, messages: &mut Vec<String>);
2023-12-17 22:00:42 +01:00
/// returns if the artifact was collected and can be removed from the level
2023-12-17 16:14:17 +01:00
fn was_collected(&self) -> bool;
2023-12-03 23:59:05 +01:00
}
pub struct Chest {
/// a chest that contains some gold
2023-12-03 13:44:29 +01:00
position: Position,
2023-12-03 23:59:05 +01:00
gold: usize,
2023-12-03 13:44:29 +01:00
}
2023-12-03 23:59:05 +01:00
impl Chest {
2023-12-03 13:44:29 +01:00
pub fn new(position: Position) -> Self {
2024-10-21 20:37:52 +02:00
let min_gold = 10 * (position.get_level() + 1);
let max_gold = min_gold + 10 * position.get_level();
2023-12-03 23:59:05 +01:00
Self {
2023-12-03 13:44:29 +01:00
position,
gold: rand::thread_rng().gen_range(min_gold..=max_gold),
2023-12-03 13:44:29 +01:00
}
}
2023-12-03 23:59:05 +01:00
}
impl Artifact for Chest {
fn get_representation(&self) -> (&str, Color) {
("C", Color::Blue)
}
2024-10-20 14:59:20 +02:00
fn get_immutable_position(&self) -> &Position {
&self.position
}
2023-12-31 15:59:52 +01:00
fn collect(&mut self, player: &mut Player, messages: &mut Vec<String>) {
2023-12-03 23:59:05 +01:00
player.retrieve_gold(self.gold);
2024-10-20 14:59:20 +02:00
messages.insert(
0,
format!("opened chest and collected {} gold.", self.gold).to_string(),
);
2023-12-03 23:59:05 +01:00
self.gold = 0;
2023-12-03 13:44:29 +01:00
}
2023-12-17 16:14:17 +01:00
fn was_collected(&self) -> bool {
self.gold == 0
}
2023-12-03 13:44:29 +01:00
}
2023-12-03 23:59:05 +01:00
#[derive(Clone, Copy)]
2023-12-03 23:59:05 +01:00
pub struct Potion {
/// a potion that restores some health
position: Position,
health: usize,
was_collected: bool,
2023-12-03 23:59:05 +01:00
}
impl Potion {
pub fn new(position: Position) -> Self {
let min_health_gain = 5 + position.get_level();
let max_health_gain = min_health_gain + 3 * position.get_level();
2023-12-03 23:59:05 +01:00
Self {
position,
health: rand::thread_rng().gen_range(min_health_gain..=max_health_gain),
was_collected: false,
2023-12-03 23:59:05 +01:00
}
}
}
impl Artifact for Potion {
fn get_representation(&self) -> (&str, Color) {
("P", Color::Green)
}
2024-10-20 14:59:20 +02:00
fn get_immutable_position(&self) -> &Position {
&self.position
}
2023-12-31 15:59:52 +01:00
fn collect(&mut self, player: &mut Player, messages: &mut Vec<String>) {
// only consume potion of the player can gain at least one health point
if !player.is_healthy() {
2023-12-31 15:59:52 +01:00
let old = player.get_life();
player.change_life(self.health.try_into().unwrap());
2023-12-31 15:59:52 +01:00
let new = player.get_life();
2024-10-20 14:59:20 +02:00
messages.insert(
0,
format!("picked up potion and gained {} health.", new - old).to_string(),
2024-10-20 14:59:20 +02:00
);
self.health = 0;
self.was_collected = true;
2024-10-21 21:59:55 +02:00
} else if player.add_to_inventory(self) {
messages.insert(0, "move potion to inventory.".to_string());
self.was_collected = true;
2024-10-21 21:59:55 +02:00
} else {
messages.insert(0, "inventory is full.".to_string());
}
2023-12-03 23:59:05 +01:00
}
2023-12-17 16:14:17 +01:00
fn was_collected(&self) -> bool {
self.was_collected
}
}
impl Potion {
pub fn get_health(&self) -> usize {
self.health
2023-12-17 16:14:17 +01:00
}
2024-10-20 14:59:20 +02:00
}