From 314e9dbe1aa9c3e8ff457d30e4433a98b7f17bc3 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Sun, 19 Jun 2022 21:34:08 +0200 Subject: [PATCH] Initial work on adding documentation, reorganises modules --- src/defines.rs | 6 + .../{choices/mod.rs => choices.rs} | 79 +++++++++-- src/dynamic_data/event_hooks.rs | 111 +++++++++++++++ src/dynamic_data/event_hooks/event_hook.rs | 69 --------- src/dynamic_data/event_hooks/mod.rs | 1 - src/dynamic_data/flow/choice_queue.rs | 31 +++- src/dynamic_data/flow/mod.rs | 13 +- src/dynamic_data/flow/target_resolver.rs | 38 +++-- src/dynamic_data/flow/turn_runner.rs | 37 ++--- src/dynamic_data/history/history_holder.rs | 2 - src/dynamic_data/history/mod.rs | 4 +- .../libraries/battle_stat_calculator.rs | 132 ++++++++++-------- src/dynamic_data/libraries/damage_library.rs | 7 +- src/dynamic_data/libraries/dynamic_library.rs | 28 ++-- src/dynamic_data/libraries/misc_library.rs | 30 ++-- src/dynamic_data/libraries/mod.rs | 21 ++- src/dynamic_data/mod.rs | 29 +++- src/dynamic_data/models/battle.rs | 32 +++-- src/dynamic_data/models/battle_random.rs | 7 +- src/dynamic_data/models/battle_side.rs | 26 ++-- src/dynamic_data/models/executing_move.rs | 20 +-- src/dynamic_data/models/mod.rs | 45 ++++-- src/dynamic_data/models/pokemon.rs | 55 ++++---- src/dynamic_data/models/pokemon_builder.rs | 2 +- src/dynamic_data/script_handling/mod.rs | 45 +++--- src/dynamic_data/script_handling/script.rs | 23 +-- src/lib.rs | 37 ++++- .../lookup_growth_rate.rs => growth_rates.rs} | 6 +- src/static_data/growth_rates/growth_rate.rs | 6 - src/static_data/growth_rates/mod.rs | 5 - src/static_data/{items/item.rs => items.rs} | 31 +++- src/static_data/items/item_category.rs | 27 ---- src/static_data/items/mod.rs | 5 - src/static_data/libraries/ability_library.rs | 9 +- .../libraries/growth_rate_library.rs | 10 +- src/static_data/libraries/item_library.rs | 10 +- src/static_data/libraries/mod.rs | 29 ++-- src/static_data/libraries/move_library.rs | 8 +- src/static_data/libraries/species_library.rs | 12 +- src/static_data/mod.rs | 26 ++-- src/static_data/moves/mod.rs | 14 +- src/static_data/species_data/mod.rs | 20 ++- src/static_data/statistic_set.rs | 57 +++++++- src/utils/mod.rs | 8 +- tests/common/data_getter.rs | 3 +- tests/common/library_loader.rs | 24 ++-- tests/common/test_case.rs | 23 +-- tests/common/test_step.rs | 10 +- tests/main.rs | 6 +- 49 files changed, 806 insertions(+), 473 deletions(-) rename src/dynamic_data/{choices/mod.rs => choices.rs} (77%) create mode 100644 src/dynamic_data/event_hooks.rs delete mode 100644 src/dynamic_data/event_hooks/event_hook.rs delete mode 100644 src/dynamic_data/event_hooks/mod.rs delete mode 100644 src/dynamic_data/history/history_holder.rs rename src/static_data/{growth_rates/lookup_growth_rate.rs => growth_rates.rs} (84%) delete mode 100644 src/static_data/growth_rates/growth_rate.rs delete mode 100644 src/static_data/growth_rates/mod.rs rename src/static_data/{items/item.rs => items.rs} (66%) delete mode 100644 src/static_data/items/item_category.rs delete mode 100644 src/static_data/items/mod.rs diff --git a/src/defines.rs b/src/defines.rs index c14ebdc..c56c27a 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -1,2 +1,8 @@ +/// The type we store a level in. As our implementation is aimed at normal Pokemon behaviour, a u8 +/// is probably enough, as we'd go up to 100. For other users this might however not be enough. This +/// allows them to easily change it. pub type LevelInt = u8; + +/// The amount of moves a Pokemon can have at once. This is set to 4, as that is the default in most +/// current Pokemon generations. A developer should be able to modify this however. pub const MAX_MOVES: usize = 4; diff --git a/src/dynamic_data/choices/mod.rs b/src/dynamic_data/choices.rs similarity index 77% rename from src/dynamic_data/choices/mod.rs rename to src/dynamic_data/choices.rs index f91183e..8d0c5f0 100644 --- a/src/dynamic_data/choices/mod.rs +++ b/src/dynamic_data/choices.rs @@ -1,30 +1,49 @@ -use crate::dynamic_data::models::learned_move::LearnedMove; -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::dynamic_data::script_handling::script::ScriptContainer; -use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; -use parking_lot::RwLock; use std::cmp::Ordering; use std::sync::Arc; +use parking_lot::RwLock; + +use crate::dynamic_data::LearnedMove; +use crate::dynamic_data::Pokemon; +use crate::dynamic_data::ScriptContainer; +use crate::dynamic_data::{ScriptSource, ScriptSourceData, ScriptWrapper}; + +/// The data on a turn choice that should be contained in every turn choice, regardless of type. #[derive(Debug)] struct CommonChoiceData<'user, 'library> { + /// The user of the turn choice user: Arc>, + /// The speed of the user at the beginning of the turn. speed: u32, + /// This random value is set at the beginning of the turn. It is used for tie breaking of the + /// turn order in a predictable way, regardless of implementation and hardware. random_value: u32, + /// Whether or not the choice has failed. A failed choice will stop running, and execute special + /// fail handling during turn execution. has_failed: bool, + /// The data we can use to retrieve scripts that are affecting this choice. This will be written + /// to once: when we need to initialize it. After that, this is only used to read. To prevent a + /// read while we're writing to it, this is a RwLock. script_source_data: RwLock, } +/// This enum defines a single choice for a Pokemon for a battle turn. #[derive(Debug)] pub enum TurnChoice<'user, 'library> { + /// A move choice tells a Pokemon to use a move on a target for this turn. Move(MoveChoice<'user, 'library>), + /// An item choice tells a Pokemon to use an item. Item(ItemChoice<'user, 'library>), + /// A switch choice tells a Pokemon to switch with another Pokemon from the party. Switch(SwitchChoice<'user, 'library>), + /// A flee choice tells a Pokemon to flee from battle. Flee(FleeChoice<'user, 'library>), + /// A pass choice tells the user to do nothing that turn. Pass(PassChoice<'user, 'library>), } impl<'user, 'library> TurnChoice<'user, 'library> { + /// The shared choice data between each of the different turn choices. fn choice_data(&self) -> &CommonChoiceData<'user, 'library> { match self { TurnChoice::Move(data) => &data.choice_data, @@ -34,6 +53,7 @@ impl<'user, 'library> TurnChoice<'user, 'library> { TurnChoice::Pass(data) => &data.choice_data, } } + /// The shared choice data between each of the different turn choices. fn choice_data_mut(&mut self) -> &mut Box> { match self { TurnChoice::Move(data) => &mut data.choice_data, @@ -44,34 +64,49 @@ impl<'user, 'library> TurnChoice<'user, 'library> { } } + /// Get the user of the given choice. pub fn user(&self) -> &Arc> { &self.choice_data().user } + /// Get the speed of the user for the choice. Note that this speed is the speed of the Pokemon + /// at the start of the turn! pub fn speed(&self) -> u32 { self.choice_data().speed } + /// Get the mutable speed of the user for the choice. Note that this speed is the speed of the Pokemon + /// at the start of the turn! pub fn speed_mut(&mut self) -> &mut u32 { &mut self.choice_data_mut().speed } + /// Gets whether or not the choice has failed. If we notice this when we execute the choice, we + /// will not execute it. pub fn has_failed(&self) -> bool { self.choice_data().has_failed } + /// Fails the choice. This will prevent it from executing and run a specific fail handling during + /// execution. Note that this can not be undone. pub fn fail(&mut self) { self.choice_data_mut().has_failed = true } + /// The random value of a turn choice gets set during the start of a choice, and is used for tie + /// breaking of turn executions. This means that choices get executed with a predictable order, + /// regardless of implementation details. pub(crate) fn random_value(&self) -> u32 { self.choice_data().random_value } + /// This sets the above random value. pub(crate) fn set_random_value(&mut self, val: u32) { self.choice_data_mut().random_value = val; } + /// Helper function to get the move choice data from a turn. Note that this will panic if not + /// used on a move choice. pub(crate) fn get_move_turn_data<'b>(&'b self) -> &'b MoveChoice<'user, 'library> { if let TurnChoice::Move(data) = self { return data; @@ -122,17 +157,25 @@ impl<'user, 'library> ScriptSource<'user> for TurnChoice<'user, 'library> { } } +/// The data attached to a move choice. #[derive(Debug)] pub struct MoveChoice<'user, 'library> { + /// The move that is used for this choice. used_move: Arc>, + /// The side this move is aimed at. target_side: u8, + /// The index of the Pokemon on the side we're aiming at. target_index: u8, + /// The move script. script: ScriptContainer, + /// The priority of the move choice at the beginning of the turn. priority: i8, + /// The common turn choice data. choice_data: Box>, } impl<'user, 'library> MoveChoice<'user, 'library> { + /// Initializes the data for a new move choice. pub fn new( user: Arc>, used_move: Arc>, @@ -155,29 +198,35 @@ impl<'user, 'library> MoveChoice<'user, 'library> { } } + /// The actual learned move on the Pokemon we use for this choice. pub fn used_move(&self) -> &Arc> { &self.used_move } + /// The target side the move is aimed at. pub fn target_side(&self) -> u8 { self.target_side } + /// The Pokemon index on the side we're aiming at. pub fn target_index(&self) -> u8 { self.target_index } + /// The priority of the move choice at the beginning of the turn. pub fn priority(&self) -> i8 { self.priority } + /// The priority of the move choice at the beginning of the turn. + pub fn priority_mut(&mut self) -> &mut i8 { + &mut self.priority + } + /// The user of the choice. pub fn user(&self) -> &Arc> { &self.choice_data.user } + /// The move script of the choice. pub fn script(&self) -> &ScriptContainer { &self.script } - - pub fn priority_mut(&mut self) -> &mut i8 { - &mut self.priority - } } impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> { @@ -199,12 +248,15 @@ impl<'user, 'library> ScriptSource<'user> for MoveChoice<'user, 'library> { } } +/// The data given when we select an item choice. #[derive(Debug)] pub struct ItemChoice<'user, 'library> { + /// The shared data of all turn choices. choice_data: Box>, } impl<'user, 'library> ItemChoice<'user, 'library> { + /// Initialised a new item choice. pub fn new(user: Arc>) -> Self { Self { choice_data: Box::new(CommonChoiceData { @@ -234,12 +286,15 @@ impl<'user, 'library> ScriptSource<'user> for ItemChoice<'user, 'library> { } } +/// The data given when we select a switch choice. #[derive(Debug)] pub struct SwitchChoice<'user, 'library> { + /// The shared data of all turn choices. choice_data: Box>, } impl<'user, 'library> SwitchChoice<'user, 'library> { + /// Initialise the turn choice data. pub fn new(user: Arc>) -> Self { Self { choice_data: Box::new(CommonChoiceData { @@ -269,12 +324,15 @@ impl<'user, 'library> ScriptSource<'user> for SwitchChoice<'user, 'library> { } } +/// The data given when we select a flee choice. #[derive(Debug)] pub struct FleeChoice<'user, 'library> { + /// The common data all turn choices share. choice_data: Box>, } impl<'user, 'library> FleeChoice<'user, 'library> { + /// Initialises a new flee choice. pub fn new(user: Arc>) -> Self { Self { choice_data: Box::new(CommonChoiceData { @@ -304,12 +362,15 @@ impl<'user, 'library> ScriptSource<'user> for FleeChoice<'user, 'library> { } } +/// The data given when we select a pass choice. #[derive(Debug)] pub struct PassChoice<'user, 'library> { + /// The common data of all turn choices. choice_data: Box>, } impl<'user, 'library> PassChoice<'user, 'library> { + /// Initialised a new pass choice. pub fn new(user: Arc>) -> Self { Self { choice_data: Box::new(CommonChoiceData { diff --git a/src/dynamic_data/event_hooks.rs b/src/dynamic_data/event_hooks.rs new file mode 100644 index 0000000..35365d6 --- /dev/null +++ b/src/dynamic_data/event_hooks.rs @@ -0,0 +1,111 @@ +use std::fmt::{Debug, Formatter}; + +use crate::dynamic_data::DamageSource; +use crate::dynamic_data::ExecutingMove; +use crate::dynamic_data::Pokemon; +use crate::static_data::Form; +use crate::static_data::Species; + +/// The event hook is used to store external functions that listen to events. +/// +/// Events happen in many +/// different places in the battle, and can be used for GUI applications to show that these events +/// are happening. +#[derive(Default)] +pub struct EventHook { + /// All the registered event listeners on the hook. + evt_hook_function: Vec)>, +} + +impl<'battle, 'library> EventHook { + /// Register a new listener. This will start receiving all events in the battle. Multiple event + /// listeners can exist at the same time. Note that for these functions the event will be disposed + /// of after the event is finished being sent. + pub fn register_listener(&mut self, func: fn(&Box<&Event>)) { + self.evt_hook_function.push(func); + } + + /// Run a new event. This will send the event to all externally defined event listeners. It will + /// dispose of the event afterwards. + pub fn trigger<'b>(&self, evt: Event<'b, 'battle, 'library>) { + let b = Box::new(&evt); + for f in &self.evt_hook_function { + f(&b); + } + } +} + +impl Debug for EventHook { + fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { + Ok(()) + } +} + +/// The different events that can occur during the battle, for which a GUI should show something. +#[derive(Debug)] +pub enum Event<'own, 'battle, 'library> { + /// A switch event happens when a Pokemon gets switched out for something else. + Switch { + /// The side the Pokemon got switched from/on + side_index: u8, + /// The index of the Pokemon that got switched in/out on its side + index: u8, + /// The new Pokemon that will be on the spot. If none, the spot will now be empty. + pokemon: Option<&'own Pokemon<'battle, 'library>>, + }, + /// A swap event happens when two Pokemon on a side swap positions. Note that this is rare. + Swap { + /// The side the Pokemon swapped on. + side_index: u8, + /// The index on the side of the first Pokemon that was swapped. + index_a: u8, + /// The index on the side of the second pokemon that was swapped. + index_b: u8, + }, + /// This event happens when a Pokemon changes species during battle. While not normally occuring + /// this can be useful for things such as mid-battle evolutions, which some fanmade implementations + /// enjoy. + SpeciesChange { + /// The pokemon that changed species. + pokemon: &'own Pokemon<'battle, 'library>, + /// The new species of the Pokemon. + species: &'own Species, + /// The form of the species the Pokemon will have. + form: &'own Form, + }, + /// This event happens when a Pokemon changes form during battle. This is rather common. + FormChange { + /// The pokemon that changed forms. + pokemon: &'own Pokemon<'battle, 'library>, + /// The new form of the Pokemon. + form: &'own Form, + }, + /// This event happens when a Pokemon takes damage. + Damage { + /// The Pokemon that takes damage. + pokemon: &'own Pokemon<'battle, 'library>, + /// The source of damage. + source: DamageSource, + /// The health of the Pokemon before the damage. + original_health: u32, + /// The health of the Pokemon after the damage. + new_health: u32, + }, + /// This event happens when a Pokemon faints. + Faint { + /// The pokemon that has fainted. + pokemon: &'own Pokemon<'battle, 'library>, + }, + /// This event happens when a Pokemon uses a move on a target, just before any hits. + MoveUse { + /// The data of the move used. + executing_move: &'own ExecutingMove<'own, 'battle, 'library>, + }, + /// This event happens when a Pokemon missed. + Miss { + /// The pokemon that missed. + user: &'own Pokemon<'battle, 'library>, + }, + /// The turn is finished running, waiting for new input. + EndTurn, +} diff --git a/src/dynamic_data/event_hooks/event_hook.rs b/src/dynamic_data/event_hooks/event_hook.rs deleted file mode 100644 index b0dec9b..0000000 --- a/src/dynamic_data/event_hooks/event_hook.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crate::dynamic_data::models::damage_source::DamageSource; -use crate::dynamic_data::models::executing_move::ExecutingMove; -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::static_data::species_data::form::Form; -use crate::static_data::species_data::species::Species; -use std::fmt::{Debug, Formatter}; - -#[derive(Default)] -pub struct EventHook { - evt_hook_function: Vec)>, -} - -impl<'battle, 'library> EventHook { - pub fn register_listener(&mut self, func: fn(&Box<&Event>)) { - self.evt_hook_function.push(func); - } - - pub fn trigger<'b>(&self, evt: Event<'b, 'battle, 'library>) { - let b = Box::new(&evt); - for f in &self.evt_hook_function { - f(&b); - } - } -} - -impl Debug for EventHook { - fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { - Ok(()) - } -} - -#[derive(Debug)] -pub enum Event<'own, 'battle, 'library> { - Switch { - side_index: u8, - index: u8, - pokemon: Option<&'own Pokemon<'battle, 'library>>, - }, - Swap { - side_index: u8, - index_a: u8, - index_b: u8, - }, - SpeciesChange { - pokemon: &'own Pokemon<'battle, 'library>, - species: &'own Species, - form: &'own Form, - }, - FormChange { - pokemon: &'own Pokemon<'battle, 'library>, - form: &'own Form, - }, - Damage { - pokemon: &'own Pokemon<'battle, 'library>, - source: DamageSource, - original_health: u32, - new_health: u32, - }, - Faint { - pokemon: &'own Pokemon<'battle, 'library>, - }, - MoveUse { - executing_move: &'own ExecutingMove<'own, 'battle, 'library>, - }, - Miss { - user: &'own Pokemon<'battle, 'library>, - }, - EndTurn, -} diff --git a/src/dynamic_data/event_hooks/mod.rs b/src/dynamic_data/event_hooks/mod.rs deleted file mode 100644 index 2181c6e..0000000 --- a/src/dynamic_data/event_hooks/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod event_hook; diff --git a/src/dynamic_data/flow/choice_queue.rs b/src/dynamic_data/flow/choice_queue.rs index cb4f37d..87d9cd1 100644 --- a/src/dynamic_data/flow/choice_queue.rs +++ b/src/dynamic_data/flow/choice_queue.rs @@ -1,35 +1,60 @@ use crate::dynamic_data::choices::TurnChoice; -use crate::dynamic_data::models::pokemon::Pokemon; +use crate::dynamic_data::Pokemon; +/// The ChoiceQueue is used to run choices one by one. +/// +/// It functions internally by holding a vector of choices, and passing ownership of the turn choice +/// to the turn executor one by one, replacing it with empty spots at the start. It holds several +/// helper functions to change the turn order while doing the execution. This is needed, as several +/// moves in Pokemon actively mess with this order. #[derive(Debug)] pub struct ChoiceQueue<'battle, 'library> { + /// Our storage of turn choices. Starts out completely filled, then slowly empties as turns get + /// executed. queue: Vec>>, + /// The current index of the turn we need to execute next. current: usize, } impl<'battle, 'library> ChoiceQueue<'battle, 'library> { - pub fn new(queue: Vec>>) -> Self { + /// Initializes a ChoiceQueue. We expect the given queue to already be sorted here. + pub(crate) fn new(queue: Vec>>) -> Self { Self { queue, current: 0 } } + /// Dequeues the next turn choice to be executed. This gives ownership to the callee, and replaces + /// our own reference to the turn choice with an empty spot. It also increments the current position + /// by one. pub fn dequeue<'b>(&'b mut self) -> TurnChoice<'battle, 'library> { let c = self.queue[self.current].take(); self.current += 1; c.unwrap() } - pub fn peek(&mut self) -> &'battle TurnChoice { + /// This reads what the next choice to execute will be, without modifying state. + pub fn peek(&self) -> &'battle TurnChoice { self.queue[self.current].as_ref().unwrap() } + /// Check if we have any choices remaining. pub fn has_next(&self) -> bool { self.current < self.queue.len() } + /// This resorts the yet to be executed choices. This can be useful for dealing with situations + /// such as Pokemon changing forms just after the very start of a turn, when turn order has + /// technically already been decided. + pub fn resort(&mut self) { + let len = self.queue.len(); + self.queue[self.current..len].sort_unstable_by(|a, b| b.cmp(a)); + } + + /// This moves the choice of a specific Pokemon up to the next choice to be executed. pub fn move_pokemon_choice_next(&mut self, _pokemon: &Pokemon) { todo!() } + /// Internal helper function to be easily able to iterate over the yet to be executed choices. pub(crate) fn get_queue(&self) -> &[Option>] { &self.queue[self.current..self.queue.len()] } diff --git a/src/dynamic_data/flow/mod.rs b/src/dynamic_data/flow/mod.rs index df8c1cf..16acbfe 100644 --- a/src/dynamic_data/flow/mod.rs +++ b/src/dynamic_data/flow/mod.rs @@ -1,3 +1,10 @@ -pub mod choice_queue; -pub mod target_resolver; -pub mod turn_runner; +#[doc(inline)] +pub use choice_queue::*; +#[doc(inline)] +pub use target_resolver::*; +#[doc(inline)] +pub use turn_runner::*; + +mod choice_queue; +mod target_resolver; +mod turn_runner; diff --git a/src/dynamic_data/flow/target_resolver.rs b/src/dynamic_data/flow/target_resolver.rs index 5004ed3..3fae6d1 100644 --- a/src/dynamic_data/flow/target_resolver.rs +++ b/src/dynamic_data/flow/target_resolver.rs @@ -1,12 +1,16 @@ -use crate::dynamic_data::models::battle::Battle; -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::static_data::MoveTarget; -use num_traits::abs; use std::ops::Deref; use std::sync::Arc; +use num_traits::abs; + +use crate::dynamic_data::Battle; +use crate::dynamic_data::Pokemon; +use crate::static_data::MoveTarget; + +/// Helper type for the vector of targets we will return. pub type TargetList<'own, 'library> = Vec>>>; +/// This returns all Pokemon in the battle. fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> { let mut v = Vec::with_capacity(battle.pokemon_per_side() as usize * battle.number_of_sides() as usize); for side in battle.sides() { @@ -17,6 +21,7 @@ fn get_all_targets<'b, 'library>(battle: &Battle<'b, 'library>) -> TargetList<'b v } +/// Little helper function to get the other side. 1 --> 0, 0 --> 1 fn get_opposite_side(side: u8) -> u8 { if side == 0 { return 1; @@ -24,7 +29,13 @@ fn get_opposite_side(side: u8) -> u8 { 0 } -fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> { +/// Gets all Pokemon that are adjacent to of directly opposite of a Pokemon. This means the target, +/// the Pokemon left of it, the Pokemon right of it, and the Pokemon opposite of it. +fn get_all_adjacent_opponent<'b, 'library>( + side: u8, + index: u8, + battle: &Battle<'b, 'library>, +) -> TargetList<'b, 'library> { let left = index as i32 - 1; let right = index + 1; if left < 0 && right >= battle.pokemon_per_side() { @@ -57,11 +68,9 @@ fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'libr ] } -fn get_all_adjacent_opponent<'b, 'library>( - side: u8, - index: u8, - battle: &Battle<'b, 'library>, -) -> TargetList<'b, 'library> { +/// Gets all Pokemon that are adjacent to a Pokemon. This includes the target, the pokemon to the +/// left of it, and the Pokemon to the right of it. +fn get_all_adjacent<'b, 'library>(side: u8, index: u8, battle: &Battle<'b, 'library>) -> TargetList<'b, 'library> { let left = index as i32 - 1; let right = index + 1; if left < 0 && right >= battle.pokemon_per_side() { @@ -86,6 +95,7 @@ fn get_all_adjacent_opponent<'b, 'library>( ] } +/// Gets the target for a specific move target type, given the targeted position. pub fn resolve_targets<'b, 'library>( side: u8, index: u8, @@ -93,6 +103,8 @@ pub fn resolve_targets<'b, 'library>( battle: &Battle<'b, 'library>, ) -> TargetList<'b, 'library> { match target { + // These all resolve to a single position. We let the client deal with where the target is, + // and just return the Pokemon at that given target here. MoveTarget::Adjacent | MoveTarget::AdjacentAlly | MoveTarget::AdjacentAllySelf @@ -102,9 +114,14 @@ pub fn resolve_targets<'b, 'library>( | MoveTarget::SelfUse => { vec![battle.get_pokemon(side, index).as_ref().cloned()] } + // If all pokemon are requested, give all Pokemon on the battlefield MoveTarget::All => get_all_targets(battle), + // If the adjacent Pokemon are requested, pass those. MoveTarget::AllAdjacent => get_all_adjacent(side, index, battle), + // If the adjacent and opponent Pokemon are requested, give those. MoveTarget::AllAdjacentOpponent => get_all_adjacent_opponent(side, index, battle), + // If all Pokemon on a side are requested, simply give all Pokemon on the side back, and let + // the client deal with what side is passed. MoveTarget::AllAlly | MoveTarget::AllOpponent => { let mut v = Vec::new(); for pokemon in battle.sides()[side as usize].pokemon().deref() { @@ -115,6 +132,7 @@ pub fn resolve_targets<'b, 'library>( } } +/// Checks whether a given side and index are valid for a given movetarget and user. pub fn is_valid_target(side: u8, index: u8, target: MoveTarget, user: &Pokemon) -> bool { let user_side = user.get_battle_side_index(); let user_index = user.get_battle_index(); diff --git a/src/dynamic_data/flow/turn_runner.rs b/src/dynamic_data/flow/turn_runner.rs index f495769..4d6470e 100644 --- a/src/dynamic_data/flow/turn_runner.rs +++ b/src/dynamic_data/flow/turn_runner.rs @@ -1,17 +1,19 @@ -use crate::dynamic_data::choices::TurnChoice; -use crate::dynamic_data::event_hooks::event_hook::Event; -use crate::dynamic_data::flow::target_resolver::resolve_targets; -use crate::dynamic_data::models::battle::Battle; -use crate::dynamic_data::models::damage_source::DamageSource; -use crate::dynamic_data::models::executing_move::ExecutingMove; -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::dynamic_data::script_handling::{ScriptSource, ScriptWrapper}; -use crate::static_data::{DataLibrary, MoveCategory}; -use crate::{run_scripts, script_hook, PkmnResult}; use std::ops::Deref; use std::sync::Arc; +use crate::dynamic_data::choices::TurnChoice; +use crate::dynamic_data::event_hooks::Event; +use crate::dynamic_data::flow::target_resolver::resolve_targets; +use crate::dynamic_data::script_handling::{ScriptSource, ScriptWrapper}; +use crate::dynamic_data::Battle; +use crate::dynamic_data::DamageSource; +use crate::dynamic_data::ExecutingMove; +use crate::dynamic_data::Pokemon; +use crate::static_data::{DataLibrary, MoveCategory}; +use crate::{run_scripts, script_hook, PkmnResult}; + impl<'own, 'library> Battle<'own, 'library> { + /// Execute the entire turn after the choices are all set. pub(crate) fn run_turn(&self) -> PkmnResult<()> { let choice_queue = self.current_turn_queue(); @@ -60,20 +62,19 @@ impl<'own, 'library> Battle<'own, 'library> { } fn execute_choice(&self, choice: &TurnChoice<'own, 'library>) -> PkmnResult<()> { + // A pass turn choice means the user does not intend to do anything. As such, return. if let TurnChoice::Pass(..) = choice { return Ok(()); } if self.has_ended() { return Ok(()); } - { - let user = choice.user(); - if !user.is_usable() { - return Ok(()); - } - if !user.is_on_battlefield() { - return Ok(()); - } + let user = choice.user(); + if !user.is_usable() { + return Ok(()); + } + if !user.is_on_battlefield() { + return Ok(()); } if !self.can_use(choice) { return Ok(()); diff --git a/src/dynamic_data/history/history_holder.rs b/src/dynamic_data/history/history_holder.rs deleted file mode 100644 index 897ce34..0000000 --- a/src/dynamic_data/history/history_holder.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[derive(Debug)] -pub struct HistoryHolder {} diff --git a/src/dynamic_data/history/mod.rs b/src/dynamic_data/history/mod.rs index 702aa8f..7ef0549 100644 --- a/src/dynamic_data/history/mod.rs +++ b/src/dynamic_data/history/mod.rs @@ -1 +1,3 @@ -pub mod history_holder; +/// The history holder holds all specific history events that happened in the battle. +#[derive(Debug)] +pub struct HistoryHolder {} diff --git a/src/dynamic_data/libraries/battle_stat_calculator.rs b/src/dynamic_data/libraries/battle_stat_calculator.rs index b83ce47..804d72b 100644 --- a/src/dynamic_data/libraries/battle_stat_calculator.rs +++ b/src/dynamic_data/libraries/battle_stat_calculator.rs @@ -1,63 +1,28 @@ -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::static_data::statistic_set::StatisticSet; -use crate::static_data::statistics::Statistic; +use std::fmt::Debug; use std::sync::atomic::AtomicU32; +use crate::dynamic_data::Pokemon; +use crate::static_data::Statistic; +use crate::static_data::StatisticSet; + +/// A battle stat calculator is used to calculate stats for a pokemon. +pub trait BattleStatCalculator: Debug { + /// Calculate all the flat stats of a Pokemon, disregarding stat boosts. + fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet); + /// Calculate a single flat stat of a Pokemon, disregarding stat boost + fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32; + /// Calculate all the boosted stats of a pokemon, including stat boosts. + fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet); + /// Calculate a single boosted stat of a Pokemon, including stat boosts. + fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32; +} + +/// A basic implementation of the Gen 7 stat calculator. #[derive(Debug)] -pub struct BattleStatCalculator {} - -impl BattleStatCalculator { - pub fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet) { - stats.set_stat(Statistic::HP, self.calculate_health_stat(pokemon)); - stats.set_stat(Statistic::Attack, self.calculate_other_stat(pokemon, Statistic::Attack)); - stats.set_stat( - Statistic::Defense, - self.calculate_other_stat(pokemon, Statistic::Defense), - ); - stats.set_stat( - Statistic::SpecialAttack, - self.calculate_other_stat(pokemon, Statistic::SpecialAttack), - ); - stats.set_stat( - Statistic::SpecialDefense, - self.calculate_other_stat(pokemon, Statistic::SpecialDefense), - ); - stats.set_stat(Statistic::Speed, self.calculate_other_stat(pokemon, Statistic::Speed)); - } - - pub fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 { - if stat == Statistic::HP { - self.calculate_health_stat(pokemon) - } else { - self.calculate_other_stat(pokemon, stat) - } - } - - pub fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet) { - stats.set_stat(Statistic::HP, self.calculate_boosted_stat(pokemon, Statistic::HP)); - stats.set_stat( - Statistic::Attack, - self.calculate_boosted_stat(pokemon, Statistic::Attack), - ); - stats.set_stat( - Statistic::Defense, - self.calculate_boosted_stat(pokemon, Statistic::Defense), - ); - stats.set_stat( - Statistic::SpecialAttack, - self.calculate_boosted_stat(pokemon, Statistic::SpecialAttack), - ); - stats.set_stat( - Statistic::SpecialDefense, - self.calculate_boosted_stat(pokemon, Statistic::SpecialDefense), - ); - stats.set_stat(Statistic::Speed, self.calculate_boosted_stat(pokemon, Statistic::Speed)); - } - - pub fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 { - (self.calculate_flat_stat(pokemon, stat) as f32 * self.get_stat_boost_modifier(pokemon, stat)) as u32 - } +pub struct Gen7BattleStatCalculator {} +impl Gen7BattleStatCalculator { + /// The calculation used for health points. fn calculate_health_stat(&self, pokemon: &Pokemon) -> u32 { let base = pokemon.form().get_base_stat(Statistic::HP) as u32; let iv = pokemon.individual_values().hp() as u32; @@ -66,6 +31,7 @@ impl BattleStatCalculator { (((2 * base + iv + (ev / 4)) * level) / 100) + level + 10 } + /// The calculation used for all other stats fn calculate_other_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 { let base = pokemon.form().get_base_stat(stat) as u32; let iv = pokemon.individual_values().get_stat(stat) as u32; @@ -75,6 +41,7 @@ impl BattleStatCalculator { return (unmodified as f32 * pokemon.nature().get_stat_modifier(stat)) as u32; } + /// This functions returns the modifier we need to do to a stat for a given stat boost. fn get_stat_boost_modifier(&self, pokemon: &Pokemon, stat: Statistic) -> f32 { let boost = pokemon.stat_boost().get_stat(stat); match boost { @@ -95,3 +62,56 @@ impl BattleStatCalculator { } } } + +impl BattleStatCalculator for Gen7BattleStatCalculator { + fn calculate_flat_stats(&self, pokemon: &Pokemon, stats: &StatisticSet) { + stats.set_stat(Statistic::HP, self.calculate_health_stat(pokemon)); + stats.set_stat(Statistic::Attack, self.calculate_other_stat(pokemon, Statistic::Attack)); + stats.set_stat( + Statistic::Defense, + self.calculate_other_stat(pokemon, Statistic::Defense), + ); + stats.set_stat( + Statistic::SpecialAttack, + self.calculate_other_stat(pokemon, Statistic::SpecialAttack), + ); + stats.set_stat( + Statistic::SpecialDefense, + self.calculate_other_stat(pokemon, Statistic::SpecialDefense), + ); + stats.set_stat(Statistic::Speed, self.calculate_other_stat(pokemon, Statistic::Speed)); + } + + fn calculate_flat_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 { + if stat == Statistic::HP { + self.calculate_health_stat(pokemon) + } else { + self.calculate_other_stat(pokemon, stat) + } + } + + fn calculate_boosted_stats(&self, pokemon: &Pokemon, stats: &StatisticSet) { + stats.set_stat(Statistic::HP, self.calculate_boosted_stat(pokemon, Statistic::HP)); + stats.set_stat( + Statistic::Attack, + self.calculate_boosted_stat(pokemon, Statistic::Attack), + ); + stats.set_stat( + Statistic::Defense, + self.calculate_boosted_stat(pokemon, Statistic::Defense), + ); + stats.set_stat( + Statistic::SpecialAttack, + self.calculate_boosted_stat(pokemon, Statistic::SpecialAttack), + ); + stats.set_stat( + Statistic::SpecialDefense, + self.calculate_boosted_stat(pokemon, Statistic::SpecialDefense), + ); + stats.set_stat(Statistic::Speed, self.calculate_boosted_stat(pokemon, Statistic::Speed)); + } + + fn calculate_boosted_stat(&self, pokemon: &Pokemon, stat: Statistic) -> u32 { + (self.calculate_flat_stat(pokemon, stat) as f32 * self.get_stat_boost_modifier(pokemon, stat)) as u32 + } +} diff --git a/src/dynamic_data/libraries/damage_library.rs b/src/dynamic_data/libraries/damage_library.rs index 86c59b1..f871330 100644 --- a/src/dynamic_data/libraries/damage_library.rs +++ b/src/dynamic_data/libraries/damage_library.rs @@ -1,9 +1,10 @@ -use crate::dynamic_data::models::executing_move::{ExecutingMove, HitData}; -use crate::dynamic_data::models::pokemon::Pokemon; +use std::sync::Arc; + use crate::dynamic_data::script_handling::ScriptSource; +use crate::dynamic_data::Pokemon; +use crate::dynamic_data::{ExecutingMove, HitData}; use crate::script_hook; use crate::static_data::{MoveCategory, Statistic}; -use std::sync::Arc; pub trait DamageLibrary: std::fmt::Debug { fn has_randomness(&self) -> bool; diff --git a/src/dynamic_data/libraries/dynamic_library.rs b/src/dynamic_data/libraries/dynamic_library.rs index b0284d2..62706ba 100644 --- a/src/dynamic_data/libraries/dynamic_library.rs +++ b/src/dynamic_data/libraries/dynamic_library.rs @@ -1,19 +1,20 @@ +use std::ops::Deref; +use std::sync::Arc; + use crate::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator; use crate::dynamic_data::libraries::damage_library::DamageLibrary; use crate::dynamic_data::libraries::misc_library::MiscLibrary; use crate::dynamic_data::libraries::script_resolver::ScriptCategory; -use crate::dynamic_data::script_handling::item_script::ItemScript; -use crate::dynamic_data::script_handling::script::Script; -use crate::static_data::items::item::Item; -use crate::static_data::libraries::static_data::StaticData; +use crate::dynamic_data::ItemScript; +use crate::dynamic_data::Script; +use crate::static_data::Item; +use crate::static_data::StaticData; use crate::{PkmnResult, StringKey}; -use std::ops::Deref; -use std::sync::Arc; #[derive(Debug)] pub struct DynamicLibrary { static_data: StaticData, - stat_calculator: BattleStatCalculator, + stat_calculator: Box, damage_calculator: Box, misc_library: Box>, } @@ -25,7 +26,7 @@ unsafe impl Send for DynamicLibrary {} impl DynamicLibrary { pub fn new( static_data: StaticData, - stat_calculator: BattleStatCalculator, + stat_calculator: Box, damage_calculator: Box, misc_library: Box>, ) -> Self { @@ -40,8 +41,8 @@ impl DynamicLibrary { pub fn static_data(&self) -> &StaticData { &self.static_data } - pub fn stat_calculator(&self) -> &BattleStatCalculator { - &self.stat_calculator + pub fn stat_calculator(&self) -> &dyn BattleStatCalculator { + self.stat_calculator.deref() } pub fn damage_calculator(&self) -> &dyn DamageLibrary { self.damage_calculator.deref() @@ -60,16 +61,15 @@ impl DynamicLibrary { #[cfg(test)] pub mod test { - use crate::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator; + use crate::dynamic_data::libraries::battle_stat_calculator::Gen7BattleStatCalculator; use crate::dynamic_data::libraries::damage_library::Gen7DamageLibrary; use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary; use crate::dynamic_data::libraries::misc_library::Gen7MiscLibrary; - use crate::static_data::libraries::static_data; pub fn build() -> DynamicLibrary { DynamicLibrary { - static_data: static_data::test::build(), - stat_calculator: BattleStatCalculator {}, + static_data: crate::static_data::libraries::static_data::test::build(), + stat_calculator: Box::new(Gen7BattleStatCalculator {}), damage_calculator: Box::new(Gen7DamageLibrary::new(false)), misc_library: Box::new(Gen7MiscLibrary::new()), } diff --git a/src/dynamic_data/libraries/misc_library.rs b/src/dynamic_data/libraries/misc_library.rs index 5f5a4d9..91d14be 100644 --- a/src/dynamic_data/libraries/misc_library.rs +++ b/src/dynamic_data/libraries/misc_library.rs @@ -1,16 +1,18 @@ -use crate::dynamic_data::choices::{MoveChoice, SwitchChoice, TurnChoice}; -use crate::dynamic_data::models::battle::Battle; -use crate::dynamic_data::models::executing_move::ExecutingMove; -use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod}; -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::dynamic_data::script_handling::ScriptSource; -use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect}; -use crate::{script_hook, StringKey}; -use hashbrown::HashSet; -use std::fmt::{Debug, Formatter}; +use std::fmt::Debug; use std::sync::Arc; -pub trait MiscLibrary<'library> { +use hashbrown::HashSet; + +use crate::dynamic_data::choices::{MoveChoice, SwitchChoice, TurnChoice}; +use crate::dynamic_data::script_handling::ScriptSource; +use crate::dynamic_data::Battle; +use crate::dynamic_data::ExecutingMove; +use crate::dynamic_data::Pokemon; +use crate::dynamic_data::{LearnedMove, MoveLearnMethod}; +use crate::static_data::{MoveCategory, MoveData, MoveTarget, SecondaryEffect}; +use crate::{script_hook, StringKey}; + +pub trait MiscLibrary<'library>: Debug { fn is_critical( &self, battle: &Battle, @@ -29,12 +31,6 @@ pub trait MiscLibrary<'library> { // TODO: get time } -impl<'library> Debug for dyn MiscLibrary<'library> { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str("MiscLibrary") - } -} - #[derive(Debug)] pub struct Gen7MiscLibrary<'library> { struggle_data: *const MoveData, diff --git a/src/dynamic_data/libraries/mod.rs b/src/dynamic_data/libraries/mod.rs index 12358c9..bfe5d63 100644 --- a/src/dynamic_data/libraries/mod.rs +++ b/src/dynamic_data/libraries/mod.rs @@ -1,5 +1,16 @@ -pub mod battle_stat_calculator; -pub mod damage_library; -pub mod dynamic_library; -pub mod misc_library; -pub mod script_resolver; +#[doc(inline)] +pub use battle_stat_calculator::*; +#[doc(inline)] +pub use damage_library::*; +#[doc(inline)] +pub use dynamic_library::*; +#[doc(inline)] +pub use misc_library::*; +#[doc(inline)] +pub use script_resolver::*; + +mod battle_stat_calculator; +mod damage_library; +pub(crate) mod dynamic_library; +mod misc_library; +mod script_resolver; diff --git a/src/dynamic_data/mod.rs b/src/dynamic_data/mod.rs index 9a463d1..4ee7666 100644 --- a/src/dynamic_data/mod.rs +++ b/src/dynamic_data/mod.rs @@ -1,7 +1,22 @@ -pub mod choices; -pub mod event_hooks; -pub mod flow; -pub mod history; -pub mod libraries; -pub mod models; -pub mod script_handling; +#[doc(inline)] +pub use choices::*; +#[doc(inline)] +pub use event_hooks::*; +#[doc(inline)] +pub use flow::*; +#[doc(inline)] +pub use history::*; +#[doc(inline)] +pub use libraries::*; +#[doc(inline)] +pub use models::*; +#[doc(inline)] +pub use script_handling::*; + +mod choices; +mod event_hooks; +mod flow; +mod history; +pub(crate) mod libraries; +mod models; +mod script_handling; diff --git a/src/dynamic_data/models/battle.rs b/src/dynamic_data/models/battle.rs index c0d3225..6eb0097 100644 --- a/src/dynamic_data/models/battle.rs +++ b/src/dynamic_data/models/battle.rs @@ -1,24 +1,26 @@ +use std::ops::{Deref, DerefMut}; +use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; +use std::sync::Arc; + +use atomic::Atomic; +use parking_lot::RwLock; + use crate::dynamic_data::choices::TurnChoice; -use crate::dynamic_data::event_hooks::event_hook::{Event, EventHook}; -use crate::dynamic_data::flow::choice_queue::ChoiceQueue; -use crate::dynamic_data::flow::target_resolver::is_valid_target; -use crate::dynamic_data::history::history_holder::HistoryHolder; -use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary; +use crate::dynamic_data::event_hooks::{Event, EventHook}; +use crate::dynamic_data::history::HistoryHolder; +use crate::dynamic_data::is_valid_target; use crate::dynamic_data::models::battle_party::BattleParty; use crate::dynamic_data::models::battle_random::BattleRandom; use crate::dynamic_data::models::battle_result::BattleResult; use crate::dynamic_data::models::battle_side::BattleSide; use crate::dynamic_data::models::pokemon::Pokemon; -use crate::dynamic_data::script_handling::script::Script; -use crate::dynamic_data::script_handling::script_set::ScriptSet; -use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts; -use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; -use crate::{script_hook, PkmnResult, ScriptCategory, StringKey}; -use atomic::Atomic; -use parking_lot::RwLock; -use std::ops::{Deref, DerefMut}; -use std::sync::atomic::{AtomicBool, AtomicU32, Ordering}; -use std::sync::Arc; +use crate::dynamic_data::ChoiceQueue; +use crate::dynamic_data::DynamicLibrary; +use crate::dynamic_data::Script; +use crate::dynamic_data::ScriptSet; +use crate::dynamic_data::VolatileScripts; +use crate::dynamic_data::{ScriptCategory, ScriptSource, ScriptSourceData, ScriptWrapper}; +use crate::{script_hook, PkmnResult, StringKey}; #[derive(Debug)] pub struct Battle<'own, 'library> { diff --git a/src/dynamic_data/models/battle_random.rs b/src/dynamic_data/models/battle_random.rs index b38b84f..e4e0097 100644 --- a/src/dynamic_data/models/battle_random.rs +++ b/src/dynamic_data/models/battle_random.rs @@ -1,10 +1,11 @@ +use std::fmt::{Debug, Formatter}; +use std::sync::{Arc, Mutex}; + use crate::dynamic_data::models::executing_move::ExecutingMove; use crate::dynamic_data::models::pokemon::Pokemon; use crate::dynamic_data::script_handling::ScriptSource; use crate::script_hook; -use crate::utils::random::Random; -use std::fmt::{Debug, Formatter}; -use std::sync::{Arc, Mutex}; +use crate::utils::Random; #[derive(Default)] pub struct BattleRandom { diff --git a/src/dynamic_data/models/battle_side.rs b/src/dynamic_data/models/battle_side.rs index 19b65e9..0f2f347 100644 --- a/src/dynamic_data/models/battle_side.rs +++ b/src/dynamic_data/models/battle_side.rs @@ -1,19 +1,21 @@ -use crate::dynamic_data::choices::TurnChoice; -use crate::dynamic_data::event_hooks::event_hook::Event; -use crate::dynamic_data::models::battle::Battle; -use crate::dynamic_data::models::battle_party::BattleParty; -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::dynamic_data::script_handling::script::Script; -use crate::dynamic_data::script_handling::script_set::ScriptSet; -use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts; -use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; -use crate::{script_hook, PkmnResult, StringKey}; -use parking_lot::lock_api::RwLockReadGuard; -use parking_lot::{RawRwLock, RwLock}; use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use std::sync::Arc; +use parking_lot::lock_api::RwLockReadGuard; +use parking_lot::{RawRwLock, RwLock}; + +use crate::dynamic_data::choices::TurnChoice; +use crate::dynamic_data::event_hooks::Event; +use crate::dynamic_data::models::battle::Battle; +use crate::dynamic_data::models::battle_party::BattleParty; +use crate::dynamic_data::models::pokemon::Pokemon; +use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; +use crate::dynamic_data::Script; +use crate::dynamic_data::ScriptSet; +use crate::dynamic_data::VolatileScripts; +use crate::{script_hook, PkmnResult, StringKey}; + #[derive(Debug)] pub struct BattleSide<'own, 'library> { index: u8, diff --git a/src/dynamic_data/models/executing_move.rs b/src/dynamic_data/models/executing_move.rs index ba7ef8f..4ae7aaf 100644 --- a/src/dynamic_data/models/executing_move.rs +++ b/src/dynamic_data/models/executing_move.rs @@ -1,16 +1,18 @@ -use crate::dynamic_data::flow::target_resolver::TargetList; -use crate::dynamic_data::models::learned_move::LearnedMove; -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::dynamic_data::script_handling::script::ScriptContainer; -use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; -use crate::static_data::MoveData; -use crate::{PkmnResult, PokemonError}; -use atomic::Atomic; -use parking_lot::RwLock; use std::ops::Deref; use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU8, Ordering}; use std::sync::Arc; +use atomic::Atomic; +use parking_lot::RwLock; + +use crate::dynamic_data::models::learned_move::LearnedMove; +use crate::dynamic_data::models::pokemon::Pokemon; +use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; +use crate::dynamic_data::ScriptContainer; +use crate::dynamic_data::TargetList; +use crate::static_data::MoveData; +use crate::{PkmnResult, PokemonError}; + #[derive(Default, Debug)] pub struct HitData { critical: AtomicBool, diff --git a/src/dynamic_data/models/mod.rs b/src/dynamic_data/models/mod.rs index 7ab2e55..3ed3138 100644 --- a/src/dynamic_data/models/mod.rs +++ b/src/dynamic_data/models/mod.rs @@ -1,11 +1,34 @@ -pub mod battle; -pub mod battle_party; -pub mod battle_random; -pub mod battle_result; -pub mod battle_side; -pub mod damage_source; -pub mod executing_move; -pub mod learned_move; -pub mod pokemon; -pub mod pokemon_builder; -pub mod pokemon_party; +#[doc(inline)] +pub use battle::*; +#[doc(inline)] +pub use battle_party::*; +#[doc(inline)] +pub use battle_random::*; +#[doc(inline)] +pub use battle_result::*; +#[doc(inline)] +pub use battle_side::*; +#[doc(inline)] +pub use damage_source::*; +#[doc(inline)] +pub use executing_move::*; +#[doc(inline)] +pub use learned_move::*; +#[doc(inline)] +pub use pokemon::*; +#[doc(inline)] +pub use pokemon_builder::*; +#[doc(inline)] +pub use pokemon_party::*; + +mod battle; +mod battle_party; +mod battle_random; +mod battle_result; +mod battle_side; +mod damage_source; +mod executing_move; +mod learned_move; +mod pokemon; +mod pokemon_builder; +mod pokemon_party; diff --git a/src/dynamic_data/models/pokemon.rs b/src/dynamic_data/models/pokemon.rs index f1d31a2..e73c656 100644 --- a/src/dynamic_data/models/pokemon.rs +++ b/src/dynamic_data/models/pokemon.rs @@ -1,30 +1,29 @@ -use crate::defines::{LevelInt, MAX_MOVES}; -use crate::dynamic_data::event_hooks::event_hook::Event; -use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary; -use crate::dynamic_data::models::battle::Battle; -use crate::dynamic_data::models::damage_source::DamageSource; -use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod}; -use crate::dynamic_data::script_handling::script::{Script, ScriptContainer}; -use crate::dynamic_data::script_handling::script_set::ScriptSet; -use crate::dynamic_data::script_handling::volatile_scripts::VolatileScripts; -use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; -use crate::static_data::items::item::Item; -use crate::static_data::natures::Nature; -use crate::static_data::species_data::ability::Ability; -use crate::static_data::species_data::ability_index::AbilityIndex; -use crate::static_data::species_data::form::Form; -use crate::static_data::species_data::gender::Gender; -use crate::static_data::species_data::species::Species; -use crate::static_data::statistic_set::{ClampedStatisticSet, StatisticSet}; -use crate::static_data::DataLibrary; -use crate::utils::random::Random; -use crate::{script_hook, PkmnResult, ScriptCategory, StringKey}; -use atomic::Atomic; -use parking_lot::RwLock; use std::ops::{Deref, DerefMut}; use std::sync::atomic::{AtomicBool, AtomicI8, AtomicU32, AtomicU8, Ordering}; use std::sync::{Arc, Weak}; +use atomic::Atomic; +use parking_lot::RwLock; + +use crate::defines::{LevelInt, MAX_MOVES}; +use crate::dynamic_data::event_hooks::Event; +use crate::dynamic_data::models::battle::Battle; +use crate::dynamic_data::models::damage_source::DamageSource; +use crate::dynamic_data::models::learned_move::{LearnedMove, MoveLearnMethod}; +use crate::dynamic_data::script_handling::{ScriptSource, ScriptSourceData, ScriptWrapper}; +use crate::dynamic_data::{DynamicLibrary, Script, ScriptCategory, ScriptContainer, ScriptSet, VolatileScripts}; +use crate::static_data::Ability; +use crate::static_data::AbilityIndex; +use crate::static_data::DataLibrary; +use crate::static_data::Form; +use crate::static_data::Gender; +use crate::static_data::Item; +use crate::static_data::Nature; +use crate::static_data::Species; +use crate::static_data::{ClampedStatisticSet, StatisticSet}; +use crate::utils::Random; +use crate::{script_hook, PkmnResult, StringKey}; + #[derive(Debug)] pub struct PokemonBattleData<'pokemon, 'library> { battle: *mut Battle<'pokemon, 'library>, @@ -585,15 +584,15 @@ impl<'own, 'library> VolatileScripts<'own> for Pokemon<'own, 'library> { #[cfg(test)] pub mod test { - use crate::dynamic_data::libraries::dynamic_library; use crate::dynamic_data::models::pokemon::Pokemon; - use crate::static_data::libraries::data_library::DataLibrary; - use crate::static_data::species_data::ability_index::AbilityIndex; - use crate::static_data::species_data::gender::Gender; + use crate::dynamic_data::DynamicLibrary; + use crate::static_data::AbilityIndex; + use crate::static_data::DataLibrary; + use crate::static_data::Gender; #[test] fn construct_pokemon() { - let lib = dynamic_library::test::build(); + let lib = crate::dynamic_data::libraries::dynamic_library::test::build(); let species = lib.static_data().species().get(&"foo".into()).unwrap(); let form = species.get_form(&"default".into()).unwrap(); diff --git a/src/dynamic_data/models/pokemon_builder.rs b/src/dynamic_data/models/pokemon_builder.rs index 1fea05e..4cf399b 100644 --- a/src/dynamic_data/models/pokemon_builder.rs +++ b/src/dynamic_data/models/pokemon_builder.rs @@ -1,7 +1,7 @@ use crate::defines::LevelInt; -use crate::dynamic_data::libraries::dynamic_library::DynamicLibrary; use crate::dynamic_data::models::learned_move::MoveLearnMethod; use crate::dynamic_data::models::pokemon::Pokemon; +use crate::dynamic_data::DynamicLibrary; use crate::static_data::{AbilityIndex, DataLibrary, Gender}; use crate::StringKey; diff --git a/src/dynamic_data/script_handling/mod.rs b/src/dynamic_data/script_handling/mod.rs index ae4608f..5f1687c 100644 --- a/src/dynamic_data/script_handling/mod.rs +++ b/src/dynamic_data/script_handling/mod.rs @@ -1,12 +1,20 @@ -use crate::dynamic_data::script_handling::script::{Script, ScriptContainer}; -use crate::dynamic_data::script_handling::script_set::ScriptSet; -use parking_lot::RwLock; use std::sync::{Arc, Weak}; -pub mod item_script; -pub mod script; -pub mod script_set; -pub mod volatile_scripts; +use parking_lot::RwLock; + +#[doc(inline)] +pub use item_script::*; +#[doc(inline)] +pub use script::*; +#[doc(inline)] +pub use script_set::*; +#[doc(inline)] +pub use volatile_scripts::*; + +mod item_script; +mod script; +mod script_set; +mod volatile_scripts; #[macro_export] macro_rules! script_hook { @@ -25,21 +33,6 @@ macro_rules! script_hook { }; } -#[macro_export] -macro_rules! script_hook_on_lock { - ($hook_name: ident, $source: ident, $($parameters: expr),*) => { - let mut aggregator = $source.read().get_script_iterator(); - while let Some(script) = aggregator.get_next() { - let lock = &mut script.get().read(); - let script = lock.as_mut().unwrap(); - if script.is_suppressed() { - continue; - } - script.$hook_name($($parameters),*); - } - }; -} - #[macro_export] macro_rules! run_scripts { ($hook_name: ident, $source: ident, $($parameters: expr),*) => { @@ -198,12 +191,14 @@ impl ScriptAggregator { #[cfg(test)] mod tests { - use super::*; + use std::any::Any; + use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; + use crate::dynamic_data::script_handling::script::ScriptContainer; use crate::static_data::EffectParameter; use crate::StringKey; - use std::any::Any; - use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; + + use super::*; pub struct TestScript { name: StringKey, diff --git a/src/dynamic_data/script_handling/script.rs b/src/dynamic_data/script_handling/script.rs index 296786f..1b96a2e 100644 --- a/src/dynamic_data/script_handling/script.rs +++ b/src/dynamic_data/script_handling/script.rs @@ -1,12 +1,3 @@ -use crate::dynamic_data::choices::{MoveChoice, TurnChoice}; -use crate::dynamic_data::models::battle::Battle; -use crate::dynamic_data::models::damage_source::DamageSource; -use crate::dynamic_data::models::executing_move::ExecutingMove; -use crate::dynamic_data::models::pokemon::Pokemon; -use crate::static_data::moves::secondary_effect::EffectParameter; -use crate::static_data::{Item, Statistic}; -use crate::StringKey; -use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard}; use std::any::Any; use std::fmt::{Debug, Formatter}; use std::ops::Deref; @@ -14,6 +5,17 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::Arc; use std::thread::JoinHandle; +use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard}; + +use crate::dynamic_data::choices::{MoveChoice, TurnChoice}; +use crate::dynamic_data::Battle; +use crate::dynamic_data::DamageSource; +use crate::dynamic_data::ExecutingMove; +use crate::dynamic_data::Pokemon; +use crate::static_data::EffectParameter; +use crate::static_data::{Item, Statistic}; +use crate::StringKey; + pub trait Script: Send + Sync { fn name(&self) -> &StringKey; fn get_marked_for_deletion(&self) -> &AtomicBool; @@ -231,9 +233,10 @@ impl Clone for ScriptContainer { #[cfg(test)] mod tests { - use super::*; use std::sync::atomic::{AtomicBool, AtomicPtr}; + use super::*; + pub struct TestScript { name: StringKey, container: AtomicPtr, diff --git a/src/lib.rs b/src/lib.rs index a548434..27d6e60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,8 @@ -// The too many arguments is annoying, especially for when we create constructors, disable. +// The too many arguments is annoying, especially for when we create constructor, disable. #![allow(clippy::too_many_arguments, clippy::needless_range_loop)] #![allow(clippy::not_unsafe_ptr_arg_deref)] +#![warn(missing_docs)] +#![warn(clippy::missing_docs_in_private_items)] #![feature(test)] #![feature(bench_black_box)] #![feature(let_chains)] @@ -8,22 +10,45 @@ #![feature(const_option)] #![feature(is_some_with)] +//! PkmnLib +//! PkmnLib is a full featured implementation of Pokemon. while currently focused on implementing +//! generation 7, this library tries to offload generational differences such as move effects +//! to a scripting library. +//! extern crate core; -use crate::dynamic_data::libraries::script_resolver::ScriptCategory; +#[doc(hidden)] +pub use utils::*; +use crate::dynamic_data::ScriptCategory; + +/// The defines module holds the core defines of the library pub mod defines; +/// The dynamic data module holds data that can change during execution, and things that relate to +/// this. This includes things as Pokemon themselves, battles, etc. pub mod dynamic_data; +/// The static data module holds data that can be set once, and then never change. This includes +/// things such as data about Pokemon species, data about items, etc. pub mod static_data; +/// The utils module includes misc utils that are used within PkmnLib pub mod utils; +/// The PokemonError enum holds all different error states that can be encountered in PkmnLib. #[derive(Debug, Clone)] pub enum PokemonError { - ScriptNotFound { category: ScriptCategory, name: String }, - MiscError, + /// A script was requested, but we were unable to find it. + ScriptNotFound { + /// The category of the script we requested, + category: ScriptCategory, + /// The unique key of the requested script. + name: StringKey, + }, + /// We requested data for a specific target, but that target does not exist on the battle field. InvalidTargetRequested, + + /// Misc errors. Use of this should be minimized, but it is useful for early development. + MiscError, } +/// A simple result type. pub type PkmnResult = Result; - -pub use utils::*; diff --git a/src/static_data/growth_rates/lookup_growth_rate.rs b/src/static_data/growth_rates.rs similarity index 84% rename from src/static_data/growth_rates/lookup_growth_rate.rs rename to src/static_data/growth_rates.rs index bcfdb3f..bb00821 100644 --- a/src/static_data/growth_rates/lookup_growth_rate.rs +++ b/src/static_data/growth_rates.rs @@ -1,5 +1,9 @@ use crate::defines::LevelInt; -use crate::static_data::growth_rates::growth_rate::GrowthRate; + +pub trait GrowthRate { + fn calculate_level(&self, experience: u32) -> LevelInt; + fn calculate_experience(&self, level: LevelInt) -> u32; +} pub struct LookupGrowthRate { experience: Vec, diff --git a/src/static_data/growth_rates/growth_rate.rs b/src/static_data/growth_rates/growth_rate.rs deleted file mode 100644 index 72255b8..0000000 --- a/src/static_data/growth_rates/growth_rate.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::defines::LevelInt; - -pub trait GrowthRate { - fn calculate_level(&self, experience: u32) -> LevelInt; - fn calculate_experience(&self, level: LevelInt) -> u32; -} diff --git a/src/static_data/growth_rates/mod.rs b/src/static_data/growth_rates/mod.rs deleted file mode 100644 index 826805b..0000000 --- a/src/static_data/growth_rates/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod growth_rate; -pub mod lookup_growth_rate; - -pub use growth_rate::*; -pub use lookup_growth_rate::*; diff --git a/src/static_data/items/item.rs b/src/static_data/items.rs similarity index 66% rename from src/static_data/items/item.rs rename to src/static_data/items.rs index 5441267..8d40053 100644 --- a/src/static_data/items/item.rs +++ b/src/static_data/items.rs @@ -1,6 +1,33 @@ -use super::item_category::{BattleItemCategory, ItemCategory}; -use crate::StringKey; use hashbrown::HashSet; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +use crate::StringKey; + +#[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[repr(u8)] +pub enum ItemCategory { + MiscItem, + Pokeball, + Medicine, + Berry, + TMHM, + FormChanger, + KeyItem, + Mail, +} + +#[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[repr(u8)] +pub enum BattleItemCategory { + None, + Healing, + StatusHealing, + Pokeball, + MiscBattleItem, +} #[derive(Debug)] pub struct Item { diff --git a/src/static_data/items/item_category.rs b/src/static_data/items/item_category.rs deleted file mode 100644 index ae4b363..0000000 --- a/src/static_data/items/item_category.rs +++ /dev/null @@ -1,27 +0,0 @@ -#[cfg(feature = "serde")] -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Copy, Clone)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[repr(u8)] -pub enum ItemCategory { - MiscItem, - Pokeball, - Medicine, - Berry, - TMHM, - FormChanger, - KeyItem, - Mail, -} - -#[derive(Debug, Copy, Clone)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[repr(u8)] -pub enum BattleItemCategory { - None, - Healing, - StatusHealing, - Pokeball, - MiscBattleItem, -} diff --git a/src/static_data/items/mod.rs b/src/static_data/items/mod.rs deleted file mode 100644 index bf55abd..0000000 --- a/src/static_data/items/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod item; -pub mod item_category; - -pub use item::*; -pub use item_category::*; diff --git a/src/static_data/libraries/ability_library.rs b/src/static_data/libraries/ability_library.rs index bc33754..a478d12 100644 --- a/src/static_data/libraries/ability_library.rs +++ b/src/static_data/libraries/ability_library.rs @@ -1,7 +1,8 @@ +use hashbrown::HashMap; + use crate::static_data::Ability; use crate::static_data::DataLibrary; use crate::StringKey; -use hashbrown::HashMap; #[derive(Debug)] pub struct AbilityLibrary { @@ -34,9 +35,9 @@ impl DataLibrary<'_, Box> for AbilityLibrary { #[cfg(test)] pub mod tests { - use crate::static_data::libraries::ability_library::AbilityLibrary; - use crate::static_data::libraries::data_library::DataLibrary; - use crate::static_data::species_data::ability::Ability; + use crate::static_data::Ability; + use crate::static_data::AbilityLibrary; + use crate::static_data::DataLibrary; use crate::StringKey; pub fn build() -> AbilityLibrary { diff --git a/src/static_data/libraries/growth_rate_library.rs b/src/static_data/libraries/growth_rate_library.rs index b198878..78892f5 100644 --- a/src/static_data/libraries/growth_rate_library.rs +++ b/src/static_data/libraries/growth_rate_library.rs @@ -1,9 +1,11 @@ +use std::fmt; +use std::fmt::{Debug, Formatter}; + +use hashbrown::HashMap; + use crate::defines::LevelInt; use crate::static_data::GrowthRate; use crate::StringKey; -use hashbrown::HashMap; -use std::fmt; -use std::fmt::{Debug, Formatter}; pub struct GrowthRateLibrary { growth_rates: HashMap>, @@ -35,7 +37,7 @@ impl Debug for GrowthRateLibrary { #[cfg(test)] pub mod tests { - use crate::static_data::growth_rates::lookup_growth_rate::LookupGrowthRate; + use crate::static_data::growth_rates::LookupGrowthRate; use crate::static_data::libraries::growth_rate_library::GrowthRateLibrary; pub fn build() -> GrowthRateLibrary { diff --git a/src/static_data/libraries/item_library.rs b/src/static_data/libraries/item_library.rs index 318df44..1ba525b 100644 --- a/src/static_data/libraries/item_library.rs +++ b/src/static_data/libraries/item_library.rs @@ -1,7 +1,8 @@ +use hashbrown::HashMap; + use crate::static_data::DataLibrary; use crate::static_data::Item; use crate::StringKey; -use hashbrown::HashMap; #[derive(Debug)] pub struct ItemLibrary { @@ -34,11 +35,12 @@ impl DataLibrary<'_, Box> for ItemLibrary { #[cfg(test)] pub mod tests { - use crate::static_data::items::item::Item; - use crate::static_data::items::item_category::{BattleItemCategory, ItemCategory}; + use hashbrown::HashSet; + use crate::static_data::libraries::data_library::DataLibrary; use crate::static_data::libraries::item_library::ItemLibrary; - use hashbrown::HashSet; + use crate::static_data::Item; + use crate::static_data::{BattleItemCategory, ItemCategory}; fn build_item() -> Item { Item::new( diff --git a/src/static_data/libraries/mod.rs b/src/static_data/libraries/mod.rs index cfcd326..8af13e4 100644 --- a/src/static_data/libraries/mod.rs +++ b/src/static_data/libraries/mod.rs @@ -1,19 +1,28 @@ -pub mod ability_library; -pub mod data_library; -pub mod growth_rate_library; -pub mod item_library; -pub mod library_settings; -pub mod move_library; -pub mod species_library; -pub mod static_data; -pub mod type_library; - +#[doc(inline)] pub use ability_library::AbilityLibrary; +#[doc(inline)] pub use data_library::DataLibrary; +#[doc(inline)] pub use growth_rate_library::GrowthRateLibrary; +#[doc(inline)] pub use item_library::ItemLibrary; +#[doc(inline)] pub use library_settings::LibrarySettings; +#[doc(inline)] pub use move_library::MoveLibrary; +#[doc(inline)] pub use species_library::SpeciesLibrary; +#[doc(inline)] pub use static_data::StaticData; +#[doc(inline)] pub use type_library::TypeLibrary; + +mod ability_library; +mod data_library; +mod growth_rate_library; +mod item_library; +mod library_settings; +mod move_library; +mod species_library; +pub(crate) mod static_data; +mod type_library; diff --git a/src/static_data/libraries/move_library.rs b/src/static_data/libraries/move_library.rs index 6b91ede..31ce402 100644 --- a/src/static_data/libraries/move_library.rs +++ b/src/static_data/libraries/move_library.rs @@ -1,7 +1,8 @@ +use hashbrown::HashMap; + use crate::static_data::DataLibrary; use crate::static_data::MoveData; use crate::StringKey; -use hashbrown::HashMap; #[derive(Debug)] pub struct MoveLibrary { @@ -34,11 +35,12 @@ impl DataLibrary<'_, MoveData> for MoveLibrary { #[cfg(test)] pub mod tests { + use hashbrown::HashSet; + use crate::static_data::libraries::data_library::DataLibrary; use crate::static_data::libraries::move_library::MoveLibrary; - use crate::static_data::moves::move_data::{MoveCategory, MoveData, MoveTarget}; + use crate::static_data::{MoveCategory, MoveData, MoveTarget}; use crate::StringKey; - use hashbrown::HashSet; fn build_move() -> MoveData { MoveData::new( diff --git a/src/static_data/libraries/species_library.rs b/src/static_data/libraries/species_library.rs index 1661925..5877af3 100644 --- a/src/static_data/libraries/species_library.rs +++ b/src/static_data/libraries/species_library.rs @@ -1,7 +1,8 @@ +use hashbrown::HashMap; + use crate::static_data::DataLibrary; use crate::static_data::Species; use crate::StringKey; -use hashbrown::HashMap; #[derive(Debug)] pub struct SpeciesLibrary { @@ -34,13 +35,14 @@ impl<'a> DataLibrary<'a, Box> for SpeciesLibrary { #[cfg(test)] pub mod tests { + use hashbrown::HashSet; + use crate::static_data::libraries::data_library::DataLibrary; use crate::static_data::libraries::species_library::SpeciesLibrary; - use crate::static_data::species_data::form::Form; - use crate::static_data::species_data::learnable_moves::LearnableMoves; - use crate::static_data::species_data::species::Species; + use crate::static_data::Form; + use crate::static_data::LearnableMoves; + use crate::static_data::Species; use crate::static_data::StaticStatisticSet; - use hashbrown::HashSet; fn build_species() -> Species { Species::new( diff --git a/src/static_data/mod.rs b/src/static_data/mod.rs index b709d16..e008548 100644 --- a/src/static_data/mod.rs +++ b/src/static_data/mod.rs @@ -1,17 +1,25 @@ -pub mod growth_rates; -pub mod items; -pub mod libraries; -pub mod moves; -pub mod natures; -pub mod species_data; -pub mod statistic_set; -pub mod statistics; - +#[doc(inline)] pub use growth_rates::*; +#[doc(inline)] pub use items::*; +#[doc(inline)] pub use libraries::*; +#[doc(inline)] pub use moves::*; +#[doc(inline)] pub use natures::*; +#[doc(inline)] pub use species_data::*; +#[doc(inline)] pub use statistic_set::*; +#[doc(inline)] pub use statistics::*; + +mod growth_rates; +mod items; +pub(crate) mod libraries; +mod moves; +mod natures; +mod species_data; +mod statistic_set; +mod statistics; diff --git a/src/static_data/moves/mod.rs b/src/static_data/moves/mod.rs index 09ae473..1a138e3 100644 --- a/src/static_data/moves/mod.rs +++ b/src/static_data/moves/mod.rs @@ -1,9 +1,7 @@ -pub mod move_data; -pub mod secondary_effect; +#[doc(inline)] +pub use move_data::*; +#[doc(inline)] +pub use secondary_effect::*; -pub use move_data::MoveCategory; -pub use move_data::MoveData; -pub use move_data::MoveTarget; - -pub use secondary_effect::EffectParameter; -pub use secondary_effect::SecondaryEffect; +mod move_data; +mod secondary_effect; diff --git a/src/static_data/species_data/mod.rs b/src/static_data/species_data/mod.rs index e215544..564ddd5 100644 --- a/src/static_data/species_data/mod.rs +++ b/src/static_data/species_data/mod.rs @@ -1,13 +1,19 @@ -pub mod ability; -pub mod ability_index; -pub mod form; -pub mod gender; -pub mod learnable_moves; -pub mod species; - +#[doc(inline)] pub use ability::Ability; +#[doc(inline)] pub use ability_index::AbilityIndex; +#[doc(inline)] pub use form::Form; +#[doc(inline)] pub use gender::Gender; +#[doc(inline)] pub use learnable_moves::LearnableMoves; +#[doc(inline)] pub use species::Species; + +mod ability; +mod ability_index; +mod form; +mod gender; +mod learnable_moves; +mod species; diff --git a/src/static_data/statistic_set.rs b/src/static_data/statistic_set.rs index 74da68c..f71af37 100644 --- a/src/static_data/statistic_set.rs +++ b/src/static_data/statistic_set.rs @@ -1,18 +1,30 @@ -use super::statistics::Statistic; -use atomic_prim_traits::AtomicInt; -use num_traits::{clamp, NumCast, PrimInt}; use std::sync::atomic::Ordering; +use atomic_prim_traits::AtomicInt; +use num_traits::{clamp, NumCast, PrimInt}; + +use super::statistics::Statistic; + +/// A collection of every individual stat. This set can hold any value that is valid for its integer +/// type, and can be modified at will. +/// +/// As all data in this type is atomic, threaded access to this struct is completely legal. #[derive(Default, Eq, PartialEq, Clone, Debug)] pub struct StatisticSet where T: AtomicInt, { + /// The health point stat value. hp: T, + /// The physical attack stat value. attack: T, + /// The physical defense stat value. defense: T, + /// The special attack stat value. special_attack: T, + /// The special defense stat value. special_defense: T, + /// The speed stat value. speed: T, } @@ -20,6 +32,7 @@ impl StatisticSet where T: AtomicInt, { + /// Creates a new statistic set with given stats. pub fn new( hp: T::Prim, attack: T::Prim, @@ -38,25 +51,32 @@ where } } + /// The health point stat value. pub fn hp(&self) -> T::Prim { self.hp.load(Ordering::Relaxed) } + /// The physical attack stat value. pub fn attack(&self) -> T::Prim { self.attack.load(Ordering::Relaxed) } + /// The physical defense stat value. pub fn defense(&self) -> T::Prim { self.defense.load(Ordering::Relaxed) } + /// The special attack stat value. pub fn special_attack(&self) -> T::Prim { self.special_attack.load(Ordering::Relaxed) } + /// The special defense stat value. pub fn special_defense(&self) -> T::Prim { self.special_defense.load(Ordering::Relaxed) } + /// The speed stat value. pub fn speed(&self) -> T::Prim { self.speed.load(Ordering::Relaxed) } + /// Get the value of a specific stat pub fn get_stat(&self, stat: Statistic) -> T::Prim { match stat { Statistic::HP => self.hp.load(Ordering::Relaxed), @@ -68,6 +88,7 @@ where } } + /// Modify the value of a specific stat. pub fn set_stat(&self, stat: Statistic, value: T::Prim) { match stat { Statistic::HP => self.hp.store(value, Ordering::SeqCst), @@ -79,6 +100,7 @@ where } } + /// Increase the value of a given stat by a value. pub fn increase_stat(&self, stat: Statistic, value: T::Prim) { match stat { Statistic::HP => self.hp.fetch_add(value, Ordering::SeqCst), @@ -90,6 +112,7 @@ where }; } + /// Decrease the value of a given stat by a value. pub fn decrease_stat(&self, stat: Statistic, value: T::Prim) { match stat { Statistic::HP => self.hp.fetch_sub(value, Ordering::SeqCst), @@ -102,16 +125,25 @@ where } } +/// A collection of statistics that can not be modified after creation. +/// +/// As no modifications happen, this struct does not use atomics. #[derive(Default, Eq, PartialEq, Clone, Debug)] pub struct StaticStatisticSet where T: PrimInt, { + /// The health point stat value. hp: T, + /// The physical attack stat value. attack: T, + /// The physical defense stat value. defense: T, + /// The special attack stat value. special_attack: T, + /// The special defense stat value. special_defense: T, + /// The speed stat value. speed: T, } @@ -119,6 +151,7 @@ impl StaticStatisticSet where T: PrimInt, { + /// Create a new static statistic set. pub const fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self { Self { hp, @@ -130,25 +163,32 @@ where } } + /// The health point stat value.= pub const fn hp(&self) -> T { self.hp } + /// The physical attack stat value. pub const fn attack(&self) -> T { self.attack } + /// The physical defense stat value. pub const fn defense(&self) -> T { self.defense } + /// The special attack stat value. pub const fn special_attack(&self) -> T { self.special_attack } + /// The special defense stat value. pub const fn special_defense(&self) -> T { self.special_defense } + /// The speed stat value. pub const fn speed(&self) -> T { self.speed } + /// Get the value of a specific stat pub const fn get_stat(&self, stat: Statistic) -> T { match stat { Statistic::HP => self.hp, @@ -166,14 +206,22 @@ pub struct ClampedStatisticSet where T: AtomicInt, { + /// The health point stat value. hp: T, + /// The physical attack stat value. attack: T, + /// The physical defense stat value. defense: T, + /// The special attack stat value. special_attack: T, + /// The special defense stat value. special_defense: T, + /// The speed stat value. speed: T, } +/// A clamped statistic set is a collection of each statistics that can be modified, but that will +/// always remain between two compile time constant values (Min, Max). impl ClampedStatisticSet where T: AtomicInt, @@ -302,9 +350,10 @@ where #[cfg(test)] mod tests { - use super::*; use std::sync::atomic::AtomicI32; + use super::*; + #[test] fn create_get_values() { let set = StatisticSet::::new(1, 2, 3, 4, 5, 6); diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d8e60a6..bf7721a 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,5 +1,7 @@ -pub mod random; -pub mod string_key; - +#[doc(inline)] pub use random::Random; +#[doc(inline)] pub use string_key::StringKey; + +mod random; +mod string_key; diff --git a/tests/common/data_getter.rs b/tests/common/data_getter.rs index 82809bc..67c6f7c 100644 --- a/tests/common/data_getter.rs +++ b/tests/common/data_getter.rs @@ -1,6 +1,7 @@ -use pkmn_lib::dynamic_data::models::battle::Battle; use serde::Deserialize; +use pkmn_lib::dynamic_data::Battle; + #[derive(Deserialize)] #[serde(rename_all = "snake_case")] pub enum TestDataGetter { diff --git a/tests/common/library_loader.rs b/tests/common/library_loader.rs index d3f8649..5309512 100644 --- a/tests/common/library_loader.rs +++ b/tests/common/library_loader.rs @@ -1,22 +1,24 @@ +use std::convert::TryFrom; +use std::fmt::Debug; +use std::fs::File; +use std::io::Read; + use hashbrown::HashSet; use num_traits::PrimInt; +use project_root::get_project_root; +use serde_json::Value; + use pkmn_lib::defines::LevelInt; -use pkmn_lib::dynamic_data::libraries::battle_stat_calculator::BattleStatCalculator; -use pkmn_lib::dynamic_data::libraries::damage_library::Gen7DamageLibrary; -use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary; -use pkmn_lib::dynamic_data::libraries::misc_library::Gen7MiscLibrary; +use pkmn_lib::dynamic_data::DynamicLibrary; +use pkmn_lib::dynamic_data::Gen7BattleStatCalculator; +use pkmn_lib::dynamic_data::Gen7DamageLibrary; +use pkmn_lib::dynamic_data::Gen7MiscLibrary; use pkmn_lib::static_data::{ Ability, AbilityLibrary, BattleItemCategory, DataLibrary, EffectParameter, Form, GrowthRateLibrary, Item, ItemLibrary, LearnableMoves, LibrarySettings, LookupGrowthRate, MoveData, MoveLibrary, Nature, NatureLibrary, SecondaryEffect, Species, StaticData, StaticStatisticSet, Statistic, TypeLibrary, }; use pkmn_lib::StringKey; -use project_root::get_project_root; -use serde_json::Value; -use std::convert::TryFrom; -use std::fmt::Debug; -use std::fs::File; -use std::io::Read; pub fn load_library() -> DynamicLibrary { let mut path = get_project_root().unwrap(); @@ -32,7 +34,7 @@ pub fn load_library() -> DynamicLibrary { load_species(&path, &mut data); let dynamic = DynamicLibrary::new( data, - BattleStatCalculator {}, + Box::new(Gen7BattleStatCalculator {}), Box::new(Gen7DamageLibrary::new(false)), Box::new(Gen7MiscLibrary::new()), ); diff --git a/tests/common/test_case.rs b/tests/common/test_case.rs index 9d88cf1..1ce19a1 100644 --- a/tests/common/test_case.rs +++ b/tests/common/test_case.rs @@ -1,15 +1,18 @@ -use super::test_step::TestStep; -use pkmn_lib::defines::LevelInt; -use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary; -use pkmn_lib::dynamic_data::models::battle::Battle; -use pkmn_lib::dynamic_data::models::battle_party::BattleParty; -use pkmn_lib::dynamic_data::models::pokemon::Pokemon; -use pkmn_lib::dynamic_data::models::pokemon_builder::PokemonBuilder; -use pkmn_lib::dynamic_data::models::pokemon_party::PokemonParty; -use pkmn_lib::StringKey; -use serde::Deserialize; use std::sync::Arc; +use serde::Deserialize; + +use pkmn_lib::defines::LevelInt; +use pkmn_lib::dynamic_data::Battle; +use pkmn_lib::dynamic_data::BattleParty; +use pkmn_lib::dynamic_data::DynamicLibrary; +use pkmn_lib::dynamic_data::Pokemon; +use pkmn_lib::dynamic_data::PokemonBuilder; +use pkmn_lib::dynamic_data::PokemonParty; +use pkmn_lib::StringKey; + +use super::test_step::TestStep; + #[derive(Deserialize)] pub struct TestCase { pub name: String, diff --git a/tests/common/test_step.rs b/tests/common/test_step.rs index 2e5d4d2..82ee85a 100644 --- a/tests/common/test_step.rs +++ b/tests/common/test_step.rs @@ -1,9 +1,11 @@ -use super::data_getter::TestDataGetter; -use pkmn_lib::dynamic_data::choices::{MoveChoice, PassChoice, TurnChoice}; -use pkmn_lib::dynamic_data::models::battle::Battle; -use pkmn_lib::StringKey; use serde::Deserialize; +use pkmn_lib::dynamic_data::Battle; +use pkmn_lib::dynamic_data::{MoveChoice, PassChoice, TurnChoice}; +use pkmn_lib::StringKey; + +use super::data_getter::TestDataGetter; + #[derive(Deserialize)] #[serde(rename_all = "snake_case")] pub enum TestStep { diff --git a/tests/main.rs b/tests/main.rs index cc4498c..9afb94e 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -2,13 +2,15 @@ #![feature(once_cell)] #![test_runner(datatest::runner)] -use crate::common::{library_loader, TestCase}; -use pkmn_lib::dynamic_data::libraries::dynamic_library::DynamicLibrary; use std::fs::File; use std::io::Read; use std::lazy::SyncLazy; use std::path::Path; +use pkmn_lib::dynamic_data::DynamicLibrary; + +use crate::common::{library_loader, TestCase}; + pub mod common; static LIBRARY: SyncLazy = SyncLazy::new(|| {