Large amounts of work on Rune
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2024-05-08 15:46:09 +02:00
parent 4bc76b0ee4
commit 4ec07ca049
43 changed files with 979 additions and 397 deletions

View File

@@ -2,9 +2,10 @@ use crate::defines::LevelInt;
use crate::VecExt;
use anyhow::Result;
use anyhow_ext::ensure;
use std::fmt::Debug;
/// A growth rate defines how much experience is required per level.
pub trait GrowthRate {
pub trait GrowthRate: Debug {
/// Calculate the level something with this growth rate would have at a certain experience.
fn calculate_level(&self, experience: u32) -> LevelInt;
/// Calculate the experience something with this growth rate would have at a certain level.
@@ -12,6 +13,7 @@ pub trait GrowthRate {
}
/// An implementation of the growth rate that uses a lookup table for experience.
#[derive(Debug)]
pub struct LookupGrowthRate {
/// The lookup Vec.
experience: Vec<u32>,
@@ -20,9 +22,7 @@ pub struct LookupGrowthRate {
impl LookupGrowthRate {
/// Instantiates a new lookup growth rate. The experience vec should be the amount of experience
/// required per level, with the first element being the experience required for level 1 (generally 0).
pub fn new(experience: Vec<u32>) -> LookupGrowthRate {
LookupGrowthRate { experience }
}
pub fn new(experience: Vec<u32>) -> LookupGrowthRate { LookupGrowthRate { experience } }
}
impl GrowthRate for LookupGrowthRate {

View File

@@ -1,6 +1,5 @@
use hashbrown::HashSet;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")] use serde::{Deserialize, Serialize};
use std::any::Any;
use std::fmt::Debug;
@@ -9,6 +8,7 @@ use crate::StringKey;
/// An item category defines which bag slot items are stored in.
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "rune", derive(rune::Any))]
#[repr(u8)]
pub enum ItemCategory {
/// This is where most items should go.
@@ -32,6 +32,7 @@ pub enum ItemCategory {
/// A battle item category defines how the item is categorized when in battle.
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "rune", derive(rune::Any))]
#[repr(u8)]
pub enum BattleItemCategory {
/// This item can't be used in battle.
@@ -99,30 +100,18 @@ impl ItemImpl {
impl Item for ItemImpl {
/// The name of the item.
fn name(&self) -> &StringKey {
&self.name
}
fn name(&self) -> &StringKey { &self.name }
/// Which bag slot items are stored in.
fn category(&self) -> ItemCategory {
self.category
}
fn category(&self) -> ItemCategory { self.category }
/// How the item is categorized when in battle.
fn battle_category(&self) -> BattleItemCategory {
self.battle_category
}
fn battle_category(&self) -> BattleItemCategory { self.battle_category }
/// The buying value of the item.
fn price(&self) -> i32 {
self.price
}
fn price(&self) -> i32 { self.price }
/// A set of arbitrary flags that can be set on the item.
fn flags(&self) -> &HashSet<StringKey> {
&self.flags
}
fn flags(&self) -> &HashSet<StringKey> { &self.flags }
/// Checks whether the item has a specific flag.
fn has_flag(&self, key: &StringKey) -> bool {
self.flags.contains(key)
}
fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains(key) }
}
#[cfg(test)]

View File

@@ -1,4 +1,5 @@
use anyhow_ext::Result;
use std::fmt::Debug;
use std::sync::Arc;
use indexmap::IndexMap;
@@ -8,7 +9,7 @@ use crate::StringKey;
/// 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<T: ?Sized> {
pub trait DataLibrary<T: ?Sized>: Debug {
/// Returns the underlying map.
fn map(&self) -> &IndexMap<StringKey, Arc<T>>;
/// Returns the underlying map in mutable manner.
@@ -25,32 +26,22 @@ pub trait DataLibrary<T: ?Sized> {
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);
self_mut.get_modify().swap_remove(key);
}
/// Gets a value from the library.
fn get(&self, key: &StringKey) -> Option<Arc<T>> {
self.map().get::<StringKey>(key).cloned()
}
fn get(&self, key: &StringKey) -> Option<Arc<T>> { self.map().get::<StringKey>(key).cloned() }
/// Gets a value from the library.
fn get_by_hash(&self, key: u32) -> Option<Arc<T>> {
self.map().get::<u32>(&key).cloned()
}
fn get_by_hash(&self, key: u32) -> Option<Arc<T>> { self.map().get::<u32>(&key).cloned() }
/// Gets a value from the library by the index where it is stored.
fn get_key_by_index(&self, index: usize) -> Option<StringKey> {
self.map().get_index(index).map(|a| a.0.clone())
}
fn get_key_by_index(&self, index: usize) -> Option<StringKey> { self.map().get_index(index).map(|a| a.0.clone()) }
/// Gets the amount of values in the library.
fn len(&self) -> usize {
self.map().len()
}
fn len(&self) -> usize { self.map().len() }
/// Returns whether the library has no values.
fn is_empty(&self) -> bool {
self.map().is_empty()
}
fn is_empty(&self) -> bool { self.map().is_empty() }
/// Gets a random value from the library.
fn random_value(&self, rand: &mut Random) -> Result<&Arc<T>> {

View File

@@ -61,9 +61,7 @@ impl GrowthRateLibrary for GrowthRateLibraryImpl {
}
impl Debug for GrowthRateLibraryImpl {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("GrowthRateLibrary").finish()
}
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("GrowthRateLibrary").finish() }
}
#[cfg(test)]
@@ -72,8 +70,6 @@ impl Debug for GrowthRateLibraryImpl {
pub mod tests {
use super::*;
use crate::static_data::growth_rates::LookupGrowthRate;
use crate::static_data::libraries::growth_rate_library::GrowthRateLibrary;
use crate::static_data::GrowthRateLibraryImpl;
pub fn build() -> GrowthRateLibraryImpl {
let mut lib = GrowthRateLibraryImpl::new(1);

View File

@@ -38,14 +38,10 @@ impl NatureLibraryImpl {
impl NatureLibrary for NatureLibraryImpl {
/// Adds a new nature with name to the library.
fn load_nature(&self, name: StringKey, nature: Arc<dyn Nature>) {
self.map.write().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.read().get(key).cloned()
}
fn get_nature(&self, key: &StringKey) -> Option<Arc<dyn Nature>> { self.map.read().get(key).cloned() }
fn get_random_nature(&self, rand: &mut Random) -> Result<Arc<dyn Nature>> {
let map = self.map.read();
@@ -80,7 +76,7 @@ impl NatureLibrary for NatureLibraryImpl {
pub mod tests {
use super::*;
use crate::static_data::statistics::Statistic;
use crate::static_data::{NatureImpl, NatureLibrary, NatureLibraryImpl};
use crate::static_data::NatureImpl;
pub fn build() -> NatureLibraryImpl {
let lib = NatureLibraryImpl::new(2);

View File

@@ -11,27 +11,18 @@ use crate::{PkmnError, StringKey};
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, Hash, Atom)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct TypeIdentifier {
/// The unique internal value.
val: u8,
}
pub struct TypeIdentifier(u8);
impl From<u8> for TypeIdentifier {
fn from(val: u8) -> Self {
Self { val }
}
fn from(val: u8) -> Self { Self(val) }
}
impl From<TypeIdentifier> for u8 {
fn from(id: TypeIdentifier) -> Self {
id.val
}
fn from(id: TypeIdentifier) -> Self { id.0 }
}
impl Display for TypeIdentifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "TypeId({})", self.val)
}
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "TypeId({})", self.0) }
}
/// All data related to types and effectiveness.
@@ -87,18 +78,16 @@ impl TypeLibraryImpl {
defending: TypeIdentifier,
) -> Result<f32> {
Ok(*lock
.get((attacking.val - 1) as usize)
.get((attacking.0 - 1) as usize)
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: attacking })?
.get((defending.val - 1) as usize)
.get((defending.0 - 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.read().get(key).cloned()
}
fn get_type_id(&self, key: &StringKey) -> Option<TypeIdentifier> { self.types.read().get(key).cloned() }
/// Gets the type name from the type identifier.
fn get_type_name(&self, t: TypeIdentifier) -> Option<StringKey> {
@@ -133,13 +122,11 @@ impl TypeLibrary for TypeLibraryImpl {
let mut types_write_lock = self.types.write();
let mut effectiveness_write_lock = self.effectiveness.write();
let id = TypeIdentifier {
val: (types_write_lock.len() + 1) as u8,
};
let id = TypeIdentifier((types_write_lock.len() + 1) as u8);
types_write_lock.insert(name.clone(), id);
effectiveness_write_lock.resize((id.val) as usize, vec![]);
effectiveness_write_lock.resize((id.0) as usize, vec![]);
for effectiveness in &mut effectiveness_write_lock.iter_mut() {
effectiveness.resize((id.val) as usize, 1.0)
effectiveness.resize((id.0) as usize, 1.0)
}
id
}
@@ -154,9 +141,9 @@ impl TypeLibrary for TypeLibraryImpl {
*self
.effectiveness
.write()
.get_mut((attacking.val - 1) as usize)
.get_mut((attacking.0 - 1) as usize)
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: attacking })?
.get_mut((defending.val - 1) as usize)
.get_mut((defending.0 - 1) as usize)
.ok_or(PkmnError::InvalidTypeIdentifier { type_id: defending })? = effectiveness;
Ok(())
}
@@ -169,7 +156,6 @@ pub mod tests {
use assert_approx_eq::assert_approx_eq;
use super::*;
use crate::static_data::libraries::type_library::TypeLibrary;
pub fn build() -> TypeLibraryImpl {
let mut lib = TypeLibraryImpl::new(2);

View File

@@ -24,12 +24,6 @@ use std::fmt::{Display, Formatter};
pub(crate) mod tests {
use super::*;
#[doc(inline)]
pub use growth_rates::tests::*;
#[doc(inline)]
pub use items::tests::*;
#[doc(inline)]
pub use libraries::tests::*;
#[doc(inline)]
pub use moves::tests::*;
#[doc(inline)]
pub use natures::tests::*;
@@ -71,27 +65,19 @@ pub enum Parameter {
}
impl From<bool> for Parameter {
fn from(b: bool) -> Self {
Parameter::Bool(b)
}
fn from(b: bool) -> Self { Parameter::Bool(b) }
}
impl From<i64> for Parameter {
fn from(i: i64) -> Self {
Parameter::Int(i)
}
fn from(i: i64) -> Self { Parameter::Int(i) }
}
impl From<f32> for Parameter {
fn from(f: f32) -> Self {
Parameter::Float(f)
}
fn from(f: f32) -> Self { Parameter::Float(f) }
}
impl From<StringKey> for Parameter {
fn from(s: StringKey) -> Self {
Parameter::String(s)
}
fn from(s: StringKey) -> Self { Parameter::String(s) }
}
impl Display for Parameter {

View File

@@ -1,16 +1,11 @@
#[doc(inline)]
pub use move_data::*;
#[doc(inline)]
pub use secondary_effect::*;
#[doc(inline)] pub use move_data::*;
#[doc(inline)] pub use secondary_effect::*;
#[cfg(test)]
pub(crate) mod tests {
use super::*;
#[doc(inline)]
pub use move_data::tests::*;
#[doc(inline)]
pub use secondary_effect::tests::*;
#[doc(inline)] pub use move_data::tests::*;
}
/// The data belonging to a certain move.

View File

@@ -1,6 +1,5 @@
use hashbrown::HashSet;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")] use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::sync::Arc;
@@ -11,6 +10,7 @@ use crate::StringKey;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
#[cfg_attr(feature = "rune", derive(rune::Any))]
#[repr(u8)]
pub enum MoveCategory {
/// A physical move uses the physical attack stats and physical defense stats to calculate damage.
@@ -24,6 +24,7 @@ pub enum MoveCategory {
/// The move target defines what kind of targets the move can touch.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "rune", derive(rune::Any))]
#[repr(u8)]
pub enum MoveTarget {
/// Adjacent allows a move to target any Pokemon that is either directly to the left or right of
@@ -149,54 +150,32 @@ impl MoveDataImpl {
impl MoveData for MoveDataImpl {
/// The name of the move.
fn name(&self) -> &StringKey {
&self.name
}
fn name(&self) -> &StringKey { &self.name }
/// The attacking type of the move.
fn move_type(&self) -> TypeIdentifier {
self.move_type
}
fn move_type(&self) -> TypeIdentifier { self.move_type }
/// The category of the move.
fn category(&self) -> MoveCategory {
self.category
}
fn category(&self) -> MoveCategory { self.category }
/// The base power, not considering any modifiers, the move has.
fn base_power(&self) -> u8 {
self.base_power
}
fn base_power(&self) -> u8 { self.base_power }
/// The accuracy of the move in percentage. Should be 255 for moves that always hit.
fn accuracy(&self) -> u8 {
self.accuracy
}
fn accuracy(&self) -> u8 { self.accuracy }
/// The number of times the move can be used. This can be modified on actually learned moves using
/// PP-Ups
fn base_usages(&self) -> u8 {
self.base_usages
}
fn base_usages(&self) -> u8 { self.base_usages }
/// How the move handles targets.
fn target(&self) -> MoveTarget {
self.target
}
fn target(&self) -> MoveTarget { self.target }
/// The priority of the move. A higher priority means the move should go before other moves.
fn priority(&self) -> i8 {
self.priority
}
fn priority(&self) -> i8 { self.priority }
/// The optional secondary effect the move has.
fn secondary_effect(&self) -> &Option<Arc<dyn SecondaryEffect>> {
&self.secondary_effect
}
fn secondary_effect(&self) -> &Option<Arc<dyn SecondaryEffect>> { &self.secondary_effect }
/// Checks if the move has a specific flag.
fn has_flag(&self, key: &StringKey) -> bool {
self.flags.contains::<StringKey>(key)
}
fn has_flag(&self, key: &StringKey) -> bool { self.flags.contains::<StringKey>(key) }
/// Checks if the move has a specific flag.
fn has_flag_by_hash(&self, key_hash: u32) -> bool {
self.flags.contains::<u32>(&key_hash)
}
fn has_flag_by_hash(&self, key_hash: u32) -> bool { self.flags.contains::<u32>(&key_hash) }
}
#[cfg(test)]

View File

@@ -52,9 +52,6 @@ pub(crate) mod tests {
use super::*;
use assert_approx_eq::assert_approx_eq;
use crate::static_data::moves::secondary_effect::SecondaryEffect;
use crate::static_data::SecondaryEffectImpl;
mockall::mock! {
#[derive(Debug)]
pub SecondaryEffect{}

View File

@@ -4,6 +4,7 @@
/// that allows for a more progressive gender system for those that want it?
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde_repr::Serialize_repr, serde_repr::Deserialize_repr))]
#[cfg_attr(feature = "rune", derive(rune::Any))]
#[repr(u8)]
pub enum Gender {
/// The Pokemon has no gender.

View File

@@ -13,9 +13,7 @@ pub use species::*;
#[cfg(test)]
pub(crate) mod tests {
pub use super::ability::tests::*;
pub use super::form::tests::*;
pub use super::learnable_moves::tests::*;
pub use super::species::tests::*;
}

View File

@@ -1,5 +1,4 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")] use serde::{Deserialize, Serialize};
/// Stats are numerical values on Pokemon that are used in battle.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]