el_diablo/src/artifacts.rs

123 lines
3.6 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
2024-10-23 15:53:04 +02:00
/// get the character and color used to draw the artifact into the level
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
}
2024-10-23 15:53:04 +02:00
/// An artifact that contains a random amount of gold pieces.
2023-12-03 23:59:05 +01:00
pub struct Chest {
2024-10-23 15:53:04 +02:00
/// the chests position
2023-12-03 13:44:29 +01:00
position: Position,
2024-10-23 15:53:04 +02:00
/// the chests value
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 {
2024-10-23 15:53:04 +02:00
/// create a chest at the given position with a random amount of gold.
/// The gold amount depends on the level, the deeper you go, the more you get.
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) {
2024-10-30 13:01:28 +01:00
("C", Color::Cyan)
}
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)]
2024-10-23 15:53:04 +02:00
/// An artifact that gives the player some health on consumption.
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
}
}
2024-10-22 13:39:43 +02:00
pub fn get_health(&self) -> usize {
self.health
}
2023-12-03 23:59:05 +01:00
}
impl Artifact for Potion {
fn get_representation(&self) -> (&str, Color) {
("P", Color::Green)
}
2024-10-22 13:39:43 +02:00
2024-10-20 14:59:20 +02:00
fn get_immutable_position(&self) -> &Position {
&self.position
}
2024-10-22 13:39:43 +02:00
2023-12-31 15:59:52 +01:00
fn collect(&mut self, player: &mut Player, messages: &mut Vec<String>) {
2024-10-23 15:53:04 +02:00
//! called when the player walked on to a potion.
//!
//! Depending on health status and inventory usage the potion will
//! be consumed directly or moved to inventory.
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
}
}