battler_data/mons/
leveling_rate.rs1use serde_string_enum::{
2 DeserializeLabeledStringEnum,
3 SerializeLabeledStringEnum,
4};
5
6#[derive(
8 Debug, Clone, Copy, PartialEq, SerializeLabeledStringEnum, DeserializeLabeledStringEnum,
9)]
10pub enum LevelingRate {
11 #[string = "Erratic"]
12 Erratic,
13 #[string = "Fast"]
14 Fast,
15 #[string = "Medium Fast"]
16 #[alias = "Medium"]
17 MediumFast,
18 #[string = "Medium Slow"]
19 MediumSlow,
20 #[string = "Slow"]
21 Slow,
22 #[string = "Fluctuating"]
23 Fluctuating,
24}
25
26impl LevelingRate {
27 pub fn exp_at_level(&self, level: u8) -> u32 {
29 if level == 1 {
30 return 0;
31 }
32 let level = level as u32;
33 let squared_level = level * level;
34 let cubed_level = level * level * level;
35 match self {
36 Self::Erratic => {
37 if level < 50 {
38 (cubed_level * (100 - level)) / 50
39 } else if level < 68 {
40 (cubed_level * (150 - level)) / 100
41 } else if level < 98 {
42 (cubed_level * ((1911 - 10 * level) / 3)) / 500
43 } else {
44 (cubed_level * (160 - level)) / 100
45 }
46 }
47 Self::Fast => (4 * cubed_level) / 5,
48 Self::MediumFast => cubed_level,
49 Self::MediumSlow => {
50 ((6 * cubed_level) / 5)
51 .overflowing_sub(15 * squared_level)
52 .0
53 .overflowing_add(100 * level)
54 .0
55 - 140
56 }
57 Self::Slow => (5 * cubed_level) / 4,
58 Self::Fluctuating => {
59 if level < 15 {
60 (cubed_level * ((level + 1) / 3 + 24)) / 50
61 } else if level < 36 {
62 (cubed_level * (level + 14)) / 50
63 } else {
64 (cubed_level * (level / 2 + 32)) / 50
65 }
66 }
67 }
68 }
69
70 pub fn level_from_exp(&self, exp: u32) -> u8 {
72 let mut min = 1;
73 let mut max = 100;
74 while max - min > 1 {
75 let mid = (max - min) / 2 + min;
76 let mid_exp = self.exp_at_level(mid);
77 if exp < mid_exp {
78 max = mid - 1;
79 } else if exp > mid_exp {
80 min = mid;
82 } else {
83 min = mid;
84 max = mid;
85 }
86 }
87 if exp >= self.exp_at_level(max) {
88 max
89 } else {
90 min
91 }
92 }
93}
94
95#[cfg(test)]
96mod leveling_rate_test {
97 use crate::{
98 mons::LevelingRate,
99 test_util::{
100 test_string_deserialization,
101 test_string_serialization,
102 },
103 };
104
105 #[test]
106 fn serializes_to_string() {
107 test_string_serialization(LevelingRate::Erratic, "Erratic");
108 test_string_serialization(LevelingRate::Fast, "Fast");
109 test_string_serialization(LevelingRate::MediumFast, "Medium Fast");
110 test_string_serialization(LevelingRate::MediumSlow, "Medium Slow");
111 test_string_serialization(LevelingRate::Slow, "Slow");
112 test_string_serialization(LevelingRate::Fluctuating, "Fluctuating");
113 }
114
115 #[test]
116 fn deserializes_lowercase() {
117 test_string_deserialization("erratic", LevelingRate::Erratic);
118 test_string_deserialization("fast", LevelingRate::Fast);
119 test_string_deserialization("medium fast", LevelingRate::MediumFast);
120 test_string_deserialization("medium slow", LevelingRate::MediumSlow);
121 test_string_deserialization("slow", LevelingRate::Slow);
122 test_string_deserialization("fluctuating", LevelingRate::Fluctuating);
123 }
124
125 #[test]
126 fn calculates_experience_at_level() {
127 assert_eq!(LevelingRate::Erratic.exp_at_level(1), 0);
128 assert_eq!(LevelingRate::Erratic.exp_at_level(2), 15);
129 assert_eq!(LevelingRate::Erratic.exp_at_level(20), 12800);
130 assert_eq!(LevelingRate::Erratic.exp_at_level(50), 125000);
131 assert_eq!(LevelingRate::Erratic.exp_at_level(77), 346965);
132 assert_eq!(LevelingRate::Erratic.exp_at_level(100), 600000);
133
134 assert_eq!(LevelingRate::Fast.exp_at_level(1), 0);
135 assert_eq!(LevelingRate::Fast.exp_at_level(2), 6);
136 assert_eq!(LevelingRate::Fast.exp_at_level(20), 6400);
137 assert_eq!(LevelingRate::Fast.exp_at_level(50), 100000);
138 assert_eq!(LevelingRate::Fast.exp_at_level(77), 365226);
139 assert_eq!(LevelingRate::Fast.exp_at_level(100), 800000);
140
141 assert_eq!(LevelingRate::MediumFast.exp_at_level(1), 0);
142 assert_eq!(LevelingRate::MediumFast.exp_at_level(2), 8);
143 assert_eq!(LevelingRate::MediumFast.exp_at_level(20), 8000);
144 assert_eq!(LevelingRate::MediumFast.exp_at_level(50), 125000);
145 assert_eq!(LevelingRate::MediumFast.exp_at_level(77), 456533);
146 assert_eq!(LevelingRate::MediumFast.exp_at_level(100), 1000000);
147
148 assert_eq!(LevelingRate::MediumSlow.exp_at_level(1), 0);
149 assert_eq!(LevelingRate::MediumSlow.exp_at_level(2), 9);
150 assert_eq!(LevelingRate::MediumSlow.exp_at_level(20), 5460);
151 assert_eq!(LevelingRate::MediumSlow.exp_at_level(50), 117360);
152 assert_eq!(LevelingRate::MediumSlow.exp_at_level(77), 466464);
153 assert_eq!(LevelingRate::MediumSlow.exp_at_level(100), 1059860);
154
155 assert_eq!(LevelingRate::Slow.exp_at_level(1), 0);
156 assert_eq!(LevelingRate::Slow.exp_at_level(2), 10);
157 assert_eq!(LevelingRate::Slow.exp_at_level(20), 10000);
158 assert_eq!(LevelingRate::Slow.exp_at_level(50), 156250);
159 assert_eq!(LevelingRate::Slow.exp_at_level(77), 570666);
160 assert_eq!(LevelingRate::Slow.exp_at_level(100), 1250000);
161
162 assert_eq!(LevelingRate::Fluctuating.exp_at_level(1), 0);
163 assert_eq!(LevelingRate::Fluctuating.exp_at_level(2), 4);
164 assert_eq!(LevelingRate::Fluctuating.exp_at_level(20), 5440);
165 assert_eq!(LevelingRate::Fluctuating.exp_at_level(50), 142500);
166 assert_eq!(LevelingRate::Fluctuating.exp_at_level(77), 639146);
167 assert_eq!(LevelingRate::Fluctuating.exp_at_level(100), 1640000);
168 }
169
170 #[test]
171 fn calculates_level_from_exp() {
172 assert_eq!(LevelingRate::Erratic.level_from_exp(0), 1);
173 assert_eq!(LevelingRate::Erratic.level_from_exp(14), 1);
174 assert_eq!(LevelingRate::Erratic.level_from_exp(15), 2);
175 assert_eq!(LevelingRate::Erratic.level_from_exp(209728), 62);
176 assert_eq!(LevelingRate::Erratic.level_from_exp(217539), 62);
177 assert_eq!(LevelingRate::Erratic.level_from_exp(217540), 63);
178 assert_eq!(LevelingRate::Erratic.level_from_exp(600000), 100);
179
180 assert_eq!(LevelingRate::Slow.level_from_exp(0), 1);
181 assert_eq!(LevelingRate::Slow.level_from_exp(9), 1);
182 assert_eq!(LevelingRate::Slow.level_from_exp(10), 2);
183 assert_eq!(LevelingRate::Slow.level_from_exp(297910), 62);
184 assert_eq!(LevelingRate::Slow.level_from_exp(312557), 62);
185 assert_eq!(LevelingRate::Slow.level_from_exp(312558), 63);
186 assert_eq!(LevelingRate::Slow.level_from_exp(1250000), 100);
187 }
188}