123 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
use rand::Rng;
 | 
						|
use ratatui::style::Color;
 | 
						|
 | 
						|
use crate::player::Player;
 | 
						|
use crate::position::Position;
 | 
						|
 | 
						|
pub trait Artifact {
 | 
						|
    //! An artifact that can be collected by the player
 | 
						|
    /// get the character and color used to draw the artifact into the level
 | 
						|
    fn get_representation(&self) -> (&str, Color);
 | 
						|
    /// 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, messages: &mut Vec<String>);
 | 
						|
    /// returns if the artifact was collected and can be removed from the level
 | 
						|
    fn was_collected(&self) -> bool;
 | 
						|
}
 | 
						|
 | 
						|
/// An artifact that contains a random amount of gold pieces.
 | 
						|
pub struct Chest {
 | 
						|
    /// the chests position
 | 
						|
    position: Position,
 | 
						|
    /// the chests value
 | 
						|
    gold: usize,
 | 
						|
}
 | 
						|
 | 
						|
impl Chest {
 | 
						|
    /// 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.
 | 
						|
    pub fn new(position: Position) -> Self {
 | 
						|
        let min_gold = 10 * (position.get_level() + 1);
 | 
						|
        let max_gold = min_gold + 10 * position.get_level();
 | 
						|
        Self {
 | 
						|
            position,
 | 
						|
            gold: rand::thread_rng().gen_range(min_gold..=max_gold),
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
impl Artifact for Chest {
 | 
						|
    fn get_representation(&self) -> (&str, Color) {
 | 
						|
        ("C", Color::Cyan)
 | 
						|
    }
 | 
						|
 | 
						|
    fn get_immutable_position(&self) -> &Position {
 | 
						|
        &self.position
 | 
						|
    }
 | 
						|
    fn collect(&mut self, player: &mut Player, messages: &mut Vec<String>) {
 | 
						|
        player.retrieve_gold(self.gold);
 | 
						|
        messages.insert(
 | 
						|
            0,
 | 
						|
            format!("opened chest and collected {} gold.", self.gold).to_string(),
 | 
						|
        );
 | 
						|
        self.gold = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    fn was_collected(&self) -> bool {
 | 
						|
        self.gold == 0
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#[derive(Clone, Copy)]
 | 
						|
/// An artifact that gives the player some health on consumption.
 | 
						|
pub struct Potion {
 | 
						|
    /// a potion that restores some health
 | 
						|
    position: Position,
 | 
						|
    health: usize,
 | 
						|
    was_collected: bool,
 | 
						|
}
 | 
						|
 | 
						|
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();
 | 
						|
        Self {
 | 
						|
            position,
 | 
						|
            health: rand::thread_rng().gen_range(min_health_gain..=max_health_gain),
 | 
						|
            was_collected: false,
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    pub fn get_health(&self) -> usize {
 | 
						|
        self.health
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
impl Artifact for Potion {
 | 
						|
    fn get_representation(&self) -> (&str, Color) {
 | 
						|
        ("P", Color::Green)
 | 
						|
    }
 | 
						|
 | 
						|
    fn get_immutable_position(&self) -> &Position {
 | 
						|
        &self.position
 | 
						|
    }
 | 
						|
 | 
						|
    fn collect(&mut self, player: &mut Player, messages: &mut Vec<String>) {
 | 
						|
        //! 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() {
 | 
						|
            let old = player.get_life();
 | 
						|
            player.change_life(self.health.try_into().unwrap());
 | 
						|
            let new = player.get_life();
 | 
						|
            messages.insert(
 | 
						|
                0,
 | 
						|
                format!("picked up potion and gained {} health.", new - old).to_string(),
 | 
						|
            );
 | 
						|
            self.health = 0;
 | 
						|
            self.was_collected = true;
 | 
						|
        } else if player.add_to_inventory(self) {
 | 
						|
            messages.insert(0, "move potion to inventory.".to_string());
 | 
						|
            self.was_collected = true;
 | 
						|
        } else {
 | 
						|
            messages.insert(0, "inventory is full.".to_string());
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    fn was_collected(&self) -> bool {
 | 
						|
        self.was_collected
 | 
						|
    }
 | 
						|
}
 |