Skip to main content

battler_data/mons/
learnset.rs

1use alloc::{
2    format,
3    string::String,
4};
5use core::{
6    fmt,
7    fmt::Display,
8    str::FromStr,
9};
10
11use anyhow::Error;
12use hashbrown::{
13    HashMap,
14    HashSet,
15};
16use serde_string_enum::{
17    DeserializeStringEnum,
18    SerializeStringEnum,
19};
20
21/// The source of a move, which details how a species can learn a move in their learnset.
22///
23/// This enum is encoded as a single letter followed by optional details:
24/// - `Machine`: `M`
25/// - `Tutor`: `T`
26/// - `Level`: `L#`, where `#` is the level number.
27/// - `Egg`: `E`
28/// - `Restricted`: `R`
29#[derive(Debug, Clone, PartialEq, Eq, Hash, SerializeStringEnum, DeserializeStringEnum)]
30pub enum MoveSource {
31    /// Taught manually by a Technical or Hidden Machine.
32    Machine,
33    /// Taught manually by a Move Tutor.
34    Tutor,
35    /// Learned on level up at the specified level.
36    Level(u8),
37    /// Learned only through breeding.
38    Egg,
39    /// Restricted to some forme.
40    Restricted,
41}
42
43impl FromStr for MoveSource {
44    type Err = Error;
45    fn from_str(s: &str) -> Result<Self, Self::Err> {
46        match &s[0..1] {
47            "M" => Ok(Self::Machine),
48            "T" => Ok(Self::Tutor),
49            "L" => {
50                let level_str = &s[1..];
51                let level = level_str.parse::<u8>().map_err(|err| {
52                    Into::<Error>::into(err).context(format!("invalid level: {level_str}"))
53                })?;
54                Ok(Self::Level(level))
55            }
56            "E" => Ok(Self::Egg),
57            "R" => Ok(Self::Restricted),
58            _ => Err(Error::msg(format!("invalid move source: {s}"))),
59        }
60    }
61}
62
63impl Display for MoveSource {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        match self {
66            Self::Machine => write!(f, "M"),
67            Self::Tutor => write!(f, "T"),
68            Self::Level(level) => write!(f, "L{level}"),
69            Self::Egg => write!(f, "E"),
70            Self::Restricted => write!(f, "R"),
71        }
72    }
73}
74
75/// A species learnset, which maps move names to how they are learned.
76pub type LearnSet = HashMap<String, HashSet<MoveSource>>;
77
78#[cfg(test)]
79mod move_source_test {
80    use crate::{
81        MoveSource,
82        test_util::test_string_serialization,
83    };
84
85    #[test]
86    fn serializes_to_string() {
87        test_string_serialization(MoveSource::Machine, "M");
88        test_string_serialization(MoveSource::Tutor, "T");
89        test_string_serialization(MoveSource::Level(10), "L10");
90        test_string_serialization(MoveSource::Level(25), "L25");
91        test_string_serialization(MoveSource::Egg, "E");
92    }
93}