1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use rand::distributions::WeightedIndex;
use rand::prelude::*;
use rand::Rng;

#[rustfmt::skip]
const ADJECTIVES: &[&str] = &[
    "Blue", "Bronze", "Brown", "Burgundy", "Driven", "Enchanted", "Gold", "Green", "Grey",
    "Grouchy", "Hallowed", "Happy", "Hidden", "Hungry", "Jovial", "Lone", "Lost", "Lucky",
    "Merry", "Moody", "Morose", "Orange", "Purple", "Red", "Silent", "Silver", "Thirsty",
    "Wasted", "Wild",
];

#[rustfmt::skip]
const LAND_ANIMALS: &[&str] = &[
    "Antelope", "Ape", "Baboon", "Badger", "Bat", "Bear", "Beaver", "Bee", "Beetle", "Boar",
    "Camel", "Cat", "Cow", "Deer", "Dog", "Donkey", "Dove", "Dragonfly", "Duck", "Eagle",
    "Elephant", "Elk", "Ermine", "Fox", "Frog", "Goat", "Goose", "Hare", "Hart", "Hawk",
    "Hedgehog", "Heron", "Herring", "Horse", "Hound", "Hyena", "Jackal", "Lamb", "Leopard",
    "Lion", "Magpie", "Mole", "Owl", "Panther", "Peacock", "Phoenix", "Pony", "Porcupine",
    "Rabbit", "Ram", "Rat", "Raven", "Salamander", "Scorpion", "Sheep", "Snake", "Spider",
    "Squirrel", "Stag", "Stoat", "Stork", "Swan", "Tiger", "Toad", "Tortoise",
    "Turkey", "Turtle", "Unicorn", "Vulture", "Weasel", "Wolf",
];

#[rustfmt::skip]
const COASTAL_ANIMALS: &[&str] = &[
    "Cormorant", "Crab", "Dolphin", "Herring", "Mermaid", "Octopus", "Osprey", "Otter",
    "Pelican", "Perch", "Salmon", "Seagull", "Seal", "Shark", "Starfish", "Squid", "Whale",
    "Whelk"
];

#[rustfmt::skip]
const ENEMIES: &[&str] = &[
    "Angel", "Bandit", "Brigand", "Centaur", "Chimera", "Demon", "Devil", "Dragon", "Fairy",
    "Ghost", "Giant", "Goblin", "Gorgon", "Gremlin", "Hag", "Harpy", "Hydra", "Imp", "Kappa",
    "Lich", "Manticore", "Minotaur", "Necromancer", "Oni", "Orc", "Peryton", "Pirate", "Roc",
    "Satyr", "Seraph", "Siren", "Sorcerer", "Sphinx", "Thief", "Trickster", "Troll", "Unicorn",
    "Vampire", "Werewolf", "Witch", "Wyvern", "Zombie",
];

#[rustfmt::skip]
const FOOD: &[&str] = &[
    "Barley", "Barrel", "Beef", "Beer", "Bread", "Cask", "Cheese", "Hop", "Keg", "Malt",
    "Mead", "Meat", "Mutton", "Pint", "Pork", "Potatoes", "Rye", "Tun", "Veal", "Venison",
    "Vine",
];

#[rustfmt::skip]
const GEMS: &[&str] = &[
    "Amber", "Agate", "Amethyst", "Aquamarine", "Beryl", "Citrine", "Diamond", "Emerald",
    "Opal", "Quartz", "Sapphire", "Topaz"
];

#[rustfmt::skip]
const PEOPLE: &[&str] = &[
    "Father", "Mother", "Parent", "Sibling", "Hunter", "Emperor", "Empress", "Warrior",
    "Sage", "Ancestor"
];

#[rustfmt::skip]
const PROFESSIONS: &[&str] = &[
    "Adventurer", "Baker", "Beggar", "Blacksmith", "Brewer", "Bricklayer", "Builder",
    "Butcher", "Carpenter", "Conjurer", "Cooper", "Diviner", "Enchanter", "Evoker", "Farrier",
    "Ferryman", "Fisherman", "Glazier", "Illusionist", "Knight", "Mage", "Magician", "Mason",
    "Miller", "Plumber", "Porter", "Printer", "Roper", "Sailor", "Shipwright", "Smith",
    "Soldier", "Waterman", "Warrior", "Wizard",
];

#[rustfmt::skip]
const SYMBOLS: &[&str] = &[
    "Abbey", "Anchor", "Anvil", "Arrow", "Axe", "Belfry", "Bell", "Book", "Buckle", "Cap",
    "Castle", "Column", "Crescent", "Crown", "Drum", "Feather", "Foil", "Hammer", "Harp",
    "Harrow", "Helmet", "Horseshoe", "Key", "Lance", "Lance", "Locket", "Mace", "Mill",
    "Mitre", "Moon", "Nail", "Oar", "Phalactary", "Rake", "Rook", "Scale", "Sceptre", "Scythe",
    "Ship", "Shovel", "Spear", "Spur", "Star", "Steeple", "Sun", "Sword", "Thunderbolt",
    "Tower", "Trumpet", "Wand", "Wheel",
];

pub fn adjective(rng: &mut impl Rng) -> &'static str {
    ListGenerator(ADJECTIVES).gen(rng)
}

pub fn cardinal_direction(rng: &mut impl Rng) -> &'static str {
    ListGenerator(&["North", "South", "East", "West"]).gen(rng)
}

pub fn enemy(rng: &mut impl Rng) -> &'static str {
    ListGenerator(ENEMIES).gen(rng)
}

pub fn food(rng: &mut impl Rng) -> &'static str {
    ListGenerator(FOOD).gen(rng)
}

pub fn gem(rng: &mut impl Rng) -> &'static str {
    ListGenerator(GEMS).gen(rng)
}

pub fn person(rng: &mut impl Rng) -> &'static str {
    ListGenerator(PEOPLE).gen(rng)
}

pub fn profession(rng: &mut impl Rng) -> &'static str {
    ListGenerator(PROFESSIONS).gen(rng)
}

pub fn symbol(rng: &mut impl Rng) -> &'static str {
    ListGenerator(SYMBOLS).gen(rng)
}

pub fn animal(rng: &mut impl Rng) -> &'static str {
    let dist = WeightedIndex::new([LAND_ANIMALS.len(), COASTAL_ANIMALS.len()]).unwrap();
    match dist.sample(rng) {
        0 => land_animal(rng),
        1 => coastal_animal(rng),
        _ => unreachable!(),
    }
}

pub fn land_animal(rng: &mut impl Rng) -> &'static str {
    ListGenerator(LAND_ANIMALS).gen(rng)
}

pub fn coastal_animal(rng: &mut impl Rng) -> &'static str {
    ListGenerator(COASTAL_ANIMALS).gen(rng)
}

pub struct ListGenerator(pub &'static [&'static str]);

impl ListGenerator {
    pub fn gen(&self, rng: &mut impl Rng) -> &'static str {
        self.0[rng.gen_range(0..self.0.len())]
    }
}