1use crate::world::place::PlaceData;
2use crate::world::Demographics;
3use rand::prelude::*;
4
5pub fn generate(place: &mut PlaceData, rng: &mut impl Rng, _demographics: &Demographics) {
6 place.name.replace_with(|_| name(rng));
7}
8
9fn name(rng: &mut impl Rng) -> String {
10 match rng.gen_range(0..=7) {
11 0 => format!("The {} {}", placement(rng), canyon_synonym(rng)),
12 1 => format!("{} {}", cardinal_direction(rng), canyon_synonym(rng)),
13 2 => format!("{} {}", adjective(rng), canyon_synonym(rng)),
14 3 => format!("{} {} {}", adjective(rng), thing(rng), canyon_synonym(rng)),
15 4..=5 => format!("{} {}", thing(rng), canyon_synonym(rng)),
16 6..=7 => format!("{}'s {}", profession(rng), canyon_synonym(rng)),
17 _ => unreachable!(),
18 }
19}
20
21fn thing(rng: &mut impl Rng) -> &'static str {
22 match rng.gen_range(0..=9) {
23 0 => other_animal(rng),
24 1..=4 => canyon_animal(rng),
25 5 => enemy(rng),
26 6 => food(rng),
27 7 => profession(rng),
28 8 => symbol(rng),
29 9 => gem(rng),
30 _ => unreachable!(),
31 }
32}
33
34fn adjective(rng: &mut impl Rng) -> &'static str {
35 #[rustfmt::skip]
36 const ADJECTIVES: &[&str] = &[
37 "Angry", "Awkward", "Bloated", "Driven", "Elegant", "Engorged",
38 "Enchanted", "Gold", "Green", "Grey", "Grouchy", "Hallowed", "Happy",
39 "Hidden", "Hungry", "Jovial", "Lone", "Lost", "Lucky", "Merry", "Moody",
40 "Morose", "Quiet", "Red", "Sickly", "Silent", "Silver", "Slim",
41 "Slender", "Solemn", "Starved", "Stoic", "Thirsty", "Wasted", "Wild",
42 "White", "Yellow"
43 ];
44 ADJECTIVES[rng.gen_range(0..ADJECTIVES.len())]
45}
46
47fn canyon_synonym(rng: &mut impl Rng) -> &'static str {
48 #[rustfmt::skip]
49 const CANYON_SYNONYMS: &[&str] = &[
50 "Canyon", "Canyon", "Ravine", "Ravine", "Gorge", "Gorge", "Crevice",
54 "Gap", "Abyss", "Flume", "Fissure", "Trench"
55 ];
56 CANYON_SYNONYMS[rng.gen_range(0..CANYON_SYNONYMS.len())]
57}
58
59fn other_animal(rng: &mut impl Rng) -> &'static str {
60 #[rustfmt::skip]
61 const LAND_ANIMALS: &[&str] = &[
62 "Antelope", "Ape", "Baboon", "Bat", "Bear", "Beaver", "Bee", "Beetle",
63 "Boar", "Cow", "Deer", "Dove", "Dragonfly", "Duck", "Elephant", "Elk",
64 "Ermine", "Frog", "Goose", "Hart", "Hedgehog", "Heron", "Herring",
65 "Horse", "Hound", "Lamb", "Leopard", "Lion", "Magpie", "Mole",
66 "Panther", "Peacock", "Phoenix", "Porcupine", "Rat", "Raven",
67 "Salamander", "Sheep", "Squid", "Squirrel", "Stag", "Stoat", "Stork",
68 "Swan", "Tiger", "Toad", "Turkey", "Turtle", "Unicorn", "Weasel"
69 ];
70 LAND_ANIMALS[rng.gen_range(0..LAND_ANIMALS.len())]
71}
72
73fn canyon_animal(rng: &mut impl Rng) -> &'static str {
74 #[rustfmt::skip]
75 const CANYON_ANIMALS: &[&str] = &[
76 "Camel", "Badger", "Scorpion", "Beetle", "Fox", "Gecko", "Viper",
77 "Snake", "Vulture", "Condor", "Dog", "Donkey", "Mule", "Owl", "Hyena",
78 "Coyote", "Lizard", "Cat", "Eagle", "Goat", "Ram", "Hawk", "Tortoise",
79 "Hare", "Ram", "Pony", "Rabbit", "Wolf"
80 ];
81 CANYON_ANIMALS[rng.gen_range(0..CANYON_ANIMALS.len())]
82}
83
84fn enemy(rng: &mut impl Rng) -> &'static str {
85 #[rustfmt::skip]
86 const ENEMIES: &[&str] = &[
87 "Angel", "Bandit", "Brigand", "Centaur", "Chimera", "Demon", "Devil",
88 "Dragon", "Fairy", "Ghost", "Giant", "Goblin", "Gorgon", "Gremlin",
89 "Hag","Harpy", "Hydra", "Imp", "Kappa", "Lich", "Manticore", "Minotaur",
90 "Necromancer", "Oni", "Orc", "Peryton", "Pirate", "Roc", "Satyr",
91 "Seraph", "Siren", "Sorcerer", "Sphinx", "Thief", "Trickster", "Troll",
92 "Unicorn", "Vampire", "Werewolf", "Witch", "Wyvern", "Zombie",
93 ];
94 ENEMIES[rng.gen_range(0..ENEMIES.len())]
95}
96
97fn food(rng: &mut impl Rng) -> &'static str {
98 #[rustfmt::skip]
99 const FOODS: &[&str] = &[
100 "Barley", "Barrel", "Beef", "Beer", "Bread", "Cask", "Cheese", "Hop",
101 "Keg", "Malt", "Mead", "Meat", "Mutton", "Pint", "Pork", "Potatoes",
102 "Rye", "Tun", "Veal", "Venison", "Vine",
103 ];
104 FOODS[rng.gen_range(0..FOODS.len())]
105}
106
107fn gem(rng: &mut impl Rng) -> &'static str {
108 #[rustfmt::skip]
109 const GEMS: &[&str] = &[
110 "Amber", "Agate", "Amethyst", "Aquamarine", "Beryl", "Citrine",
111 "Diamond", "Emerald", "Opal", "Quartz", "Sapphire", "Topaz"
112 ];
113 GEMS[rng.gen_range(0..GEMS.len())]
114}
115
116fn placement(rng: &mut impl Rng) -> &'static str {
117 #[rustfmt::skip]
118 const PLACEMENT: &[&str] = &["First", "Last"];
119 PLACEMENT[rng.gen_range(0..PLACEMENT.len())]
120}
121
122fn cardinal_direction(rng: &mut impl Rng) -> &'static str {
123 const CARDINAL_DIRS: &[&str] = &["North", "South", "East", "West"];
124 CARDINAL_DIRS[rng.gen_range(0..CARDINAL_DIRS.len())]
125}
126
127fn profession(rng: &mut impl Rng) -> &'static str {
128 #[rustfmt::skip]
129 const PROFESSIONS: &[&str] = &[
130 "Adventurer", "Baker", "Beggar", "Blacksmith", "Brewer", "Bricklayer",
131 "Builder", "Butcher", "Carpenter", "Conjurer", "Cooper", "Diviner",
132 "Enchanter", "Evoker", "Farrier", "Ferryman", "Fisherman", "Glazier",
133 "Illusionist", "Knight", "Mage", "Magician", "Mason", "Miller",
134 "Plumber", "Porter", "Printer", "Roper", "Sailor", "Shipwright",
135 "Smith", "Soldier", "Waterman", "Warrior", "Wizard",
136 ];
137 PROFESSIONS[rng.gen_range(0..PROFESSIONS.len())]
138}
139
140fn symbol(rng: &mut impl Rng) -> &'static str {
141 #[rustfmt::skip]
142 const SYMBOLS: &[&str] = &[
143 "Abbey", "Anchor", "Anvil", "Arrow", "Axe", "Belfry", "Bell", "Book",
144 "Buckle", "Cap", "Castle", "Column", "Crescent", "Crown", "Drum",
145 "Feather", "Foil", "Hammer", "Harp", "Harrow", "Helmet", "Horseshoe",
146 "Key", "Lance", "Lance", "Locket", "Mace", "Mill", "Mitre", "Moon",
147 "Nail", "Oar", "Phalactary", "Rake", "Rook", "Scale", "Sceptre",
148 "Scythe", "Ship", "Shovel", "Spear", "Spur", "Star", "Steeple", "Sun",
149 "Sword", "Thunderbolt", "Tower", "Trumpet", "Wand", "Wheel",
150 ];
151 SYMBOLS[rng.gen_range(0..SYMBOLS.len())]
152}
153
154#[cfg(test)]
155mod test {
156 use super::*;
157
158 #[test]
159 fn name_test() {
160 let mut rng = SmallRng::seed_from_u64(4);
161
162 #[rustfmt::skip]
163 assert_eq!(
164 ["Printer Gorge", "Viper Gorge", "The Last Flume", "West Fissure",
165 "Mage Canyon", "The First Crevice", "Tortoise Fissure",
166 "Badger Fissure", "Rye Ravine", "Porter's Fissure", "Ram Gorge",
167 "Cooper's Fissure", "Evoker's Abyss", "Porter's Ravine",
168 "Keg Flume", "Smith's Ravine", "Rabbit Trench", "Grey Pork Flume",
169 "Plumber Canyon", "Gorgon Canyon"]
170 .iter()
171 .map(|s| s.to_string())
172 .collect::<Vec<_>>(),
173 (0..20).map(|_| name(&mut rng)).collect::<Vec<String>>(),
174 );
175 }
176}