1use crate::utils::pluralize;
2use crate::world::place::PlaceData;
3use crate::world::{word, word::ListGenerator, Demographics};
4use rand::prelude::*;
5
6pub fn generate(place: &mut PlaceData, rng: &mut impl Rng, _demographics: &Demographics) {
7 place.name.replace_with(|_| name(rng));
8}
9
10fn name(rng: &mut impl Rng) -> String {
11 match rng.gen_range(0..10) {
12 0..=3 => format!("The {} {}", descriptor(rng), place(rng)),
13 4..=7 => format!("{} of {}", place(rng), deity(rng)),
14 8 => {
15 let (animal, s) = pluralize(word::animal(rng));
16 format!("Place Where the {}{} {}", animal, s, action(rng))
17 }
18 9 => {
19 let (animal, s) = pluralize(word::animal(rng));
20 format!("{} of the {} {}{}", place(rng), number(rng), animal, s)
21 }
22 _ => unreachable!(),
23 }
24}
25
26fn place(rng: &mut impl Rng) -> &'static str {
28 match rng.gen_range(0..6) {
29 0..=2 => "Shrine",
30 3..=4 => building(rng),
31 5 => feature(rng),
32 _ => unreachable!(),
33 }
34}
35
36fn building(rng: &mut impl Rng) -> &'static str {
38 ListGenerator(&[
39 "Altar", "Pagoda", "Gate", "Obelisk", "Pagoda", "Pillar", "Pillars",
40 ])
41 .gen(rng)
42}
43
44#[rustfmt::skip]
46fn feature(rng: &mut impl Rng) -> &'static str {
47 ListGenerator(&[
48 "Basin","Cavern","Grove","Pond","Pool","Menhir",
49 "Grotto","Cenote", "Tree", "Stones", "Cave"
50 ]).gen(rng)
51}
52
53fn descriptor(rng: &mut impl Rng) -> String {
55 match rng.gen_range(0..3) {
56 0..=1 => word::adjective(rng).to_string(),
57 2 => gerund(action(rng)),
58 _ => unreachable!(),
59 }
60}
61
62#[rustfmt::skip]
64fn action(rng: &mut impl Rng) -> String {
65 ListGenerator(&[
66 "Dance","Whisper","Shiver","Rot","Rise","Fall","Laugh","Travel","Creep",
67 "Sing","Fade","Glow","Shine","Stand","Weep","Drown","Howl","Smile","Hunt",
68 "Burn","Return","Dream","Wake","Slumber"
69 ]).gen(rng).to_string()
70}
71
72fn gerund(verb: String) -> String {
73 let last_char = verb.chars().last().unwrap();
74 let last_two_chars = &verb[verb.len() - 2..verb.len()];
75 if last_char == 'e' {
76 format!("{}ing", &verb[..verb.len() - 1])
77 } else if last_two_chars == "ot" {
78 format!("{}ting", &verb)
79 } else if last_two_chars == "el" {
80 format!("{}ling", &verb)
81 } else {
82 format!("{}ing", verb)
83 }
84}
85
86#[rustfmt::skip]
87fn number(rng: &mut impl Rng) -> &'static str {
88 ListGenerator(&[
89 "Two","Three","Four","Five","Six","Seven","Eight","Eight-and-a-Half","Nine",
90 "Twelve","Thirty-Six", "Forty","Seventy-Two","Nine-and-Twenty", "Ninety-Nine","Thousand","Thousand-Thousand"
91 ]).gen(rng)
92}
93
94fn deity(rng: &mut impl Rng) -> String {
96 match rng.gen_range(0..10) {
97 0..=1 => format!("the {}", word::person(rng)),
98 2 => format!("the {} {}", descriptor(rng), word::person(rng)),
99 3..=4 => format!("the {}", word::animal(rng)),
100 5 => format!("the {} {}", descriptor(rng), word::animal(rng)),
101 6..=8 => concept(rng).to_string(),
102 9 => format!("{} {}", descriptor(rng), concept(rng)),
103 _ => unreachable!(),
104 }
105}
106
107#[rustfmt::skip]
109fn concept(rng: &mut impl Rng) -> &'static str {
110 ListGenerator(&[
111 "Love","Knowledge","Wisdom","Truth","Justice","Mercy","Protection","Healing","Strength","Courage",
112 "Fortune","Prosperity","Storms","Fire","Water","Earth","Air","Dreams","Music","Poetry","Dance",
113 "Ancestors","Transcendence","Anguish","Blight","Confessions","Connections","Courage","Decay",
114 "Lore","Silence","Triumph","Wisdom","Mending","Healing","Judgement","Forgiveness","Justice","Textiles",
115 ]).gen(rng)
116}
117
118#[cfg(test)]
119mod test {
120 use super::*;
121
122 #[test]
123 fn name_test() {
124 let mut rng = SmallRng::seed_from_u64(0);
125
126 assert_eq!(
127 [
128 "Shrine of the Pelican",
129 "Place Where the Weasels Drown",
130 "The Gold Pillar",
131 "The Singing Cave",
132 "The Fading Basin",
133 "The Grey Gate",
134 "The Creeping Shrine",
135 "The Red Shrine",
136 "Pillar of the Five Camels",
137 "The Wasted Pagoda",
138 "Shrine of the Empress",
139 "The Singing Shrine",
140 "Place Where the Unicorns Weep",
141 "Gate of the Emperor",
142 "The Orange Tree",
143 "The Creeping Shrine",
144 "Gate of the Thirty-Six Rams",
145 "Shrine of the Wild Cat",
146 "The Wasted Altar",
147 "Shrine of Forgiveness"
148 ]
149 .iter()
150 .map(|s| s.to_string())
151 .collect::<Vec<_>>(),
152 (0..20).map(|_| name(&mut rng)).collect::<Vec<String>>(),
153 );
154 }
155}