use crate::static_data::Statistic; use std::fmt::Debug; use std::sync::Arc; /// A nature is an attribute on a Pokemon that modifies the effective base stats on a Pokemon. They /// can have an increased statistic and a decreased statistic, or be neutral. pub trait Nature: Debug { /// The stat that should receive the increased modifier. fn increased_stat(&self) -> Statistic; /// The stat that should receive the decreased modifier. fn decreased_stat(&self) -> Statistic; /// The amount that the increased stat gets modified by. fn increased_modifier(&self) -> f32; /// The amount that the decreased stat gets modified by. fn decreased_modifier(&self) -> f32; /// Calculates the modifier for a given stat. If it's the increased stat, returns the increased /// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0 fn get_stat_modifier(&self, stat: Statistic) -> f32; /// Checks if two natures are equal. fn eq(&self, other: &dyn Nature) -> bool; } /// A nature is an attribute on a Pokemon that modifies the effective base stats on a Pokemon. They /// can have an increased statistic and a decreased statistic, or be neutral. #[derive(Debug)] pub struct NatureImpl { /// The stat that should receive the increased modifier. increase_stat: Statistic, /// The stat that should receive the decreased modifier. decrease_stat: Statistic, /// The amount by which the increased stat is multiplied. increase_modifier: f32, /// The amount by which the decreased stat is multiplied. decrease_modifier: f32, } impl NatureImpl { /// Instantiates a new nature. pub fn new( increase_stat: Statistic, decrease_stat: Statistic, increase_modifier: f32, decrease_modifier: f32, ) -> Arc { Arc::new(Self { increase_stat, decrease_stat, increase_modifier, decrease_modifier, }) } } impl Nature for NatureImpl { /// The stat that should receive the increased modifier. fn increased_stat(&self) -> Statistic { self.increase_stat } /// The stat that should receive the decreased modifier. fn decreased_stat(&self) -> Statistic { self.decrease_stat } fn increased_modifier(&self) -> f32 { self.increase_modifier } fn decreased_modifier(&self) -> f32 { self.decrease_modifier } /// Calculates the modifier for a given stat. If it's the increased stat, returns the increased /// modifier, if it's the decreased stat, returns the decreased modifier. Otherwise returns 1.0 fn get_stat_modifier(&self, stat: Statistic) -> f32 { if stat == self.increase_stat && stat != self.decrease_stat { self.increase_modifier } else if stat == self.decrease_stat && stat != self.increase_stat { self.decrease_modifier } else { 1.0 } } fn eq(&self, other: &dyn Nature) -> bool { std::ptr::eq(self, other as *const dyn Nature as *const Self) } } #[cfg(test)] #[allow(clippy::indexing_slicing)] #[allow(clippy::unwrap_used)] pub(crate) mod tests { use super::*; mockall::mock! { #[derive(Debug)] pub Nature {} impl Nature for Nature { fn increased_stat(&self) -> Statistic; fn decreased_stat(&self) -> Statistic; fn increased_modifier(&self) -> f32; fn decreased_modifier(&self) -> f32; fn get_stat_modifier(&self, stat: Statistic) -> f32; fn eq(&self, other: &dyn Nature) -> bool; } } }