scarlet_queen_fitness/
pokemon_type.rs

1use crate::effective::TypeEffectiveness;
2use scarlet_queen_core::{
3    each_individual::{EachCrateIndividual, FitnessIndividualTrait, Individual},
4    pokemon_type::{PokemonTypeAll, PokemonTypeTrait},
5};
6use std::{ops::Deref, rc::Rc};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct FitnessPokemonType<P>
10where
11    P: PokemonTypeTrait,
12{
13    pokemon_type: Rc<Individual<P>>,
14}
15
16impl<P> FitnessPokemonType<P>
17where
18    P: PokemonTypeTrait,
19{
20    fn attack_effectiveness(&self, defense: &Self) -> TypeEffectiveness {
21        TypeEffectiveness::from_effective_array(self, defense)
22    }
23}
24
25impl<P> EachCrateIndividual for FitnessPokemonType<P>
26where
27    P: PokemonTypeTrait,
28{
29    type Item = P;
30
31    fn new(pokemon_type: &Rc<Individual<P>>) -> FitnessPokemonType<P> {
32        FitnessPokemonType {
33            pokemon_type: Rc::clone(pokemon_type),
34        }
35    }
36
37    fn get_individual(&self) -> &Individual<P> {
38        &self.pokemon_type
39    }
40}
41
42impl<P> FitnessIndividualTrait for FitnessPokemonType<P>
43where
44    P: PokemonTypeTrait,
45{
46    fn fitness(&self, other: &Self) -> usize {
47        self.attack_effectiveness(other).point()
48    }
49}
50
51impl<P> From<FitnessPokemonType<P>> for usize
52where
53    P: PokemonTypeTrait,
54{
55    fn from(val: FitnessPokemonType<P>) -> Self {
56        usize::from(&val)
57    }
58}
59
60impl<P> From<&FitnessPokemonType<P>> for usize
61where
62    P: PokemonTypeTrait,
63{
64    fn from(val: &FitnessPokemonType<P>) -> Self {
65        match <P as Into<PokemonTypeAll>>::into(val.pokemon_type.deref().get_value().clone()) {
66            PokemonTypeAll::None => 0,
67            PokemonTypeAll::Normal => 1,
68            PokemonTypeAll::Fire => 2,
69            PokemonTypeAll::Water => 3,
70            PokemonTypeAll::Electric => 4,
71            PokemonTypeAll::Grass => 5,
72            PokemonTypeAll::Ice => 6,
73            PokemonTypeAll::Fighting => 7,
74            PokemonTypeAll::Poison => 8,
75            PokemonTypeAll::Ground => 9,
76            PokemonTypeAll::Flying => 10,
77            PokemonTypeAll::Psychic => 11,
78            PokemonTypeAll::Bug => 12,
79            PokemonTypeAll::Rock => 13,
80            PokemonTypeAll::Ghost => 14,
81            PokemonTypeAll::Dragon => 15,
82            PokemonTypeAll::Dark => 16,
83            PokemonTypeAll::Steel => 17,
84            PokemonTypeAll::Fairy => 18,
85        }
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use std::rc::Rc;
92
93    use scarlet_queen_core::{
94        each_individual::{EachCrateIndividual, FitnessIndividualTrait, Individual},
95        pokemon_type::PokemonTypeAll,
96    };
97
98    use crate::{effective::TypeEffectiveness, pokemon_type::FitnessPokemonType};
99
100    #[test]
101    fn test_fitnesspokemontype_attackeffectiveness() {
102        let testcases = vec![
103            (
104                (
105                    FitnessPokemonType {
106                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::None)),
107                    },
108                    FitnessPokemonType {
109                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Dragon)),
110                    },
111                ),
112                TypeEffectiveness::Normal,
113            ),
114            (
115                (
116                    FitnessPokemonType {
117                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Steel)),
118                    },
119                    FitnessPokemonType {
120                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::None)),
121                    },
122                ),
123                TypeEffectiveness::Normal,
124            ),
125            (
126                (
127                    FitnessPokemonType {
128                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fire)),
129                    },
130                    FitnessPokemonType {
131                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Grass)),
132                    },
133                ),
134                TypeEffectiveness::SuperEffective,
135            ),
136            (
137                (
138                    FitnessPokemonType {
139                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fire)),
140                    },
141                    FitnessPokemonType {
142                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Water)),
143                    },
144                ),
145                TypeEffectiveness::NotVeryEffective,
146            ),
147            (
148                (
149                    FitnessPokemonType {
150                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Rock)),
151                    },
152                    FitnessPokemonType {
153                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Rock)),
154                    },
155                ),
156                TypeEffectiveness::Normal,
157            ),
158            (
159                (
160                    FitnessPokemonType {
161                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fighting)),
162                    },
163                    FitnessPokemonType {
164                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Ghost)),
165                    },
166                ),
167                TypeEffectiveness::NoEffect,
168            ),
169        ];
170        for ((arg_1, arg_2), result) in testcases.into_iter() {
171            assert_eq!(
172                FitnessPokemonType::<PokemonTypeAll>::attack_effectiveness(&arg_1, &arg_2),
173                result
174            );
175        }
176    }
177
178    #[test]
179    fn test_fitnesspokemontype_eachcrateindividual_new() {
180        let testcases: Vec<(
181            Rc<Individual<PokemonTypeAll>>,
182            FitnessPokemonType<PokemonTypeAll>,
183        )> = vec![
184            (
185                Rc::new(Individual::new_with_id(0, PokemonTypeAll::None)),
186                FitnessPokemonType {
187                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::None)),
188                },
189            ),
190            (
191                Rc::new(Individual::new_with_id(1, PokemonTypeAll::Fire)),
192                FitnessPokemonType {
193                    pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Fire)),
194                },
195            ),
196            (
197                Rc::new(Individual::new_with_id(0, PokemonTypeAll::Dragon)),
198                FitnessPokemonType {
199                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Dragon)),
200                },
201            ),
202        ];
203        for (arg, result) in testcases.into_iter() {
204            assert_eq!(FitnessPokemonType::<PokemonTypeAll>::new(&arg), result);
205        }
206    }
207
208    #[test]
209    fn test_fitnesspokemontype_fitnessindividual_fitness() {
210        let testcases = vec![
211            (
212                (
213                    FitnessPokemonType {
214                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::None)),
215                    },
216                    FitnessPokemonType {
217                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Dragon)),
218                    },
219                ),
220                2,
221            ),
222            (
223                (
224                    FitnessPokemonType {
225                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Steel)),
226                    },
227                    FitnessPokemonType {
228                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::None)),
229                    },
230                ),
231                2,
232            ),
233            (
234                (
235                    FitnessPokemonType {
236                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fire)),
237                    },
238                    FitnessPokemonType {
239                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Grass)),
240                    },
241                ),
242                3,
243            ),
244            (
245                (
246                    FitnessPokemonType {
247                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fire)),
248                    },
249                    FitnessPokemonType {
250                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Water)),
251                    },
252                ),
253                1,
254            ),
255            (
256                (
257                    FitnessPokemonType {
258                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Rock)),
259                    },
260                    FitnessPokemonType {
261                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Rock)),
262                    },
263                ),
264                2,
265            ),
266            (
267                (
268                    FitnessPokemonType {
269                        pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fighting)),
270                    },
271                    FitnessPokemonType {
272                        pokemon_type: Rc::new(Individual::new_with_id(1, PokemonTypeAll::Ghost)),
273                    },
274                ),
275                0,
276            ),
277        ];
278        for ((arg_1, arg_2), result) in testcases.into_iter() {
279            assert_eq!(
280                FitnessPokemonType::<PokemonTypeAll>::fitness(&arg_1, &arg_2),
281                result
282            );
283        }
284    }
285
286    #[test]
287    fn test_fitnesspokemontype_intousize_into() {
288        let testcases: Vec<(FitnessPokemonType<PokemonTypeAll>, usize)> = vec![
289            (
290                FitnessPokemonType {
291                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::None)),
292                },
293                0,
294            ),
295            (
296                FitnessPokemonType {
297                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Normal)),
298                },
299                1,
300            ),
301            (
302                FitnessPokemonType {
303                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fire)),
304                },
305                2,
306            ),
307            (
308                FitnessPokemonType {
309                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Water)),
310                },
311                3,
312            ),
313            (
314                FitnessPokemonType {
315                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Electric)),
316                },
317                4,
318            ),
319            (
320                FitnessPokemonType {
321                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Grass)),
322                },
323                5,
324            ),
325            (
326                FitnessPokemonType {
327                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Ice)),
328                },
329                6,
330            ),
331            (
332                FitnessPokemonType {
333                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fighting)),
334                },
335                7,
336            ),
337            (
338                FitnessPokemonType {
339                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Poison)),
340                },
341                8,
342            ),
343            (
344                FitnessPokemonType {
345                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Ground)),
346                },
347                9,
348            ),
349            (
350                FitnessPokemonType {
351                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Flying)),
352                },
353                10,
354            ),
355            (
356                FitnessPokemonType {
357                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Psychic)),
358                },
359                11,
360            ),
361            (
362                FitnessPokemonType {
363                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Bug)),
364                },
365                12,
366            ),
367            (
368                FitnessPokemonType {
369                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Rock)),
370                },
371                13,
372            ),
373            (
374                FitnessPokemonType {
375                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Ghost)),
376                },
377                14,
378            ),
379            (
380                FitnessPokemonType {
381                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Dragon)),
382                },
383                15,
384            ),
385            (
386                FitnessPokemonType {
387                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Dark)),
388                },
389                16,
390            ),
391            (
392                FitnessPokemonType {
393                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Steel)),
394                },
395                17,
396            ),
397            (
398                FitnessPokemonType {
399                    pokemon_type: Rc::new(Individual::new_with_id(0, PokemonTypeAll::Fairy)),
400                },
401                18,
402            ),
403        ];
404        for (arg, result) in testcases.into_iter() {
405            assert_eq!(usize::from(&arg), result);
406            assert_eq!(usize::from(arg), result);
407        }
408    }
409}