initiative_core/world/npc/species/
half_orc.rs

1use super::{Age, Gender, Generate, Size};
2use rand::prelude::*;
3
4pub struct Species;
5
6impl Generate for Species {
7    fn gen_gender(rng: &mut impl Rng) -> Gender {
8        match rng.gen_range(1..=101) {
9            1..=50 => Gender::Feminine,
10            51..=100 => Gender::Masculine,
11            101 => Gender::NonBinaryThey,
12            _ => unreachable!(),
13        }
14    }
15
16    fn gen_age_years(rng: &mut impl Rng) -> u16 {
17        rng.gen_range(0..=79)
18    }
19
20    fn gen_years_from_age(rng: &mut impl Rng, age: &Age) -> u16 {
21        rng.gen_range(match age {
22            Age::Infant => return 0,
23            Age::Child => 1..=7,
24            Age::Adolescent => 8..=14,
25            Age::YoungAdult => 15..=19,
26            Age::Adult => 20..=34,
27            Age::MiddleAged => 35..=54,
28            Age::Elderly => 55..=64,
29            Age::Geriatric => 65..=79,
30        })
31    }
32
33    fn age_from_years(years: u16) -> Age {
34        match years {
35            i if i < 1 => Age::Infant,
36            i if i < 8 => Age::Child,
37            i if i < 15 => Age::Adolescent,
38            i if i < 20 => Age::YoungAdult,
39            i if i < 35 => Age::Adult,
40            i if i < 55 => Age::MiddleAged,
41            i if i < 65 => Age::Elderly,
42            _ => Age::Geriatric,
43        }
44    }
45
46    fn gen_size(rng: &mut impl Rng, _age_years: u16, _gender: &Gender) -> Size {
47        let size = rng.gen_range(1..=8) + rng.gen_range(1..=8);
48        Size::Medium {
49            height: 60 + size,
50            weight: 130 + size * 6,
51        }
52    }
53}
54
55#[cfg(test)]
56mod test_generate_for_species {
57    use super::*;
58    use std::collections::HashMap;
59
60    #[test]
61    fn gen_gender_test() {
62        let mut rng = SmallRng::seed_from_u64(0);
63        let mut genders: HashMap<String, u16> = HashMap::new();
64
65        for _ in 0..500 {
66            let gender = Species::gen_gender(&mut rng);
67            *genders.entry(format!("{}", gender)).or_default() += 1;
68        }
69
70        assert_eq!(3, genders.len());
71        assert_eq!(Some(&3), genders.get("non-binary (they/them)"));
72        assert_eq!(Some(&233), genders.get("feminine (she/her)"));
73        assert_eq!(Some(&264), genders.get("masculine (he/him)"));
74    }
75
76    #[test]
77    fn gen_age_years_test() {
78        let mut rng = SmallRng::seed_from_u64(0);
79
80        assert_eq!(
81            [35, 35, 78, 36, 71],
82            [
83                Species::gen_age_years(&mut rng),
84                Species::gen_age_years(&mut rng),
85                Species::gen_age_years(&mut rng),
86                Species::gen_age_years(&mut rng),
87                Species::gen_age_years(&mut rng),
88            ],
89        );
90    }
91
92    #[test]
93    fn gen_years_from_age_test() {
94        let ages = [
95            Age::Infant,
96            Age::Child,
97            Age::Adolescent,
98            Age::YoungAdult,
99            Age::Adult,
100            Age::MiddleAged,
101            Age::Elderly,
102            Age::Geriatric,
103        ];
104
105        for age in ages {
106            let mut rng = SmallRng::seed_from_u64(0);
107
108            for _ in 0..10 {
109                let age_years = Species::gen_years_from_age(&mut rng, &age);
110                assert_eq!(age, Species::age_from_years(age_years));
111            }
112        }
113    }
114
115    #[test]
116    fn age_from_years_test() {
117        assert_eq!(Age::Infant, Species::age_from_years(0));
118
119        assert_eq!(Age::Child, Species::age_from_years(1));
120        assert_eq!(Age::Child, Species::age_from_years(7));
121
122        assert_eq!(Age::Adolescent, Species::age_from_years(8));
123        assert_eq!(Age::Adolescent, Species::age_from_years(14));
124
125        assert_eq!(Age::YoungAdult, Species::age_from_years(15));
126        assert_eq!(Age::YoungAdult, Species::age_from_years(19));
127
128        assert_eq!(Age::Adult, Species::age_from_years(20));
129        assert_eq!(Age::Adult, Species::age_from_years(34));
130
131        assert_eq!(Age::MiddleAged, Species::age_from_years(35));
132        assert_eq!(Age::MiddleAged, Species::age_from_years(54));
133
134        assert_eq!(Age::Elderly, Species::age_from_years(55));
135        assert_eq!(Age::Elderly, Species::age_from_years(64));
136
137        assert_eq!(Age::Geriatric, Species::age_from_years(65));
138        assert_eq!(Age::Geriatric, Species::age_from_years(u16::MAX));
139    }
140
141    #[test]
142    fn gen_size_test() {
143        let mut rng = SmallRng::seed_from_u64(0);
144        let t = Gender::NonBinaryThey;
145
146        let size = |height, weight| Size::Medium { height, weight };
147
148        assert_eq!(
149            [
150                size(68, 178),
151                size(72, 202),
152                size(76, 226),
153                size(69, 184),
154                size(71, 196),
155            ],
156            [
157                Species::gen_size(&mut rng, 0, &t),
158                Species::gen_size(&mut rng, 0, &t),
159                Species::gen_size(&mut rng, 0, &t),
160                Species::gen_size(&mut rng, 0, &t),
161                Species::gen_size(&mut rng, 0, &t),
162            ]
163        );
164    }
165}