Complete refactor of the FFI to use handles instead of pointers.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-06-24 14:44:23 +02:00
parent 4c222cb753
commit 78bb91093b
76 changed files with 1510 additions and 1952 deletions

View File

@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use std::any::Any;
use std::fmt::Debug;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
/// An item category defines which bag slot items are stored in.
#[derive(Debug, Copy, Clone)]
@@ -47,7 +47,7 @@ pub enum BattleItemCategory {
}
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner
pub trait Item: ValueIdentifiable + Debug + Any {
pub trait Item: Debug + Any {
/// The name of the item.
fn name(&self) -> &StringKey;
/// Which bag slot items are stored in.
@@ -66,8 +66,6 @@ pub trait Item: ValueIdentifiable + Debug + Any {
/// An item is an object which the player can pick up, keep in their Bag, and use in some manner
#[derive(Debug)]
pub struct ItemImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The name of the item.
name: StringKey,
/// Which bag slot items are stored in.
@@ -90,7 +88,6 @@ impl ItemImpl {
flags: HashSet<StringKey>,
) -> ItemImpl {
ItemImpl {
identifier: Default::default(),
name: name.clone(),
category,
battle_category,
@@ -128,12 +125,6 @@ impl Item for ItemImpl {
}
}
impl ValueIdentifiable for ItemImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
pub(crate) mod tests {
@@ -150,10 +141,5 @@ pub(crate) mod tests {
fn flags(&self) -> &HashSet<StringKey>;
fn has_flag(&self, key: &StringKey) -> bool;
}
impl ValueIdentifiable for Item {
fn value_identifier(&self) -> ValueIdentifier {
ValueIdentifier::new(0)
}
}
}
}

View File

@@ -5,16 +5,14 @@ use indexmap::IndexMap;
use crate::static_data::Ability;
use crate::static_data::DataLibrary;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
/// A storage for all abilities that can be used in this data library.
pub trait AbilityLibrary: DataLibrary<dyn Ability> + ValueIdentifiable + Debug {}
pub trait AbilityLibrary: DataLibrary<dyn Ability> + Debug {}
/// A storage for all abilities that can be used in this data library.
#[derive(Debug)]
pub struct AbilityLibraryImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The underlying map for the library.
map: IndexMap<StringKey, Arc<dyn Ability>>,
}
@@ -23,7 +21,6 @@ impl AbilityLibraryImpl {
/// Instantiates a new ability library.
pub fn new(capacity: usize) -> Self {
Self {
identifier: Default::default(),
map: IndexMap::with_capacity(capacity),
}
}
@@ -40,12 +37,6 @@ impl DataLibrary<dyn Ability> for AbilityLibraryImpl {
}
}
impl ValueIdentifiable for AbilityLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -57,7 +48,7 @@ pub mod tests {
use std::sync::Arc;
pub fn build() -> AbilityLibraryImpl {
let mut lib = AbilityLibraryImpl::new(1);
let lib = AbilityLibraryImpl::new(1);
lib.add(
&StringKey::new("test_ability"),
Arc::new(AbilityImpl::new(

View File

@@ -15,13 +15,17 @@ pub trait DataLibrary<T: ?Sized> {
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<T>>;
/// Adds a new value to the library.
fn add(&mut self, key: &StringKey, value: Arc<T>) {
self.get_modify().insert(key.clone(), value);
fn add(&self, key: &StringKey, value: Arc<T>) {
#[allow(clippy::unwrap_used)] // We know this cant fail.
let self_mut = unsafe { (self as *const Self as *mut Self).as_mut() }.unwrap();
self_mut.get_modify().insert(key.clone(), value);
}
/// Removes a value from the library.
fn remove(&mut self, key: &StringKey) {
self.get_modify().remove(key);
fn remove(&self, key: &StringKey) {
#[allow(clippy::unwrap_used)] // We know this cant fail.
let self_mut = unsafe { (self as *const Self as *mut Self).as_mut() }.unwrap();
self_mut.get_modify().remove(key);
}
/// Gets a value from the library.

View File

@@ -1,37 +1,36 @@
use anyhow::Result;
use std::fmt;
use std::fmt::{Debug, Formatter};
use std::sync::Arc;
use hashbrown::HashMap;
use parking_lot::RwLock;
use crate::defines::LevelInt;
use crate::static_data::GrowthRate;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
/// A library to store all growth rates.
pub trait GrowthRateLibrary: Debug + ValueIdentifiable {
pub trait GrowthRateLibrary: Debug {
/// Calculates the level for a given growth key name and a certain experience.
fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> Result<LevelInt>;
/// Calculates the experience for a given growth key name and a certain level.
fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> Result<u32>;
/// Adds a new growth rate with a name and value.
fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>);
fn add_growth_rate(&self, key: &StringKey, value: Arc<dyn GrowthRate>);
}
/// A library to store all growth rates.
pub struct GrowthRateLibraryImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The underlying data structure.
growth_rates: HashMap<StringKey, Box<dyn GrowthRate>>,
growth_rates: RwLock<HashMap<StringKey, Arc<dyn GrowthRate>>>,
}
impl GrowthRateLibraryImpl {
/// Instantiates a new growth rate library with a capacity.
pub fn new(capacity: usize) -> Self {
Self {
identifier: Default::default(),
growth_rates: HashMap::with_capacity(capacity),
growth_rates: RwLock::new(HashMap::with_capacity(capacity)),
}
}
}
@@ -41,6 +40,7 @@ impl GrowthRateLibrary for GrowthRateLibraryImpl {
fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> Result<LevelInt> {
Ok(self
.growth_rates
.read()
.get(growth_rate)
.ok_or_else(|| anyhow::anyhow!("No growth rate found with key {}", growth_rate.to_string()))?
.calculate_level(experience))
@@ -48,20 +48,15 @@ impl GrowthRateLibrary for GrowthRateLibraryImpl {
/// Calculates the experience for a given growth key name and a certain level.
fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> Result<u32> {
self.growth_rates
.read()
.get(growth_rate)
.ok_or_else(|| anyhow::anyhow!("No growth rate found with key {}", growth_rate.to_string()))?
.calculate_experience(level)
}
/// Adds a new growth rate with a name and value.
fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>) {
self.growth_rates.insert(key.clone(), value);
}
}
impl ValueIdentifiable for GrowthRateLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
fn add_growth_rate(&self, key: &StringKey, value: Arc<dyn GrowthRate>) {
self.growth_rates.write().insert(key.clone(), value);
}
}
@@ -87,7 +82,7 @@ pub mod tests {
let w = &mut lib;
w.add_growth_rate(
&"test_growthrate".into(),
Box::new(LookupGrowthRate::new(vec![0, 5, 10, 100])),
Arc::new(LookupGrowthRate::new(vec![0, 5, 10, 100])),
);
// Drops borrow as mut
@@ -100,12 +95,7 @@ pub mod tests {
impl GrowthRateLibrary for GrowthRateLibrary {
fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> Result<LevelInt>;
fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> Result<u32>;
fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>);
}
impl ValueIdentifiable for GrowthRateLibrary {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
fn add_growth_rate(&self, key: &StringKey, value: Arc<dyn GrowthRate>);
}
}

View File

@@ -5,16 +5,14 @@ use indexmap::IndexMap;
use crate::static_data::DataLibrary;
use crate::static_data::Item;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
/// A library to store all items.
pub trait ItemLibrary: DataLibrary<dyn Item> + ValueIdentifiable + Debug {}
pub trait ItemLibrary: DataLibrary<dyn Item> + Debug {}
/// A library to store all items.
#[derive(Debug)]
pub struct ItemLibraryImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The underlying data structure.
map: IndexMap<StringKey, Arc<dyn Item>>,
}
@@ -23,7 +21,6 @@ impl ItemLibraryImpl {
/// Instantiates a new Item Library.
pub fn new(capacity: usize) -> Self {
Self {
identifier: Default::default(),
map: IndexMap::with_capacity(capacity),
}
}
@@ -41,12 +38,6 @@ impl DataLibrary<dyn Item> for ItemLibraryImpl {
}
}
impl ValueIdentifiable for ItemLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
pub mod tests {
use hashbrown::HashSet;

View File

@@ -1,11 +1,10 @@
use crate::defines::LevelInt;
use crate::{ValueIdentifiable, ValueIdentifier};
use anyhow::Result;
use anyhow_ext::ensure;
use std::fmt::Debug;
/// This library holds several misc settings for the library.
pub trait LibrarySettings: Debug + ValueIdentifiable {
pub trait LibrarySettings: Debug {
/// The highest level a Pokemon can be.
fn maximum_level(&self) -> LevelInt;
@@ -17,8 +16,6 @@ pub trait LibrarySettings: Debug + ValueIdentifiable {
/// This library holds several misc settings for the library.
#[derive(Debug)]
pub struct LibrarySettingsImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The highest level a Pokemon can be.
maximum_level: LevelInt,
/// The chance of a Pokemon being shiny, as the denominator of a fraction, where the nominator
@@ -36,7 +33,6 @@ impl LibrarySettingsImpl {
ensure!(shiny_rate >= 1);
ensure!(maximum_level >= 1);
Ok(Self {
identifier: Default::default(),
maximum_level,
shiny_rate,
})
@@ -51,9 +47,3 @@ impl LibrarySettings for LibrarySettingsImpl {
self.shiny_rate
}
}
impl ValueIdentifiable for LibrarySettingsImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}

View File

@@ -5,16 +5,14 @@ use indexmap::IndexMap;
use crate::static_data::DataLibrary;
use crate::static_data::MoveData;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
/// A library to store all data for moves.
pub trait MoveLibrary: DataLibrary<dyn MoveData> + ValueIdentifiable + Debug {}
pub trait MoveLibrary: DataLibrary<dyn MoveData> + Debug {}
/// A library to store all data for moves.
#[derive(Debug)]
pub struct MoveLibraryImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The underlying map.
map: IndexMap<StringKey, Arc<dyn MoveData>>,
}
@@ -23,7 +21,6 @@ impl MoveLibraryImpl {
/// Instantiates a new Move Library.
pub fn new(capacity: usize) -> Self {
Self {
identifier: Default::default(),
map: IndexMap::with_capacity(capacity),
}
}
@@ -40,12 +37,6 @@ impl DataLibrary<dyn MoveData> for MoveLibraryImpl {
}
}
impl ValueIdentifiable for MoveLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
pub mod tests {
use hashbrown::HashSet;

View File

@@ -1,15 +1,16 @@
use crate::static_data::Nature;
use crate::{Random, StringKey, ValueIdentifiable, ValueIdentifier};
use crate::{Random, StringKey};
use anyhow::bail;
use anyhow_ext::{ensure, Result};
use indexmap::IndexMap;
use parking_lot::RwLock;
use std::fmt::Debug;
use std::sync::Arc;
/// A library of all natures that can be used, stored by their names.
pub trait NatureLibrary: Debug + ValueIdentifiable {
pub trait NatureLibrary: Debug {
/// Adds a new nature with name to the library.
fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>);
fn load_nature(&self, name: StringKey, nature: Arc<dyn Nature>);
/// Gets a nature by name.
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>>;
/// Gets a random nature.
@@ -21,38 +22,35 @@ pub trait NatureLibrary: Debug + ValueIdentifiable {
/// A library of all natures that can be used, stored by their names.
#[derive(Debug)]
pub struct NatureLibraryImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The underlying data structure.
map: IndexMap<StringKey, Arc<dyn Nature>>,
map: RwLock<IndexMap<StringKey, Arc<dyn Nature>>>,
}
impl NatureLibraryImpl {
/// Creates a new nature library with a given capacity.
pub fn new(capacity: usize) -> Self {
Self {
identifier: Default::default(),
map: IndexMap::with_capacity(capacity),
map: RwLock::new(IndexMap::with_capacity(capacity)),
}
}
}
impl NatureLibrary for NatureLibraryImpl {
/// Adds a new nature with name to the library.
fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>) {
self.map.insert(name, nature);
fn load_nature(&self, name: StringKey, nature: Arc<dyn Nature>) {
self.map.write().insert(name, nature);
}
/// Gets a nature by name.
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>> {
self.map.get(key).cloned()
self.map.read().get(key).cloned()
}
fn get_random_nature(&self, rand: &mut Random) -> Result<Arc<dyn Nature>> {
ensure!(!self.map.is_empty(), "No natures were loaded into the library.");
let i = rand.get_between(0, self.map.len() as i32);
Ok(self
.map
let map = self.map.read();
ensure!(!map.is_empty(), "No natures were loaded into the library.");
let i = rand.get_between(0, map.len() as i32);
Ok(map
.get_index(i as usize)
// this should never happen, but we'll check anyway.
.ok_or(anyhow_ext::anyhow!("Failed to get a random nature from the library."))?
@@ -62,10 +60,11 @@ impl NatureLibrary for NatureLibraryImpl {
/// Finds a nature name by nature.
fn get_nature_name(&self, nature: &Arc<dyn Nature>) -> Result<StringKey> {
for kv in &self.map {
let read_lock = self.map.read();
for kv in read_lock.iter() {
// As natures can't be copied, and should always be the same reference as the value
// in the map, we just compare by reference.
if kv.1.value_identifier() == nature.value_identifier() {
if Arc::ptr_eq(&kv.1, nature) {
return Ok(kv.0.clone());
}
}
@@ -73,12 +72,6 @@ impl NatureLibrary for NatureLibraryImpl {
}
}
impl ValueIdentifiable for NatureLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -89,7 +82,7 @@ pub mod tests {
use crate::static_data::{NatureImpl, NatureLibrary, NatureLibraryImpl};
pub fn build() -> NatureLibraryImpl {
let mut lib = NatureLibraryImpl::new(2);
let lib = NatureLibraryImpl::new(2);
lib.load_nature(
"test_nature".into(),
@@ -103,21 +96,16 @@ pub mod tests {
#[derive(Debug)]
pub NatureLibrary{}
impl NatureLibrary for NatureLibrary {
fn load_nature(&mut self, name: StringKey, nature: Arc<dyn Nature>);
fn load_nature(&self, name: StringKey, nature: Arc<dyn Nature>);
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>>;
fn get_nature_name(&self, nature: &Arc<dyn Nature>) -> Result<StringKey>;
fn get_random_nature(&self, rand: &mut Random) -> Result<Arc<dyn Nature>>;
}
impl ValueIdentifiable for NatureLibrary {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
#[test]
fn create_nature_library_insert_and_retrieve() {
let mut lib = NatureLibraryImpl::new(2);
let lib = NatureLibraryImpl::new(2);
lib.load_nature(
"foo".into(),
NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9),
@@ -135,7 +123,7 @@ pub mod tests {
#[test]
fn create_nature_library_insert_and_get_name() {
let mut lib = NatureLibraryImpl::new(2);
let lib = NatureLibraryImpl::new(2);
lib.load_nature(
"foo".into(),
NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9),
@@ -155,7 +143,7 @@ pub mod tests {
#[test]
fn create_nature_library_insert_single_and_retrieve_random() {
let mut lib = NatureLibraryImpl::new(2);
let lib = NatureLibraryImpl::new(2);
lib.load_nature(
"foo".into(),
NatureImpl::new(Statistic::HP, Statistic::Attack, 1.1, 0.9),

View File

@@ -5,16 +5,14 @@ use indexmap::IndexMap;
use crate::static_data::DataLibrary;
use crate::static_data::Species;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
/// A library to store all data for Pokemon species.
pub trait SpeciesLibrary: DataLibrary<dyn Species> + ValueIdentifiable + Debug {}
pub trait SpeciesLibrary: DataLibrary<dyn Species> + Debug {}
/// A library to store all data for Pokemon species.
#[derive(Debug)]
pub struct SpeciesLibraryImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The underlying map.
map: IndexMap<StringKey, Arc<dyn Species>>,
}
@@ -23,7 +21,6 @@ impl SpeciesLibraryImpl {
/// Instantiates a new Species Library.
pub fn new(capacity: usize) -> Self {
Self {
identifier: Default::default(),
map: IndexMap::with_capacity(capacity),
}
}
@@ -40,12 +37,6 @@ impl DataLibrary<dyn Species> for SpeciesLibraryImpl {
}
}
impl ValueIdentifiable for SpeciesLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -65,11 +56,6 @@ pub mod tests {
fn map(&self) -> &IndexMap<StringKey, Arc<dyn Species>>;
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Arc<dyn Species>>;
}
impl ValueIdentifiable for SpeciesLibrary {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
fn build_species() -> Arc<dyn Species> {
@@ -85,10 +71,10 @@ pub mod tests {
0.0,
0,
Vec::new(),
StaticStatisticSet::new(10, 10, 10, 10, 10, 10),
Arc::new(StaticStatisticSet::new(10, 10, 10, 10, 10, 10)),
Vec::new(),
Vec::new(),
Box::new(LearnableMovesImpl::new(100)),
Arc::new(LearnableMovesImpl::new(100)),
HashSet::new(),
)),
HashSet::new(),

View File

@@ -6,12 +6,11 @@ use crate::static_data::MoveLibrary;
use crate::static_data::NatureLibrary;
use crate::static_data::SpeciesLibrary;
use crate::static_data::TypeLibrary;
use crate::{ValueIdentifiable, ValueIdentifier};
use std::fmt::Debug;
use std::sync::Arc;
/// The storage for all different libraries.
pub trait StaticData: Debug + ValueIdentifiable {
pub trait StaticData: Debug {
/// Several misc settings for the library.
fn settings(&self) -> &Arc<dyn LibrarySettings>;
/// All data for Pokemon species.
@@ -34,8 +33,6 @@ pub trait StaticData: Debug + ValueIdentifiable {
/// The storage for all different libraries.
#[derive(Debug)]
pub struct StaticDataImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// Several misc settings for the library.
settings: Arc<dyn LibrarySettings>,
/// All data for Pokemon species.
@@ -67,7 +64,6 @@ impl StaticDataImpl {
abilities: Arc<dyn AbilityLibrary>,
) -> Self {
Self {
identifier: Default::default(),
settings,
species,
moves,
@@ -116,12 +112,6 @@ impl StaticData for StaticDataImpl {
}
}
impl ValueIdentifiable for StaticDataImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -143,16 +133,10 @@ pub mod test {
fn natures(&self) -> &Arc<dyn NatureLibrary>;
fn abilities(&self) -> &Arc<dyn AbilityLibrary>;
}
impl ValueIdentifiable for StaticData {
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
pub fn build() -> StaticDataImpl {
StaticDataImpl {
identifier: Default::default(),
settings: Arc::new(LibrarySettingsImpl::new(100, 100).unwrap()),
species: crate::static_data::libraries::species_library::tests::build(),
moves: crate::static_data::libraries::move_library::tests::build(),

View File

@@ -1,9 +1,10 @@
use anyhow_ext::Result;
use atomig::Atom;
use hashbrown::HashMap;
use parking_lot::{RwLock, RwLockReadGuard};
use std::fmt::{Debug, Display};
use crate::{PkmnError, StringKey, ValueIdentifiable, ValueIdentifier};
use crate::{PkmnError, StringKey};
/// A unique key that can be used to store a reference to a type. Opaque reference to a byte
/// internally.
@@ -33,7 +34,7 @@ impl Display for TypeIdentifier {
}
/// All data related to types and effectiveness.
pub trait TypeLibrary: Debug + ValueIdentifiable {
pub trait TypeLibrary: Debug {
/// Gets the type identifier for a type with a name.
fn get_type_id(&self, key: &StringKey) -> Option<TypeIdentifier>;
@@ -49,48 +50,56 @@ pub trait TypeLibrary: Debug + ValueIdentifiable {
fn get_effectiveness(&self, attacking: TypeIdentifier, defending: &[TypeIdentifier]) -> Result<f32>;
/// Registers a new type in the library.
fn register_type(&mut self, name: &StringKey) -> TypeIdentifier;
fn register_type(&self, name: &StringKey) -> TypeIdentifier;
/// Sets the effectiveness for an attacking type against a defending type.
fn set_effectiveness(
&mut self,
attacking: TypeIdentifier,
defending: TypeIdentifier,
effectiveness: f32,
) -> Result<()>;
fn set_effectiveness(&self, attacking: TypeIdentifier, defending: TypeIdentifier, effectiveness: f32)
-> Result<()>;
}
/// All data related to types and effectiveness.
#[derive(Debug)]
pub struct TypeLibraryImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// A list of types
types: HashMap<StringKey, TypeIdentifier>,
types: RwLock<HashMap<StringKey, TypeIdentifier>>,
/// The effectiveness of the different types against each other.
effectiveness: Vec<Vec<f32>>,
effectiveness: RwLock<Vec<Vec<f32>>>,
}
impl TypeLibraryImpl {
/// Instantiates a new type library with a specific capacity.
pub fn new(capacity: usize) -> Self {
Self {
identifier: Default::default(),
types: HashMap::with_capacity(capacity),
effectiveness: vec![],
types: RwLock::new(HashMap::with_capacity(capacity)),
effectiveness: RwLock::new(vec![]),
}
}
}
impl TypeLibraryImpl {
fn get_single_effectiveness_with_lock(
lock: &RwLockReadGuard<Vec<Vec<f32>>>,
attacking: TypeIdentifier,
defending: TypeIdentifier,
) -> Result<f32> {
Ok(*lock
.get((attacking.val - 1) as usize)
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: attacking })?
.get((defending.val - 1) as usize)
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: defending })?)
}
}
impl TypeLibrary for TypeLibraryImpl {
/// Gets the type identifier for a type with a name.
fn get_type_id(&self, key: &StringKey) -> Option<TypeIdentifier> {
self.types.get(key).cloned()
self.types.read().get(key).cloned()
}
/// Gets the type name from the type identifier.
fn get_type_name(&self, t: TypeIdentifier) -> Option<StringKey> {
for kv in &self.types {
let types = self.types.read();
for kv in types.iter() {
if *kv.1 == t {
return Some(kv.0.clone());
}
@@ -100,12 +109,7 @@ impl TypeLibrary for TypeLibraryImpl {
/// Gets the effectiveness for a single attacking type against a single defending type.
fn get_single_effectiveness(&self, attacking: TypeIdentifier, defending: TypeIdentifier) -> Result<f32> {
Ok(*self
.effectiveness
.get((attacking.val - 1) as usize)
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: attacking })?
.get((defending.val - 1) as usize)
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: defending })?)
Self::get_single_effectiveness_with_lock(&self.effectiveness.read(), attacking, defending)
}
/// Gets the effectiveness for a single attacking type against an amount of defending types.
@@ -113,20 +117,24 @@ impl TypeLibrary for TypeLibraryImpl {
/// multiplying the results with each other.
fn get_effectiveness(&self, attacking: TypeIdentifier, defending: &[TypeIdentifier]) -> Result<f32> {
let mut e = 1.0;
let lock = self.effectiveness.read();
for def in defending {
e *= self.get_single_effectiveness(attacking, *def)?;
e *= Self::get_single_effectiveness_with_lock(&lock, attacking, *def)?;
}
Ok(e)
}
/// Registers a new type in the library.
fn register_type(&mut self, name: &StringKey) -> TypeIdentifier {
fn register_type(&self, name: &StringKey) -> TypeIdentifier {
let mut types_write_lock = self.types.write();
let mut effectiveness_write_lock = self.effectiveness.write();
let id = TypeIdentifier {
val: (self.types.len() + 1) as u8,
val: (types_write_lock.len() + 1) as u8,
};
self.types.insert(name.clone(), id);
self.effectiveness.resize((id.val) as usize, vec![]);
for effectiveness in &mut self.effectiveness {
types_write_lock.insert(name.clone(), id);
effectiveness_write_lock.resize((id.val) as usize, vec![]);
for effectiveness in &mut effectiveness_write_lock.iter_mut() {
effectiveness.resize((id.val) as usize, 1.0)
}
id
@@ -134,13 +142,14 @@ impl TypeLibrary for TypeLibraryImpl {
/// Sets the effectiveness for an attacking type against a defending type.
fn set_effectiveness(
&mut self,
&self,
attacking: TypeIdentifier,
defending: TypeIdentifier,
effectiveness: f32,
) -> Result<()> {
*self
.effectiveness
.write()
.get_mut((attacking.val - 1) as usize)
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: attacking })?
.get_mut((defending.val - 1) as usize)
@@ -149,12 +158,6 @@ impl TypeLibrary for TypeLibraryImpl {
}
}
impl ValueIdentifiable for TypeLibraryImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]

View File

@@ -1,4 +1,4 @@
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
#[doc(inline)]
pub use growth_rates::*;
#[doc(inline)]
@@ -56,57 +56,46 @@ mod statistics;
#[derive(PartialEq, Debug, Clone)]
pub enum EffectParameter {
/// A boolean value.
Bool(ValueIdentifier, bool),
Bool(bool),
/// An integer value. Stored as a 64 bit int to deal with potentially large numbers.
Int(ValueIdentifier, i64),
Int(i64),
/// A float value. Stored as a 32 bit float.
Float(ValueIdentifier, f32),
Float(f32),
/// A string value.
String(ValueIdentifier, StringKey),
String(StringKey),
}
impl From<bool> for EffectParameter {
fn from(b: bool) -> Self {
EffectParameter::Bool(Default::default(), b)
EffectParameter::Bool(b)
}
}
impl From<i64> for EffectParameter {
fn from(i: i64) -> Self {
EffectParameter::Int(Default::default(), i)
EffectParameter::Int(i)
}
}
impl From<f32> for EffectParameter {
fn from(f: f32) -> Self {
EffectParameter::Float(Default::default(), f)
EffectParameter::Float(f)
}
}
impl From<StringKey> for EffectParameter {
fn from(s: StringKey) -> Self {
EffectParameter::String(Default::default(), s)
EffectParameter::String(s)
}
}
impl Display for EffectParameter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
EffectParameter::Bool(_, v) => f.write_fmt(format_args!("EffectParameter::Bool({v})")),
EffectParameter::Int(_, v) => f.write_fmt(format_args!("EffectParameter::Int({v})")),
EffectParameter::Float(_, v) => f.write_fmt(format_args!("EffectParameter::Float({v})")),
EffectParameter::String(_, v) => f.write_fmt(format_args!("EffectParameter::String({v})")),
}
}
}
impl ValueIdentifiable for EffectParameter {
fn value_identifier(&self) -> ValueIdentifier {
match self {
EffectParameter::Bool(i, _) => *i,
EffectParameter::Int(i, _) => *i,
EffectParameter::Float(i, _) => *i,
EffectParameter::String(i, _) => *i,
EffectParameter::Bool(v) => f.write_fmt(format_args!("EffectParameter::Bool({v})")),
EffectParameter::Int(v) => f.write_fmt(format_args!("EffectParameter::Int({v})")),
EffectParameter::Float(v) => f.write_fmt(format_args!("EffectParameter::Float({v})")),
EffectParameter::String(v) => f.write_fmt(format_args!("EffectParameter::String({v})")),
}
}
}

View File

@@ -2,9 +2,10 @@ use hashbrown::HashSet;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::sync::Arc;
use crate::static_data::{SecondaryEffect, TypeIdentifier};
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
/// The move category defines what global kind of move this move is.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -61,7 +62,7 @@ pub enum MoveTarget {
}
/// A move is the skill Pokémon primarily use in battle. This is the data related to that.
pub trait MoveData: Debug + ValueIdentifiable {
pub trait MoveData: Debug {
/// The name of the move.
fn name(&self) -> &StringKey;
/// The attacking type of the move.
@@ -82,7 +83,7 @@ pub trait MoveData: Debug + ValueIdentifiable {
fn priority(&self) -> i8;
/// The optional secondary effect the move has.
fn secondary_effect(&self) -> &Option<Box<dyn SecondaryEffect>>;
fn secondary_effect(&self) -> &Option<Arc<dyn SecondaryEffect>>;
/// Arbitrary flags that can be applied to the move.
fn has_flag(&self, key: &StringKey) -> bool;
@@ -94,8 +95,6 @@ pub trait MoveData: Debug + ValueIdentifiable {
/// A move is the skill Pokémon primarily use in battle. This is the data related to that.
#[derive(Debug)]
pub struct MoveDataImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The name of the move.
name: StringKey,
/// The attacking type of the move.
@@ -114,7 +113,7 @@ pub struct MoveDataImpl {
/// The priority of the move. A higher priority means the move should go before other moves.
priority: i8,
/// The optional secondary effect the move has.
secondary_effect: Option<Box<dyn SecondaryEffect>>,
secondary_effect: Option<Arc<dyn SecondaryEffect>>,
/// Arbitrary flags that can be applied to the move.
flags: HashSet<StringKey>,
}
@@ -130,11 +129,10 @@ impl MoveDataImpl {
base_usages: u8,
target: MoveTarget,
priority: i8,
secondary_effect: Option<Box<dyn SecondaryEffect>>,
secondary_effect: Option<Arc<dyn SecondaryEffect>>,
flags: HashSet<StringKey>,
) -> Self {
Self {
identifier: Default::default(),
name: name.clone(),
move_type,
category,
@@ -186,7 +184,7 @@ impl MoveData for MoveDataImpl {
}
/// The optional secondary effect the move has.
fn secondary_effect(&self) -> &Option<Box<dyn SecondaryEffect>> {
fn secondary_effect(&self) -> &Option<Arc<dyn SecondaryEffect>> {
&self.secondary_effect
}
@@ -201,12 +199,6 @@ impl MoveData for MoveDataImpl {
}
}
impl ValueIdentifiable for MoveDataImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -225,14 +217,9 @@ pub(crate) mod tests {
fn base_usages(&self) -> u8;
fn target(&self) -> MoveTarget;
fn priority(&self) -> i8;
fn secondary_effect(&self) -> &Option<Box<dyn SecondaryEffect>>;
fn secondary_effect(&self) -> &Option<Arc<dyn SecondaryEffect>>;
fn has_flag(&self, key: &StringKey) -> bool;
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
}
impl ValueIdentifiable for MoveData{
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
}

View File

@@ -1,10 +1,10 @@
use crate::static_data::EffectParameter;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
use std::fmt::Debug;
use std::sync::Arc;
/// A secondary effect is an effect on a move that happens after it hits.
pub trait SecondaryEffect: Debug + ValueIdentifiable {
pub trait SecondaryEffect: Debug {
/// The chance in percentages that the effect triggers. -1 to make it always trigger.
fn chance(&self) -> f32;
/// The name of the effect.
@@ -16,8 +16,6 @@ pub trait SecondaryEffect: Debug + ValueIdentifiable {
/// A secondary effect is an effect on a move that happens after it hits.
#[derive(Debug)]
pub struct SecondaryEffectImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The chance in percentages that the effect triggers. -1 to make it always trigger.
chance: f32,
/// The name of the effect.
@@ -30,7 +28,6 @@ impl SecondaryEffectImpl {
/// Instantiates a new Secondary Effect.
pub fn new(chance: f32, effect_name: StringKey, parameters: Vec<Arc<EffectParameter>>) -> Self {
Self {
identifier: Default::default(),
chance,
effect_name,
parameters,
@@ -53,12 +50,6 @@ impl SecondaryEffect for SecondaryEffectImpl {
}
}
impl ValueIdentifiable for SecondaryEffectImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -77,11 +68,6 @@ pub(crate) mod tests {
fn effect_name(&self) -> &StringKey;
fn parameters(&self) -> &Vec<Arc<EffectParameter>>;
}
impl ValueIdentifiable for SecondaryEffect{
fn value_identifier(&self) -> ValueIdentifier{
ValueIdentifier::new(0)
}
}
}
#[test]

View File

@@ -1,11 +1,10 @@
use crate::static_data::Statistic;
use crate::{ValueIdentifiable, ValueIdentifier};
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: ValueIdentifiable + Debug {
pub trait Nature: Debug {
/// The stat that should receive the increased modifier.
fn increased_stat(&self) -> Statistic;
@@ -27,8 +26,6 @@ pub trait Nature: ValueIdentifiable + Debug {
/// can have an increased statistic and a decreased statistic, or be neutral.
#[derive(Debug)]
pub struct NatureImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The stat that should receive the increased modifier.
increase_stat: Statistic,
/// The stat that should receive the decreased modifier.
@@ -48,7 +45,6 @@ impl NatureImpl {
decrease_modifier: f32,
) -> Arc<Self> {
Arc::new(Self {
identifier: Default::default(),
increase_stat,
decrease_stat,
increase_modifier,
@@ -89,12 +85,6 @@ impl Nature for NatureImpl {
}
}
impl ValueIdentifiable for NatureImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -111,10 +101,5 @@ pub(crate) mod tests {
fn decreased_modifier(&self) -> f32;
fn get_stat_modifier(&self, stat: Statistic) -> f32;
}
impl ValueIdentifiable for Nature {
fn value_identifier(&self) -> ValueIdentifier {
ValueIdentifier::new(0)
}
}
}
}

View File

@@ -1,10 +1,10 @@
use crate::static_data::EffectParameter;
use crate::{StringKey, ValueIdentifiable, ValueIdentifier};
use crate::StringKey;
use std::fmt::Debug;
use std::sync::Arc;
/// An ability is a passive effect in battle that is attached to a Pokemon.
pub trait Ability: Debug + ValueIdentifiable {
pub trait Ability: Debug {
/// The name of the ability.
fn name(&self) -> &StringKey;
/// The name of the script effect of the ability.
@@ -16,8 +16,6 @@ pub trait Ability: Debug + ValueIdentifiable {
/// An ability is a passive effect in battle that is attached to a Pokemon.
#[derive(Debug)]
pub struct AbilityImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The name of the ability.
name: StringKey,
/// The name of the script effect of the ability.
@@ -30,7 +28,6 @@ impl AbilityImpl {
/// Instantiates a new ability.
pub fn new(name: &StringKey, effect: &StringKey, parameters: Vec<Arc<EffectParameter>>) -> Self {
Self {
identifier: Default::default(),
name: name.clone(),
effect: effect.clone(),
parameters,
@@ -53,12 +50,6 @@ impl Ability for AbilityImpl {
}
}
impl ValueIdentifiable for AbilityImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
/// An ability index allows us to find an ability on a form. It combines a bool for whether the
/// ability is hidden or not, and then an index of the ability.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -84,10 +75,5 @@ pub(crate) mod tests {
fn effect(&self) -> &StringKey;
fn parameters(&self) -> &Vec<Arc<EffectParameter>>;
}
impl ValueIdentifiable for Ability {
fn value_identifier(&self) -> ValueIdentifier {
ValueIdentifier::new(0)
}
}
}
}

View File

@@ -7,12 +7,12 @@ use crate::static_data::Statistic;
use crate::static_data::TypeIdentifier;
use crate::static_data::{Ability, StaticStatisticSet};
use crate::static_data::{AbilityIndex, LearnableMoves};
use crate::{Random, ValueIdentifiable, ValueIdentifier};
use crate::Random;
use crate::{StringKey, VecExt};
/// A form is a variant of a specific species. A species always has at least one form, but can have
/// many more.
pub trait Form: ValueIdentifiable + Debug {
pub trait Form: Debug {
/// The name of the form.
fn name(&self) -> &StringKey;
/// The height of the form in meters.
@@ -31,7 +31,7 @@ pub trait Form: ValueIdentifiable + Debug {
fn hidden_abilities(&self) -> &Vec<StringKey>;
/// The moves a Pokemon with this form can learn.
fn moves(&self) -> &Box<dyn LearnableMoves>;
fn moves(&self) -> &Arc<dyn LearnableMoves>;
/// Arbitrary flags can be set on a form for scripting use.
fn flags(&self) -> &HashSet<StringKey>;
@@ -62,8 +62,6 @@ pub trait Form: ValueIdentifiable + Debug {
/// many more.
#[derive(Debug)]
pub struct FormImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The name of the form.
name: StringKey,
/// The height of the form in meters.
@@ -81,7 +79,7 @@ pub struct FormImpl {
/// The possible hidden abilities a Pokemon with this form can have.
hidden_abilities: Vec<StringKey>,
/// The moves a Pokemon with this form can learn.
moves: Box<dyn LearnableMoves>,
moves: Arc<dyn LearnableMoves>,
/// Arbitrary flags can be set on a form for scripting use.
flags: HashSet<StringKey>,
}
@@ -94,20 +92,19 @@ impl FormImpl {
weight: f32,
base_experience: u32,
types: Vec<TypeIdentifier>,
base_stats: StaticStatisticSet<u16>,
base_stats: Arc<StaticStatisticSet<u16>>,
abilities: Vec<StringKey>,
hidden_abilities: Vec<StringKey>,
moves: Box<dyn LearnableMoves>,
moves: Arc<dyn LearnableMoves>,
flags: HashSet<StringKey>,
) -> Self {
Self {
identifier: Default::default(),
name: name.clone(),
height,
weight,
base_experience,
types,
base_stats: Arc::new(base_stats),
base_stats,
abilities,
hidden_abilities,
moves,
@@ -151,7 +148,7 @@ impl Form for FormImpl {
}
/// The moves a Pokemon with this form can learn.
fn moves(&self) -> &Box<dyn LearnableMoves> {
fn moves(&self) -> &Arc<dyn LearnableMoves> {
&self.moves
}
/// Arbitrary flags can be set on a form for scripting use.
@@ -222,12 +219,6 @@ impl Form for FormImpl {
}
}
impl ValueIdentifiable for FormImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -246,7 +237,7 @@ pub(crate) mod tests {
fn base_stats(&self) -> &Arc<StaticStatisticSet<u16>>;
fn abilities(&self) -> &Vec<StringKey>;
fn hidden_abilities(&self) -> &Vec<StringKey>;
fn moves(&self) -> &Box<dyn LearnableMoves>;
fn moves(&self) -> &Arc<dyn LearnableMoves>;
fn flags(&self) -> &HashSet<StringKey>;
fn get_type(&self, index: usize) -> Result<TypeIdentifier>;
fn get_base_stat(&self, stat: Statistic) -> u16;
@@ -257,10 +248,5 @@ pub(crate) mod tests {
fn has_flag(&self, key: &StringKey) -> bool;
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
}
impl ValueIdentifiable for Form {
fn value_identifier(&self) -> ValueIdentifier {
ValueIdentifier::new(0)
}
}
}
}

View File

@@ -1,5 +1,6 @@
use anyhow_ext::Result;
use indexmap::IndexSet;
use parking_lot::RwLock;
use std::fmt::Debug;
use crate::defines::LevelInt;
@@ -8,27 +9,27 @@ use crate::{StringKey, VecExt};
/// The storage of the moves a Pokemon can learn.
pub trait LearnableMoves: Debug {
/// Adds a new level move the Pokemon can learn.
fn add_level_move(&mut self, level: LevelInt, m: &StringKey) -> Result<()>;
fn add_level_move(&self, level: LevelInt, m: &StringKey) -> Result<()>;
/// Gets all moves a Pokemon can learn when leveling up to a specific level.
fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec<StringKey>>;
fn get_learned_by_level(&self, level: LevelInt) -> Option<Vec<StringKey>>;
/// Gets the distinct moves a Pokemon can learn through leveling up.
fn get_distinct_level_moves(&self) -> &IndexSet<StringKey>;
fn get_distinct_level_moves(&self) -> IndexSet<StringKey>;
}
/// The storage of the moves a Pokemon can learn.
#[derive(PartialEq, Eq, Debug)]
#[derive(Debug)]
pub struct LearnableMovesImpl {
/// A map of the moves a Pokemon can learn per level.
learned_by_level: Vec<Vec<StringKey>>,
learned_by_level: RwLock<Vec<Vec<StringKey>>>,
/// A list of the distinct moves a Pokemon can learn through leveling up.
distinct_level_moves: IndexSet<StringKey>,
distinct_level_moves: RwLock<IndexSet<StringKey>>,
}
impl LearnableMovesImpl {
/// Instantiates a new Learnable Moves.
pub fn new(max_level: LevelInt) -> Self {
Self {
learned_by_level: vec![Vec::new(); (max_level + 1) as usize],
learned_by_level: RwLock::new(vec![Vec::new(); (max_level + 1) as usize]),
distinct_level_moves: Default::default(),
}
}
@@ -36,20 +37,23 @@ impl LearnableMovesImpl {
impl LearnableMoves for LearnableMovesImpl {
/// Adds a new level move the Pokemon can learn.
fn add_level_move(&mut self, level: LevelInt, m: &StringKey) -> Result<()> {
self.learned_by_level.get_mut_res(level as usize)?.push(m.clone());
self.distinct_level_moves.insert(m.clone());
fn add_level_move(&self, level: LevelInt, m: &StringKey) -> Result<()> {
self.learned_by_level
.write()
.get_mut_res(level as usize)?
.push(m.clone());
self.distinct_level_moves.write().insert(m.clone());
Ok(())
}
/// Gets all moves a Pokemon can learn when leveling up to a specific level.
fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec<StringKey>> {
self.learned_by_level.get(level as usize)
fn get_learned_by_level(&self, level: LevelInt) -> Option<Vec<StringKey>> {
self.learned_by_level.read().get(level as usize).cloned()
}
/// Gets the distinct moves a Pokemon can learn through leveling up.
fn get_distinct_level_moves(&self) -> &IndexSet<StringKey> {
&self.distinct_level_moves
fn get_distinct_level_moves(&self) -> IndexSet<StringKey> {
self.distinct_level_moves.read().clone()
}
}
@@ -61,7 +65,7 @@ pub(crate) mod tests {
#[test]
fn adds_level_moves() {
let mut moves = LearnableMovesImpl::new(100);
let moves = LearnableMovesImpl::new(100);
moves.add_level_move(1, &"foo".into()).unwrap();
moves.add_level_move(1, &"bar".into()).unwrap();
@@ -73,7 +77,7 @@ pub(crate) mod tests {
#[test]
fn adds_two_same_moves_at_different_level() {
let mut moves = LearnableMovesImpl::new(100);
let moves = LearnableMovesImpl::new(100);
moves.add_level_move(1, &"foo".into()).unwrap();
moves.add_level_move(5, &"foo".into()).unwrap();

View File

@@ -8,11 +8,11 @@ use parking_lot::{RawRwLock, RwLock};
use crate::static_data::Form;
use crate::static_data::Gender;
use crate::Random;
use crate::StringKey;
use crate::{Random, ValueIdentifiable, ValueIdentifier};
/// The data belonging to a Pokemon with certain characteristics.
pub trait Species: ValueIdentifiable + Debug {
pub trait Species: Debug {
/// The national dex identifier of the Pokemon.
fn id(&self) -> u16;
/// The name of the Pokemon.
@@ -47,8 +47,6 @@ pub trait Species: ValueIdentifiable + Debug {
/// The data belonging to a Pokemon with certain characteristics.
#[derive(Debug)]
pub struct SpeciesImpl {
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The national dex identifier of the Pokemon.
id: u16,
/// The name of the Pokemon.
@@ -88,7 +86,6 @@ impl SpeciesImpl {
let mut forms = HashMap::with_capacity(1);
forms.insert_unique_unchecked(get_default_key(), default_form);
Self {
identifier: Default::default(),
id,
name: name.clone(),
gender_rate,
@@ -176,12 +173,6 @@ impl Species for SpeciesImpl {
}
}
impl ValueIdentifiable for SpeciesImpl {
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
@@ -207,10 +198,5 @@ pub(crate) mod tests {
fn has_flag(&self, key: &StringKey) -> bool;
fn has_flag_by_hash(&self, key_hash: u32) -> bool;
}
impl ValueIdentifiable for Species {
fn value_identifier(&self) -> ValueIdentifier {
ValueIdentifier::new(0)
}
}
}
}

View File

@@ -1,6 +1,5 @@
use std::sync::atomic::Ordering;
use crate::{ValueIdentifiable, ValueIdentifier};
use atomig::impls::{PrimitiveAtom, PrimitiveAtomInteger};
use atomig::{Atom, AtomInteger, Atomic};
use num_traits::{clamp, NumCast, PrimInt};
@@ -20,8 +19,6 @@ where
<T as Atom>::Repr: PrimitiveAtomInteger,
T: AtomInteger,
{
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The health point stat value.
hp: Atomic<T>,
/// The physical attack stat value.
@@ -47,7 +44,6 @@ where
/// Creates a new statistic set with given stats.
pub fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
Self {
identifier: Default::default(),
hp: Atomic::<T>::new(hp),
attack: Atomic::<T>::new(attack),
defense: Atomic::<T>::new(defense),
@@ -131,19 +127,6 @@ where
}
}
impl<T> ValueIdentifiable for StatisticSet<T>
where
T: PrimitiveAtom,
T: Atom,
T: PrimitiveAtomInteger,
<T as Atom>::Repr: PrimitiveAtomInteger,
T: AtomInteger,
{
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
/// A collection of statistics that can not be modified after creation.
///
/// As no modifications happen, this struct does not use atomics.
@@ -152,8 +135,6 @@ pub struct StaticStatisticSet<T>
where
T: PrimInt,
{
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The health point stat value.
hp: T,
/// The physical attack stat value.
@@ -175,7 +156,6 @@ where
/// Create a new static statistic set.
pub fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
Self {
identifier: Default::default(),
hp,
attack,
defense,
@@ -223,15 +203,6 @@ where
}
}
impl<T> ValueIdentifiable for StaticStatisticSet<T>
where
T: PrimInt,
{
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
/// A clamped statistic set holds the 6 normal stats for a Pokemon, but ensures it always remains
/// between two values (inclusive on the two values).
#[derive(Default, Debug)]
@@ -245,8 +216,6 @@ where
T: NumCast,
T: PrimInt,
{
/// A unique identifier so we know what value this is.
identifier: ValueIdentifier,
/// The health point stat value.
hp: Atomic<T>,
/// The physical attack stat value.
@@ -295,7 +264,6 @@ where
/// Instantiates a new clamped statistic set.
pub fn new(hp: T, attack: T, defense: T, special_attack: T, special_defense: T, speed: T) -> Self {
Self {
identifier: Default::default(),
hp: Self::clamped_cast(hp),
attack: Self::clamped_cast(attack),
defense: Self::clamped_cast(defense),
@@ -409,21 +377,6 @@ where
}
}
impl<T, const MIN: i64, const MAX: i64> ValueIdentifiable for ClampedStatisticSet<T, MIN, MAX>
where
T: PrimitiveAtom,
T: Atom,
T: PrimitiveAtomInteger,
<T as Atom>::Repr: PrimitiveAtomInteger,
T: AtomInteger,
T: NumCast,
T: PrimInt,
{
fn value_identifier(&self) -> ValueIdentifier {
self.identifier
}
}
#[cfg(test)]
mod tests {
use super::*;