More documentation.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2022-07-01 17:07:22 +02:00
parent 03f5e3bb5a
commit 8f6ecdd4ad
35 changed files with 721 additions and 262 deletions

View File

@@ -1,35 +1,31 @@
use hashbrown::HashMap;
use indexmap::IndexMap;
use crate::static_data::Ability;
use crate::static_data::DataLibrary;
use crate::StringKey;
/// A storage for all abilities that can be used in this data library.
#[derive(Debug)]
pub struct AbilityLibrary {
map: HashMap<StringKey, Box<Ability>>,
list: Vec<StringKey>,
/// The underlying map for the library.
map: IndexMap<StringKey, Box<Ability>>,
}
impl AbilityLibrary {
/// Instantiates a new ability library.
pub fn new(capacity: usize) -> AbilityLibrary {
AbilityLibrary {
map: HashMap::with_capacity(capacity),
list: Vec::with_capacity(capacity),
map: IndexMap::with_capacity(capacity),
}
}
}
impl DataLibrary<'_, Box<Ability>> for AbilityLibrary {
fn map(&self) -> &HashMap<StringKey, Box<Ability>> {
fn map(&self) -> &IndexMap<StringKey, Box<Ability>> {
&self.map
}
fn list_values(&self) -> &Vec<StringKey> {
&self.list
}
fn get_modify(&mut self) -> (&mut HashMap<StringKey, Box<Ability>>, &mut Vec<StringKey>) {
(&mut self.map, &mut self.list)
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Box<Ability>> {
&mut self.map
}
}
@@ -62,17 +58,8 @@ pub mod tests {
#[test]
fn get_ability_library_direct_map_access() {
let lib = build();
let map = lib.map();
let ability = map.get(&"test_ability".into());
let ability = lib.get(&"test_ability".into());
assert!(ability.is_some());
assert_eq!(ability.unwrap().name(), &"test_ability".into());
}
#[test]
fn get_ability_library_direct_list_access() {
let lib = build();
let list = lib.list_values();
assert_eq!(list.len(), 1);
assert!(list.contains(&StringKey::new("test_ability")));
}
}

View File

@@ -1,43 +1,48 @@
use indexmap::IndexMap;
use crate::Random;
use crate::StringKey;
use hashbrown::HashMap;
/// A data library is a collection of methods to set up a default library, where values are stored
/// by both key, while keeping their insertion order.
pub trait DataLibrary<'a, T: 'a> {
fn map(&self) -> &HashMap<StringKey, T>;
fn list_values(&self) -> &Vec<StringKey>;
fn get_modify(&mut self) -> (&mut HashMap<StringKey, T>, &mut Vec<StringKey>);
/// Returns the underlying map.
fn map(&self) -> &IndexMap<StringKey, T>;
/// Returns the underlying map in mutable manner.
fn get_modify(&mut self) -> &mut IndexMap<StringKey, T>;
/// Adds a new value to the library.
fn add(&mut self, key: &StringKey, value: T) {
let modifies = self.get_modify();
modifies.0.insert(key.clone(), value);
modifies.1.push(key.clone());
self.get_modify().insert(key.clone(), value);
}
/// Removes a value from the library.
fn remove(&mut self, key: &StringKey) {
let modifies = self.get_modify();
let index = modifies.1.iter().position(|r| r == key).unwrap();
modifies.0.remove(key);
modifies.1.remove(index);
self.get_modify().remove(key);
}
/// Gets a value from the library.
fn get(&'a self, key: &StringKey) -> Option<&'a T> {
self.map().get(key)
self.map().get::<StringKey>(key)
}
/// Gets a mutable value from the library.
fn get_mut(&mut self, key: &StringKey) -> Option<&mut T> {
self.get_modify().0.get_mut(key)
self.get_modify().get_mut(key)
}
/// Gets the amount of values in the library.
fn len(&self) -> usize {
self.map().len()
}
/// Returns whether the library has no values.
fn is_empty(&self) -> bool {
self.map().is_empty()
}
/// Gets a random value from the library.
fn random_value(&self, rand: &mut Random) -> &T {
let i = rand.get_between(0, self.list_values().len() as i32);
let key = &self.list_values()[i as usize];
return &self.map()[key];
let i = rand.get_between(0, self.len() as i32);
return &self.map().get_index(i as usize).unwrap().1;
}
}

View File

@@ -7,23 +7,30 @@ use crate::defines::LevelInt;
use crate::static_data::GrowthRate;
use crate::StringKey;
/// A library to store all growth rates.
pub struct GrowthRateLibrary {
/// The underlying data structure.
growth_rates: HashMap<StringKey, Box<dyn GrowthRate>>,
}
impl GrowthRateLibrary {
/// Instantiates a new growth rate library with a capacity.
pub fn new(capacity: usize) -> GrowthRateLibrary {
GrowthRateLibrary {
growth_rates: HashMap::with_capacity(capacity),
}
}
/// Calculates the level for a given growth key name and a certain experience.
pub fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> LevelInt {
self.growth_rates[growth_rate].calculate_level(experience)
}
/// Calculates the experience for a given growth key name and a certain level.
pub fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> u32 {
self.growth_rates[growth_rate].calculate_experience(level)
}
/// Adds a new growth rate with a name and value.
pub fn add_growth_rate(&mut self, key: &StringKey, value: Box<dyn GrowthRate>) {
self.growth_rates.insert(key.clone(), value);
}

View File

@@ -1,35 +1,32 @@
use hashbrown::HashMap;
use indexmap::IndexMap;
use crate::static_data::DataLibrary;
use crate::static_data::Item;
use crate::StringKey;
/// A library to store all items.
#[derive(Debug)]
pub struct ItemLibrary {
map: HashMap<StringKey, Box<Item>>,
list: Vec<StringKey>,
/// The underlying data structure.
map: IndexMap<StringKey, Box<Item>>,
}
impl ItemLibrary {
/// Instantiates a new Item Library.
pub fn new(capacity: usize) -> ItemLibrary {
ItemLibrary {
map: HashMap::with_capacity(capacity),
list: Vec::with_capacity(capacity),
map: IndexMap::with_capacity(capacity),
}
}
}
impl DataLibrary<'_, Box<Item>> for ItemLibrary {
fn map(&self) -> &HashMap<StringKey, Box<Item>> {
fn map(&self) -> &IndexMap<StringKey, Box<Item>> {
&self.map
}
fn list_values(&self) -> &Vec<StringKey> {
&self.list
}
fn get_modify(&mut self) -> (&mut HashMap<StringKey, Box<Item>>, &mut Vec<StringKey>) {
(&mut self.map, &mut self.list)
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Box<Item>> {
&mut self.map
}
}

View File

@@ -1,15 +1,19 @@
use crate::defines::LevelInt;
/// This library holds several misc settings for the library.
#[derive(Debug)]
pub struct LibrarySettings {
/// The highest level a Pokemon can be.
maximum_level: LevelInt,
}
impl LibrarySettings {
/// Creates a new settings library.
pub fn new(maximum_level: LevelInt) -> Self {
Self { maximum_level }
}
/// The highest level a Pokemon can be.
pub fn maximum_level(&self) -> LevelInt {
self.maximum_level
}

View File

@@ -15,7 +15,7 @@ pub use species_library::SpeciesLibrary;
#[doc(inline)]
pub use static_data::StaticData;
#[doc(inline)]
pub use type_library::TypeLibrary;
pub use type_library::*;
mod ability_library;
mod data_library;

View File

@@ -1,35 +1,31 @@
use hashbrown::HashMap;
use indexmap::IndexMap;
use crate::static_data::DataLibrary;
use crate::static_data::MoveData;
use crate::StringKey;
/// A library to store all data for moves.
#[derive(Debug)]
pub struct MoveLibrary {
map: HashMap<StringKey, MoveData>,
list: Vec<StringKey>,
/// The underlying map.
map: IndexMap<StringKey, MoveData>,
}
impl MoveLibrary {
/// Instantiates a new Move Library.
pub fn new(capacity: usize) -> MoveLibrary {
MoveLibrary {
map: HashMap::with_capacity(capacity),
list: Vec::with_capacity(capacity),
map: IndexMap::with_capacity(capacity),
}
}
}
impl DataLibrary<'_, MoveData> for MoveLibrary {
fn map(&self) -> &HashMap<StringKey, MoveData> {
fn map(&self) -> &IndexMap<StringKey, MoveData> {
&self.map
}
fn list_values(&self) -> &Vec<StringKey> {
&self.list
}
fn get_modify(&mut self) -> (&mut HashMap<StringKey, MoveData>, &mut Vec<StringKey>) {
(&mut self.map, &mut self.list)
fn get_modify(&mut self) -> &mut IndexMap<StringKey, MoveData> {
&mut self.map
}
}
@@ -45,7 +41,7 @@ pub mod tests {
fn build_move() -> MoveData {
MoveData::new(
&"foo".into(),
0,
0.into(),
MoveCategory::Physical,
100,
100,

View File

@@ -1,35 +1,31 @@
use hashbrown::HashMap;
use indexmap::IndexMap;
use crate::static_data::DataLibrary;
use crate::static_data::Species;
use crate::StringKey;
/// A library to store all data for Pokemon species.
#[derive(Debug)]
pub struct SpeciesLibrary {
map: HashMap<StringKey, Box<Species>>,
list: Vec<StringKey>,
/// The underlying map.
map: IndexMap<StringKey, Box<Species>>,
}
impl SpeciesLibrary {
/// Instantiates a new Species Library.
pub fn new(capacity: usize) -> SpeciesLibrary {
SpeciesLibrary {
map: HashMap::with_capacity(capacity),
list: Vec::with_capacity(capacity),
map: IndexMap::with_capacity(capacity),
}
}
}
impl<'a> DataLibrary<'a, Box<Species>> for SpeciesLibrary {
fn map(&self) -> &HashMap<StringKey, Box<Species>> {
fn map(&self) -> &IndexMap<StringKey, Box<Species>> {
&self.map
}
fn list_values(&self) -> &Vec<StringKey> {
&self.list
}
fn get_modify(&mut self) -> (&mut HashMap<StringKey, Box<Species>>, &mut Vec<StringKey>) {
(&mut self.map, &mut self.list)
fn get_modify(&mut self) -> &mut IndexMap<StringKey, Box<Species>> {
&mut self.map
}
}

View File

@@ -7,19 +7,29 @@ use crate::static_data::NatureLibrary;
use crate::static_data::SpeciesLibrary;
use crate::static_data::TypeLibrary;
/// The storage for all different libraries.
#[derive(Debug)]
pub struct StaticData {
/// Several misc settings for the library.
settings: LibrarySettings,
/// All data for Pokemon species.
species: SpeciesLibrary,
/// All data for the moves.
moves: MoveLibrary,
/// All data for the items.
items: ItemLibrary,
/// All data for growth rates.
growth_rates: GrowthRateLibrary,
/// All data related to types and type effectiveness.
types: TypeLibrary,
/// All data related to natures.
natures: NatureLibrary,
/// All data related to abilities.
abilities: AbilityLibrary,
}
impl StaticData {
/// Instantiates a new data collection.
pub fn new(settings: LibrarySettings) -> Self {
Self {
settings,
@@ -32,50 +42,64 @@ impl StaticData {
abilities: AbilityLibrary::new(0),
}
}
/// Several misc settings for the library.
pub fn settings(&self) -> &LibrarySettings {
&self.settings
}
/// All data for Pokemon species.
pub fn species(&self) -> &SpeciesLibrary {
&self.species
}
/// All data for Pokemon species.
pub fn species_mut(&mut self) -> &mut SpeciesLibrary {
&mut self.species
}
/// All data for the moves.
pub fn moves(&self) -> &MoveLibrary {
&self.moves
}
/// All data for the moves.
pub fn moves_mut(&mut self) -> &mut MoveLibrary {
&mut self.moves
}
/// All data for the items.
pub fn items(&self) -> &ItemLibrary {
&self.items
}
/// All data for the items.
pub fn items_mut(&mut self) -> &mut ItemLibrary {
&mut self.items
}
/// All data for growth rates.
pub fn growth_rates(&self) -> &GrowthRateLibrary {
&self.growth_rates
}
/// All data for growth rates.
pub fn growth_rates_mut(&mut self) -> &mut GrowthRateLibrary {
&mut self.growth_rates
}
/// All data related to types and type effectiveness.
pub fn types(&self) -> &TypeLibrary {
&self.types
}
/// All data related to types and type effectiveness.
pub fn types_mut(&mut self) -> &mut TypeLibrary {
&mut self.types
}
/// All data related to natures.
pub fn natures(&self) -> &NatureLibrary {
&self.natures
}
/// All data related to natures.
pub fn natures_mut(&mut self) -> &mut NatureLibrary {
&mut self.natures
}
/// All data related to abilities.
pub fn abilities(&self) -> &AbilityLibrary {
&self.abilities
}
/// All data related to abilities.
pub fn abilities_mut(&mut self) -> &mut AbilityLibrary {
&mut self.abilities
}

View File

@@ -1,13 +1,32 @@
use crate::StringKey;
use hashbrown::HashMap;
use crate::StringKey;
/// A unique key that can be used to store a reference to a type. Opaque reference to a byte
/// internally.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash)]
pub struct TypeIdentifier {
/// The unique internal value.
val: u8,
}
impl From<u8> for TypeIdentifier {
fn from(val: u8) -> Self {
Self { val }
}
}
/// All data related to types and effectiveness.
#[derive(Debug)]
pub struct TypeLibrary {
types: HashMap<StringKey, u8>,
/// A list of types
types: HashMap<StringKey, TypeIdentifier>,
/// The effectiveness of the different types against each other.
effectiveness: Vec<Vec<f32>>,
}
impl TypeLibrary {
/// Instantiates a new type library with a specific capacity.
pub fn new(capacity: usize) -> TypeLibrary {
TypeLibrary {
types: HashMap::with_capacity(capacity),
@@ -15,15 +34,20 @@ impl TypeLibrary {
}
}
pub fn get_type_id(&self, key: &StringKey) -> u8 {
/// Gets the type identifier for a type with a name.
pub fn get_type_id(&self, key: &StringKey) -> TypeIdentifier {
self.types[key]
}
pub fn get_single_effectiveness(&self, attacking: u8, defending: u8) -> f32 {
self.effectiveness[attacking as usize][defending as usize]
/// Gets the effectiveness for a single attacking type against a single defending type.
pub fn get_single_effectiveness(&self, attacking: TypeIdentifier, defending: TypeIdentifier) -> f32 {
self.effectiveness[attacking.val as usize][defending.val as usize]
}
pub fn get_effectiveness(&self, attacking: u8, defending: &[u8]) -> f32 {
/// Gets the effectiveness for a single attacking type against an amount of defending types.
/// This is equivalent to running [`get_single_effectiveness`] on each defending type, and
/// multiplying the results with each other.
pub fn get_effectiveness(&self, attacking: TypeIdentifier, defending: &[TypeIdentifier]) -> f32 {
let mut e = 1.0;
for def in defending {
e *= self.get_single_effectiveness(attacking, *def);
@@ -31,37 +55,42 @@ impl TypeLibrary {
e
}
pub fn register_type(&mut self, name: &StringKey) -> u8 {
let id = self.types.len() as u8;
/// Registers a new type in the library.
pub fn register_type(&mut self, name: &StringKey) -> TypeIdentifier {
let id = TypeIdentifier {
val: self.types.len() as u8,
};
self.types.insert(name.clone(), id);
self.effectiveness.resize((id + 1) as usize, vec![]);
self.effectiveness.resize((id.val + 1) as usize, vec![]);
for effectiveness in &mut self.effectiveness {
effectiveness.resize((id + 1) as usize, 1.0)
effectiveness.resize((id.val + 1) as usize, 1.0)
}
id
}
pub fn set_effectiveness(&mut self, attacking: u8, defending: u8, effectiveness: f32) {
self.effectiveness[attacking as usize][defending as usize] = effectiveness;
/// Sets the effectiveness for an attacking type against a defending type.
pub fn set_effectiveness(&mut self, attacking: TypeIdentifier, defending: TypeIdentifier, effectiveness: f32) {
self.effectiveness[attacking.val as usize][defending.val as usize] = effectiveness;
}
}
#[cfg(test)]
pub mod tests {
use crate::static_data::libraries::type_library::TypeLibrary;
use assert_approx_eq::assert_approx_eq;
use crate::static_data::libraries::type_library::TypeLibrary;
pub fn build() -> TypeLibrary {
let mut lib = TypeLibrary::new(2);
// Borrow as mut so we can insert
let w = &mut lib;
w.register_type(&"foo".into());
w.register_type(&"bar".into());
let t0 = w.register_type(&"foo".into());
let t1 = w.register_type(&"bar".into());
// Drops borrow as mut
w.set_effectiveness(0, 1, 0.5);
w.set_effectiveness(1, 0, 2.0);
w.set_effectiveness(t0, t1, 0.5);
w.set_effectiveness(t1, t0, 2.0);
lib
}
@@ -72,14 +101,14 @@ pub mod tests {
// Borrow as mut so we can insert
let w = &mut lib;
w.register_type(&"foo".into());
w.register_type(&"bar".into());
let t0 = w.register_type(&"foo".into());
let t1 = w.register_type(&"bar".into());
// Drops borrow as mut
// Borrow as read so we can read
let r = &lib;
assert_eq!(r.get_type_id(&"foo".into()), 0);
assert_eq!(r.get_type_id(&"bar".into()), 1);
assert_eq!(r.get_type_id(&"foo".into()), t0);
assert_eq!(r.get_type_id(&"bar".into()), t1);
}
#[test]
@@ -88,16 +117,16 @@ pub mod tests {
// Borrow as mut so we can insert
let w = &mut lib;
w.register_type(&"foo".into());
w.register_type(&"bar".into());
w.set_effectiveness(0, 1, 0.5);
w.set_effectiveness(1, 0, 2.0);
let t0 = w.register_type(&"foo".into());
let t1 = w.register_type(&"bar".into());
w.set_effectiveness(t0, t1, 0.5);
w.set_effectiveness(t1, t0, 2.0);
// Drops borrow as mut
// Borrow as read so we can read
let r = &lib;
assert_approx_eq!(r.get_single_effectiveness(0, 1), 0.5);
assert_approx_eq!(r.get_single_effectiveness(1, 0), 2.0);
assert_approx_eq!(r.get_single_effectiveness(t0, t1), 0.5);
assert_approx_eq!(r.get_single_effectiveness(t1, t0), 2.0);
}
#[test]
@@ -106,15 +135,15 @@ pub mod tests {
// Borrow as mut so we can insert
let w = &mut lib;
w.register_type(&"foo".into());
w.register_type(&"bar".into());
w.set_effectiveness(0, 1, 0.5);
w.set_effectiveness(1, 0, 2.0);
let t0 = w.register_type(&"foo".into());
let t1 = w.register_type(&"bar".into());
w.set_effectiveness(t0, t1, 0.5);
w.set_effectiveness(t1, t0, 2.0);
// Drops borrow as mut
// Borrow as read so we can read
let r = &lib;
assert_approx_eq!(r.get_effectiveness(0, &[1_u8, 1_u8]), 0.25);
assert_approx_eq!(r.get_effectiveness(1, &[0_u8, 0_u8]), 4.0);
assert_approx_eq!(r.get_effectiveness(t0, &[t1, t1]), 0.25);
assert_approx_eq!(r.get_effectiveness(t1, &[t0, t0]), 4.0);
}
}