rpg_stat/
attributes.rs

1/*!
2# Attributes
3
4These are definitions of abstract terms into code
5
6## Rate
7Rate of occurance
8```
9use rpg_stat::attributes::Rate;
10let yes:Rate = Rate::Always;
11assert_eq!(yes.worked(), true);
12let no:Rate = Rate::None;
13assert_eq!(no.worked(), false);
14let hmmm:Rate = Rate::Some;
15// who knows....
16```
17
18## Effectiveness
19
20We can easily find the value of an effectiveness:
21
22```
23use rpg_stat::attributes::{Effectiveness, Value};
24let hp:i32 = 50;
25// later on we use an item and check the effectiveness of it
26assert_eq!(Effectiveness::Half.value(hp), 25);
27
28```
29This effectiveness can be stored in a struct and you could implement a wrapper for `value(T)`:
30```
31use rpg_stat::attributes::{Effectiveness, Value};
32
33pub struct Item {
34    pub name:String,
35    pub amount:i32,
36    pub effectiveness:Effectiveness,
37}
38impl Item {
39    // much easier to use now!
40    pub fn value(&self) -> i32 {
41        self.effectiveness.value(self.amount)
42    }
43}
44```
45
46## Stage
47```
48use rpg_stat::attributes::{Stage, Value};
49let stage:Stage = Stage::Baby.value(15);
50//
51assert_eq!(stage, Stage::Teen);
52
53```
54
55
56*/
57use std::fmt;
58use std::fmt::Debug;
59use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign};
60extern crate num;
61use serde::{Deserialize, Serialize};
62
63#[cfg(feature = "fltkform")]
64use fltk::{prelude::*, *};
65#[cfg(feature = "fltkform")]
66use fltk_form_derive::*;
67#[cfg(feature = "fltkform")]
68use fltk_form::FltkForm;
69
70// our modules
71use crate::random::Random;
72
73
74/*
75# Rate
76
77This can be used to determine the Rate at which enemies/items appear in areas, or can be used for the Rate effectiveness of an attack/item/etc
78
79To find a random true/false value simple call `worked()` on your enum
80
81```
82use rpg_stat::attributes::Rate;
83let yes:Rate = Rate::Always;
84assert_eq!(yes.worked(), true);
85assert_eq!(Rate::None::worked(), false);
86```
87*/
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
89#[cfg_attr(feature = "fltkform", derive(FltkForm))]
90pub enum Rate {
91    /// 100%
92    Always,
93    /// 90%
94    Usually,
95    /// 75%
96    Often,
97    /// 50%
98    Some,
99    /// 25%
100    Hardly,
101    /// 10%
102    Barely,
103    /// 0%
104    None,
105}
106impl Random for Rate{
107    type Type = Rate;
108    fn random_type(&self) -> Self::Type {
109        let max = 7;
110        let val = self.random_rate(max);
111        match val {
112            0 => Rate::None,
113            1 => Rate::Often,
114            3 => Rate::Hardly,
115            4 => Rate::Some,
116            5 => Rate::Barely,
117            7 => Rate::Always,
118            _=> Rate::Usually,
119        }
120    }
121}
122impl Rate {
123    /*
124    
125    */
126    #[allow(unused)]
127    pub fn worked(&self) -> bool {
128        match *self {
129            Rate::Always => true, // 100%
130            Rate::Usually => self.usually(),
131            Rate::Often => self.often(),
132            Rate::Some => self.half(), // 50%
133            Rate::Hardly => self.hardly(),
134            Rate::Barely => self.barely(),
135            Rate::None => false, // 0%
136        }
137    }
138}
139impl fmt::Display for Rate {
140    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
141        let v:String;
142        match *self {
143            Rate::Always => v = String::from("Always"),
144            Rate::Usually => v = String::from("Usually"),
145            Rate::Often => v = String::from("Often"),
146            Rate::Some => v = String::from("Some"),
147            Rate::Hardly => v = String::from("Hardly"),
148            Rate::Barely => v = String::from("Barely"),
149            Rate::None => v = String::from("None"),
150        }
151        write!(f, "{}", v.as_str())
152    }
153}
154
155/*
156# Effectiveness
157
158```rs
159use rpg_stat::attributes::{Effectiveness, Value};
160let hp:i32 = 50;
161// later on we use an item and check the effectiveness of it
162assert_eq!(Effectiveness::Half.value(hp), 25);
163
164```
165*/
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
167#[cfg_attr(feature = "fltkform", derive(FltkForm))]
168pub enum Effectiveness {    
169    /// Two times the effect
170    Double,
171    /// One half extra added
172    HalfExtra,
173    /// Half of the amount
174    Half,
175    /// The full amount
176    Normal,
177    /// No amount
178    None,
179}
180impl Random for Effectiveness{
181    type Type = Effectiveness;
182    fn random_type(&self) -> Self::Type {
183        let max = 6;
184        let val = self.random_rate(max);
185        match val {
186            0 => Effectiveness::Double,
187            1 => Effectiveness::HalfExtra,
188            4 => Effectiveness::Half,
189            5 => Effectiveness::Normal,
190            _=> Effectiveness::None,
191        }
192    }
193}
194impl<T:Copy
195    + Default
196    + Debug
197    + AddAssign
198    + Add<Output = T>
199    + Div<Output = T>
200    + DivAssign
201    + Mul<Output = T>
202    + MulAssign
203    + Neg<Output = T>
204    + Rem<Output = T>
205    + RemAssign
206    + Sub<Output = T>
207    + SubAssign
208    + std::cmp::PartialOrd
209    + num::NumCast> Value<T> for Effectiveness {
210    type Type = T;
211    fn value(&self, input:T) -> Self::Type {
212        match *self {
213            Effectiveness::Double => input + input,
214            Effectiveness::HalfExtra => {
215                let half:T = input / num::cast(2).unwrap();
216                input + half
217            },
218            Effectiveness::Normal => input,
219            Effectiveness::Half => input / num::cast(2).unwrap(),
220            Effectiveness::None => num::cast(0).unwrap(),
221        }
222    }
223}
224impl Default for Effectiveness {
225    /// Default to empty
226    fn default() -> Self {
227        Self::None
228    }
229}
230impl fmt::Display for Effectiveness {
231    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232        let v:String;
233        match *self {
234            Effectiveness::Double => v = String::from("Double"),
235            Effectiveness::HalfExtra => v = String::from("HalfExtra"),
236            Effectiveness::Half => v = String::from("Half"),
237            Effectiveness::Normal => v = String::from("Normal"),
238            Effectiveness::None => v = String::from("None"),
239        }
240        write!(f, "{}", v.as_str())
241    }
242}
243#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
244#[cfg_attr(feature = "fltkform", derive(FltkForm))]
245/// This is the 'stage' of life the creature is in
246/// Stages of life are similar to Pokemon evolution,
247/// however our creatures cannot change species randomly
248/// Using a life stage is based in real life, rather than
249/// the random changing into some other species thing
250pub enum Stage {
251    Baby,
252    Toddler,
253    Kid,
254    Teen,
255    Young,
256    Grown,
257    Older,
258    Old,
259}
260impl Random for Stage{
261    type Type = Stage;
262    fn random_type(&self) -> Self::Type {
263        let max = 8;
264        let val = self.random_rate(max);
265        match val {
266            0 => Stage::Toddler,
267            1 => Stage::Kid,
268            3 => Stage::Teen,
269            4 => Stage::Young,
270            5 => Stage::Grown,
271            7 => Stage::Older,
272            8 => Stage::Old,
273            _=> Stage::Baby,
274        }
275    }
276}
277impl Stage {
278    /// Default to empty
279    #[allow(dead_code)]
280    fn default() -> Self {
281        Self::Teen
282    }
283}
284impl<T:Copy
285    + Default
286    + Debug
287    + AddAssign
288    + Add<Output = T>
289    + Div<Output = T>
290    + DivAssign
291    + Mul<Output = T>
292    + MulAssign
293    + Neg<Output = T>
294    + Rem<Output = T>
295    + RemAssign
296    + Sub<Output = T>
297    + SubAssign
298    + std::cmp::PartialOrd
299    + num::NumCast> Value<T> for Stage {
300    /// Get the Life stage of the Kreature
301    /// The stage the Kreature is at is determined by their 'age'
302    type Type = Stage;
303    fn value(&self, age:T) -> Self::Type {
304        if age < num::cast(2).unwrap() {
305            Stage::Baby
306        } else if age < num::cast(4).unwrap() {
307            Stage::Toddler
308        } else if age < num::cast(13).unwrap() {
309            Stage::Kid
310        } else if age < num::cast(20).unwrap() {
311            Stage::Teen
312        } else if age < num::cast(40).unwrap() {
313            Stage::Young
314        } else if age < num::cast(65).unwrap() {
315            Stage::Grown
316        } else if age < num::cast(85).unwrap() {
317            Stage::Older
318        } else {
319            Stage::Old
320        }
321        
322    }
323}
324
325pub trait Value<T:Copy
326    + Default
327    + Debug
328    + AddAssign
329    + Add<Output = T>
330    + Div<Output = T>
331    + DivAssign
332    + Mul<Output = T>
333    + MulAssign
334    + Neg<Output = T>
335    + Rem<Output = T>
336    + RemAssign
337    + Sub<Output = T>
338    + SubAssign
339    + std::cmp::PartialOrd
340    + num::NumCast> {
341    type Type;
342    fn value(&self, input:T) -> Self::Type;
343}