use std::fmt::Debug; use std::sync::Arc; use hashbrown::HashSet; use crate::dynamic_data::choices::{MoveChoice, TurnChoice}; use crate::dynamic_data::Pokemon; use crate::dynamic_data::{LearnedMove, MoveLearnMethod}; use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect}; use crate::StringKey; /// The misc library holds several misc functions required for the battle to run. pub trait MiscLibrary<'library>: Debug { /// Returns whether or not a Pokemon is allowed to flee or switch out. fn can_flee(&self, choice: &TurnChoice) -> bool; /// Returns the move we need to use if we can't use another move. Typically Struggle. fn replacement_move<'func>( &'func self, user: &Arc>, target_side: u8, target_index: u8, ) -> TurnChoice<'func, 'library>; // TODO: can evolve from level up? // TODO: get time } /// A gen 7 implementation for the MiscLibrary. #[derive(Debug)] pub struct Gen7MiscLibrary<'library> { /// The move data for struggle. This is a pointer due to lifetime issues; we know that the /// learned move based on this has the same lifetime as the move data, but the compiler does not. /// If possible in a sane manner, we should get rid of this pointer. struggle_data: *const MoveData, /// The learned move data for struggle. struggle_learned_move: Arc>, } impl<'library> Gen7MiscLibrary<'library> { /// Instantiates a new MiscLibrary. pub fn new() -> Self { let struggle_data = Box::new(MoveData::new( &StringKey::new("struggle"), 0, MoveCategory::Physical, 50, 255, 255, MoveTarget::Any, 0, Some(SecondaryEffect::new(-1.0, StringKey::new("struggle"), vec![])), HashSet::new(), )); let struggle_ptr = Box::into_raw(struggle_data); let struggle_learned_move = Arc::new(LearnedMove::new(unsafe { &*struggle_ptr }, MoveLearnMethod::Unknown)); Self { struggle_data: struggle_ptr, struggle_learned_move, } } } impl<'library> Default for Gen7MiscLibrary<'library> { fn default() -> Self { Self::new() } } impl<'library> Drop for Gen7MiscLibrary<'library> { fn drop(&mut self) { unsafe { Box::from_raw(self.struggle_data as *mut MoveData); } } } impl<'library> MiscLibrary<'library> for Gen7MiscLibrary<'library> { fn can_flee(&self, _choice: &TurnChoice) -> bool { todo!() } fn replacement_move<'func>( &'func self, user: &Arc>, target_side: u8, target_index: u8, ) -> TurnChoice<'func, 'library> { self.struggle_learned_move.restore_all_uses(); TurnChoice::Move(MoveChoice::new( user.clone(), self.struggle_learned_move.clone(), target_side, target_index, )) } }