Ejemplo n.º 1
0
    def __init__(self, filename):
        # Temporary Raw Data
        df = read_csv(filename)
        df['Type'] = df['Type'].str.title()
        df['Flavors'] = df['Flavors'].str.replace('/', ',')
        df['Strain'] = df['Strain'].apply(self._fix_string)
        df['Description'] = df['Description'].apply(self._fix_string)

        # Initialize Lookup Tables
        self.data = df.to_dict(orient='records')  # List[Dict {Key: Value}]
        self.effect_lookup = defaultdict(list)  # Dict {Key: List[String]}
        self.flavor_lookup = defaultdict(list)  # Dict {Key: List[String]}
        self.type_lookup = defaultdict(list)  # Dict {Key: List[String]}
        self.name_lookup = dict()  # Dict {Key: Dict {Key: Value}}
        self.id_lookup = defaultdict(list)

        # Populate Lookup Tables
        for strain in self.data:
            strain['Nearest'] = self._names_by_ids(
                strain['Nearest'].split(','))
            strain['Nearest'].remove(strain['Strain'])
            strain['Effects'] = strain['Effects'].split(',')
            for effect in strain['Effects']:
                self.effect_lookup[effect].append(strain['Strain'])

            strain['Flavors'] = strain['Flavors'].split(',')
            for flavor in strain['Flavors']:
                self.flavor_lookup[flavor].append(strain['Strain'])

            self.type_lookup[strain['Type']].append(strain['Strain'])
            self.name_lookup[strain['Strain']] = strain

        # Setup Randomizers
        self.random_by_type = FlexCat(
            {k: v
             for k, v in self.type_lookup.items()},
            val_bias='truffle_shuffle',
        )
        self.random_by_effect = FlexCat(
            {k: v
             for k, v in self.effect_lookup.items()},
            val_bias='truffle_shuffle',
        )
        self.random_by_flavor = FlexCat(
            {k: v
             for k, v in self.flavor_lookup.items()},
            val_bias='truffle_shuffle',
        )
Ejemplo n.º 2
0
    def __init__(self, filename):
        # Temporary Raw Data
        df = pd.read_csv(filename)

        # Pickled Models
        self.tfidf = pickle.load(open('pickles/tfidf.pickle', 'rb'))
        self.nearest_one = pickle.load(open('pickles/nearest.pickle', 'rb'))

        # Initialize Lookup Tables
        self.data = df.to_dict(orient='records')  # List[Dict {Key: Value}]
        self.effect_lookup = defaultdict(list)  # Dict {Key: List[String]}
        self.flavor_lookup = defaultdict(list)  # Dict {Key: List[String]}
        self.type_lookup = defaultdict(list)  # Dict {Key: List[String]}
        self.name_lookup = dict()  # Dict {Key: Dict {Key: Value}}
        self.id_lookup = defaultdict(list)

        # Populate Lookup Tables
        for strain in self.data:
            strain['Nearest'] = self._names_by_ids(
                strain['Nearest'].split(','))
            strain['Effects'] = strain['Effects'].split(',')
            for effect in strain['Effects']:
                self.effect_lookup[effect].append(strain['Name'])

            strain['Flavors'] = strain['Flavors'].split(',')
            for flavor in strain['Flavors']:
                self.flavor_lookup[flavor].append(strain['Name'])

            self.type_lookup[strain['Type']].append(strain['Name'])
            self.name_lookup[strain['Name']] = strain

        # Setup Randomizers
        self.random_by_type = FlexCat(
            {k: v
             for k, v in self.type_lookup.items()},
            val_bias='truffle_shuffle',
        )
        self.random_by_effect = FlexCat(
            {k: v
             for k, v in self.effect_lookup.items()},
            val_bias='truffle_shuffle',
        )
        self.random_by_flavor = FlexCat(
            {k: v
             for k, v in self.flavor_lookup.items()},
            val_bias='truffle_shuffle',
        )
Ejemplo n.º 3
0
class Trap:
    type = "Trap"
    spot_dc = 10
    save_dc = 11
    rank_0_damage = "1d2"
    rank_1_damage = "2d4"
    rank_2_damage = "3d6"
    rank_3_damage = "4d8"
    rank_4_damage = "5d10"
    random_ability = TruffleShuffle(("CON", "STR", "DEX", "INT", "WIS"))
    random_trap = FlexCat(
        {
            'bludgeoning': (
                "Falling Rocks",
                "Swinging Hammer",
                "Falling Chandelier",
            ),
            'falling': (
                "Deep Pit",
                "Spring Loaded Floor Tile",
                "Greased Slide",
                "False Floor",
            ),
            'piercing': (
                "Spiked Pit",
                "Guided Arrow",
                "Flying Broken Glass",
                "Falling Chandelier of Spikes",
            ),
            'slashing': (
                "Swinging Blade",
                "Guillotine",
                "Hooks and Chains",
                "Cloud of Daggers",
                "Exploding Mirror",
            ),
            'poison': (
                "Poison Dart",
                "Noxious Gas",
                "Pit Vipers",
                "Exploding Rotten Corpse",
            ),
            'acid': (
                "Acid Spay",
                "Acid Pool",
                "Acidic Bile",
                "Dripping Acidic Goo",
            ),
            'fire': (
                "Flame Jet",
                "Explosive Gas",
                "Lava Pit",
                "Delayed Fireball Blast",
                "Inferno",
            ),
            'lightning': (
                "Lightning Rod",
                "Tesla Coil",
                "Electric Trip Wire",
                "Lightning Bolt",
            ),
            'cold': (
                "Frozen Ground",
                "Cone of Cold",
                "Hail Storm",
                "Freeze the Flesh",
                "Ice Lance",
            ),
            'necrotic': (
                "Putrid Spores",
                "Cloud of Decay",
                "Energy Drain",
                "Beam of Entropy",
            ),
        },
        key_bias="truffle_shuffle",
        val_bias="truffle_shuffle")

    def __init__(self, cr, dam_type=None):
        self.cr = CR(cr)
        self.save_vs = self.random_ability()
        self.xp = self.set_xp_by_cr(self.cr)
        if dam_type:
            self.damage_type = dam_type
        else:
            self.damage_type = self.random_trap.random_cat()
        self.name = self.random_trap(self.damage_type)
        self.damage = self.set_damage(self.cr)

    def set_damage(self, cr):
        if cr.val < 1:
            damage = self.rank_0_damage
        elif cr.val < 5:
            damage = self.rank_1_damage
        elif cr.val < 11:
            damage = self.rank_2_damage
        elif cr.val < 17:
            damage = self.rank_3_damage
        else:
            damage = self.rank_4_damage
        return damage

    @staticmethod
    def set_xp_by_cr(cr):
        xp_lookup = (
            10,
            25,
            50,
            100,
            200,
            450,
            700,
            1100,
            1800,
            2300,
            2900,
            3900,
            5000,
            5900,
            7200,
            8400,
            10000,
            11500,
            13000,
            15000,
            18000,
            20000,
            22000,
            25000,
            33000,
            41000,
            50000,
            62000,
            155000,
            155000,
            155000,
            155000,
            155000,
            155000,
            155000,
            155000,
            155000,
            155000,
            155000,
        )
        return xp_lookup[cr.key]

    def __lt__(self, other):
        return self.cr <= other.cr

    def to_dict(self):
        return {
            "Name": self.name,
            "Type": self.type,
            "CR": self.cr.string,
            "Spot & Disarm DC": self.spot_dc,
            "Save vs": f"{self.save_vs} DC {self.save_dc} for half damage",
            "Damage": f"{self.damage} {self.damage_type}",
            "Disarm XP": self.xp,
        }

    def __str__(self):
        output = "\n".join(
            itertools.chain((f"{k}: {v}" for k, v in self.to_dict().items()),
                            ('', )))
        return output
Ejemplo n.º 4
0
    type = "Legendary Trap"
    spot_dc = 20
    save_dc = 24
    rank_0_damage = "1d12"
    rank_1_damage = "2d12"
    rank_2_damage = "3d12"
    rank_3_damage = "4d12"
    rank_4_damage = "5d12"


random_trap_by_tier = FlexCat(
    {
        "0": (MinorTrap, ),
        "1": (MinorTrap, DangerousTrap, DeadlyTrap),
        "2": (DangerousTrap, MinorTrap, DeadlyTrap, EpicTrap),
        "3": (DeadlyTrap, DangerousTrap, EpicTrap, MinorTrap),
        "4": (DeadlyTrap, EpicTrap, DangerousTrap),
        "5": (DeadlyTrap, EpicTrap),
        "6": (LegendaryTrap, EpicTrap),
    },
    key_bias="front_linear",
    val_bias="front_linear")


def random_trap(cr, dam_type=None):
    tier = str(CR(cr).tier)
    return random_trap_by_tier(tier, cr, dam_type)


if __name__ == "__main__":
    print()
    for i in range(-3, 31):
Ejemplo n.º 5
0
basic_gear = FlexCat({
    "Simple Melee Weapon": (
        "Dagger", "Club", "Hand Axe", "Light Hammer", "Mace",
        "Javelin", "Spear", "Quarterstaff", "Greatclub", "Sickle",
    ),
    "Simple Ranged Weapon": (
        "Light Crossbow", "Dart", "Sling", "Shortbow",
    ),
    "Martial Melee Weapon": (
        "Long Sword", "War Pick", "Morningstar", "Flail", "Battleaxe",
        "Warhammer", "Lance", "Trident", "Greatsword", "Greataxe", "Glaive",
        "Halberd", "Maul", "Pike", "Whip", "Scimitar", "Shortsword", "Rapier",
        "Bastard Sword",
    ),
    "Martial Ranged Weapon": (
        "Heavy Crossbow", "Hand Crossbow", "Blowgun", "Longbow",
    ),
    "Costume": (
        lambda: f"{fabric()} Lingerie",
        "Fancy Costume",  "Nun Costume", "Animal Costume", "Monster Costume",
        "Maid Costume", "Vampire Costume", "Beholder Costume", "Ninja Costume",
        "Pirate Costume", "Royal Knight Costume",
    ),
    "Clothing": (
        lambda: f"{fabric()} Robes",
        lambda: f"{fabric()} Hat",
        lambda: f"{fabric()} Gloves",
        lambda: f"{fabric()} Shirt",
        lambda: f"{fabric()} Pants",
        lambda: f"{fabric()} Boots",
        lambda: f"{fabric()} Overcoat",
        "Noble Garb", "Royal Robes", "Villager Garb", "Rag Shirt", "Ball Gown",
        "Highborn Garb", "Kilt", "Apron, Boots, Gloves and Goggles", "Crude Hide",
        "Leather Chaps", "Royal Garb", "Fancy Dress", "Peasant Garb",
    ),
    "Light Armor": (
        "Padded Gambeson", "Leather Jerkin", "Bone Splint Tunic", "Studded Doublet",
    ),
    "Medium Armor": (
        "Chain Mail Shirt", "Ring Mail Tunic", "Scale Mail Suit", "Brigandine",
    ),
    "Heavy Armor": (
        "Plate Mail Suit: Breastplate & Gambeson",
        "Quarter Plate Suit: Breastplate, Gambeson, Gauntlets & Sabatons",
        "Half Plate Suit: Breastplate, Gambeson, Visor Helm, Pauldrons, "
        "Gauntlets & Sabatons",
        "Field Plate Suit: Breastplate, Gambeson, Visor Helm, Gorget, "
        "Pauldrons, Vambraces, Gauntlets, Cuisses Leggings & Sabatons",
    ),
    "Shield": (
        "Tower Shield", "Kite Shield", "Jousting Shield", "Heater Shield",
        "Round Shield", "Buckler",
    ),
    "Ammunition": (
        lambda: f"Quiver of {d(3) * 10} Arrows",
        lambda: f"Quiver of {d(3) * 10} Bolts",
        lambda: f"Bag of {d(3) * 10} Sling Stones",
        lambda: f"Box of {d(3) * 10} Blowgun Darts",
    )
}, key_bias="truffle_shuffle", val_bias="truffle_shuffle")
random_monster_by_type = FlexCat({
    'Aberration': [
        'Aboleth', 'Beholder', 'Spectator', 'Chuul', 'Cloaker',
        'Flumph', 'Gibbering Mouther', 'Grell', 'Intellect Devourer',
        'Mind Flayer', 'Mind Flayer Arcanist', 'Nothic', 'Otyugh',
        'Slaad Tadpole', 'Red Slaad', 'Blue Slaad', 'Green Slaad',
        'Gray Slaad', 'Death Slaad',
    ],
    'Beast': [
        'Allosaurus', 'Ankylosaurus', 'Pteranodon', 'Plesiosaurus',
        'Triceratops', 'Tyrannosaurus Rex', 'Stirge', 'Axe Beak', 'Ape',
        'Baboon', 'Badger', 'Bat', 'Black Bear', 'Blood Hawk', 'Boar',
        'Brown Bear', 'Cat', 'Crab', 'Camel', 'Constrictor Snake',
        'Crocodile', 'Deer', 'Draft Horse', 'Dire Wolf', 'Frog', 'Eagle',
        'Flying Snake', 'Elk', 'Elephant', 'Giant Badger', 'Giant Bat',
        'Giant Centipede', 'Giant Boar', 'Giant Ape', 'Giant Crab',
        'Giant Eagle', 'Giant Constrictor Snake', 'Giant Crocodile',
        'Giant Fire Beetle', 'Giant Frog', 'Giant Elk', 'Giant Lizard',
        'Giant Goat', 'Giant Hyena', 'Giant Octopus', 'Giant Rat',
        'Giant Owl', 'Giant Poisonous Snake', 'Giant Scorpion',
        'Giant Sea Horse', 'Giant Spider', 'Giant Shark', 'Giant Weasel',
        'Giant Wasp', 'Giant Toad', 'Giant Vulture', 'Goat', 'Hawk',
        'Giant Wolf Spider', 'Hunter Shark', 'Hyena', 'Jackal', 'Lion',
        'Killer Whale', 'Lizard', 'Mastiff', 'Mammoth', 'Octopus', 'Owl',
        'Mule', 'Panther', 'Poisonous Snake', 'Cave Bear', 'Polar Bear',
        'Quipper', 'Rat', 'Raven', 'Pony', 'Riding Horse', 'Reef Shark',
        'Rhinoceros', 'Saber-toothed Tiger', 'Sea Horse', 'Scorpion',
        'Spider', 'Swarm of Bats', 'Swarm of Insects',
        'Swarm of Quippers', 'Swarm of Poisonous Snakes', 'Vulture',
        'Swarm of Rats', 'Swarm of Ravens', 'Tiger', 'Weasel', 'Warhorse',
        'Wolf',
    ],
    'Celestial': [
        'Deva', 'Planetar', 'Solar', 'Couatl', 'Empyrean', 'Pegasus',
        'Unicorn',
    ],
    'Construct': [
        'Animated Armor', 'Flying Sword', 'Rug of Smothering',
        'Clay Golem', 'Flesh Golem', 'Stone Golem', 'Iron Golem',
        'Helmed Horror', 'Homunculus', 'Monodrone', 'Duodrone',
        'Tridrone', 'Quadrone', 'Pentadrone', 'Scarecrow',
        'Shield Guardian',
    ],
    'Dragon': [
        'Young Red Shadow Dragon', 'Ancient Black Dragon',
        'Black Dragon Wyrmling', 'Young Black Dragon',
        'Adult Black Dragon', 'Ancient Blue Dragon',
        'Blue Dragon Wyrmling', 'Young Blue Dragon', 'Adult Blue Dragon',
        'Ancient Green Dragon', 'Young Green Dragon',
        'Adult Green Dragon', 'Green Dragon Wyrmling',
        'Ancient Red Dragon', 'Red Dragon Wyrmling', 'Young Red Dragon',
        'Adult Red Dragon', 'Ancient White Dragon', 'Young White Dragon',
        'Adult White Dragon', 'White Dragon Wyrmling',
        'Ancient Brass Dragon', 'Young Brass Dragon',
        'Adult Brass Dragon', 'Brass Dragon Wyrmling',
        'Ancient Bronze Dragon', 'Young Bronze Dragon',
        'Adult Bronze Dragon', 'Bronze Dragon Wyrmling',
        'Ancient Copper Dragon', 'Young Copper Dragon',
        'Adult Copper Dragon', 'Copper Dragon Wyrmling',
        'Ancient Gold Dragon', 'Adult Gold Dragon',
        'Gold Dragon Wyrmling', 'Young Gold Dragon',
        'Ancient Silver Dragon', 'Adult Silver Dragon',
        'Silver Dragon Wyrmling', 'Young Silver Dragon', 'Dragon Turtle',
        'Young Faerie Dragon', 'Adult Faerie Dragon', 'Pseudodragon',
        'Wyvern',
    ],
    'Elemental': [
        'Azer', 'Air Elemental', 'Earth Elemental', 'Fire Elemental',
        'Water Elemental', 'Galeb Duhr', 'Gargoyle', 'Dao', 'Djinni',
        'Efreeti', 'Marid', 'Invisible Stalker', 'Magmin',
        'Dust Mephit', 'Ice Mephit', 'Mud Mephit', 'Magma Mephit',
        'Smoke Mephit', 'Steam Mephit', 'Fire Snake', 'Salamander',
        'Water Weird', 'Xorn',
    ],
    'Fey': [
        'Dryad', 'Green Hag', 'Sea Hag', 'Pixie', 'Satyr', 'Sprite',
        'Blink Dog',
    ],
    'Fiend': [
        'Cambion', 'Balor', 'Barlgura', 'Dretch', 'Chasme', 'Glabrezu',
        'Goristro', 'Manes', 'Hezrou', 'Marilith', 'Nalfeshnee', 'Quasit',
        'Shadow Demon', 'Vrock', 'Yochlol', 'Bearded Devil',
        'Barbed Devil', 'Bone Devil', 'Chain Devil', 'Erinyes',
        'Horned Devil', 'Ice Devil', 'Lemure', 'Imp', 'Pit Fiend',
        'Spined Devil', 'Gnoll Fang of Yeenoghu', 'Night Hag',
        'Hell Hound', 'Nightmare', 'Rakshasa', 'Incubus', 'Succubus',
        'Mezzoloth', 'Arcanaloth', 'Nycaloth', 'Ultroloth',
    ],
    'Giant': [
        'Cyclops', 'Ettin', 'Fomorian', 'Cloud Giant', 'Fire Giant',
        'Hill Giant', 'Frost Giant', 'Stone Giant', 'Storm Giant', 'Ogre',
        'Half Ogre', 'Oni', 'Troll',
    ],
    'Humanoid': [
        'Aarakocra', 'Bugbear', 'Bugbear Chief', 'Bullywug', 'Duergar',
        'Drow', 'Drow Elite Warrior', 'Drow Mage',
        'Drow Priestess of Lolth', 'Githyanki Warrior',
        'Githyanki Knight', 'Githzerai Monk', 'Githzerai Zerth',
        'Gnoll', 'Gnoll PackLord', 'Svirfneblin', 'Goblin',
        'Goblin Boss', 'Grimlock', 'Half Red Dragon Veteran',
        'Hobgoblin', 'Hobgoblin Captain', 'Hobgoblin Warlord',
        'Jackalwere', 'Kenku', 'Kobold', 'Winged Kobold', 'Kuo-toa',
        'Kuo-toa Whip', 'Kuo-toa Archpriest', 'Lizardfolk',
        'Lizardfolk Shaman', 'Lizard King', 'Lizard Queen', 'Werebear',
        'Wererat', 'Wereboar', 'Weretiger', 'Werewolf', 'Merfolk',
        'Orc', 'Orc War Chief', 'Orc Eye of Gruumsh', 'Orog',
        'Quaggoth', 'Quaggoth Thonot', 'Sahuagin',
        'Sahuagin Priestess', 'Sahuagin Baron', 'Thri-kreen',
        'Troglodyte', 'Yuan-ti Pureblood',
    ],
    'Monstrosity': [
        'Ankheg', 'Basilisk', 'Behir', 'Bulette', 'Carrion Crawler',
        'Centaur', 'Chimera', 'Cockatrice', 'Darkmantle',
        'Displacer Beast', 'Doppelganger', 'Drider', 'Ettercap',
        'Gorgon', 'Grick', 'Grick Alpha', 'Griffon', 'Harpy',
        'Hippogriff', 'Hook Horror', 'Hydra', 'Kraken', 'Lamia',
        'Manticore', 'Medusa', 'Merrow', 'Mimic', 'Minotaur',
        'Spirit Naga', 'Guardian Naga', 'Owlbear', 'Peryton',
        'Piercer', 'Purple Worm', 'Young Remorhaz', 'Remorhaz',
        'Roc', 'Roper', 'Rust Monster', 'Androsphinx', 'Gynosphinx',
        'Tarrasque', 'Umber Hulk', 'Yeti', 'Abominable Yeti',
        'Yuan-ti Abomination', 'Yuan-ti Malison', 'Death Dog',
        'Phase Spider', 'Winter Wolf', 'Worg',
    ],
    'Plant': [
        'Twig Blight', 'Needle Blight', 'Vine Blight', 'Shrieker',
        'Violet Fungus', 'Gas Spore', 'Myconid Sprout',
        'Quaggoth Spore Servant', 'Myconid Adult', 'Myconid Sovereign',
        'Shambling Mound', 'Treant', 'Awakened Shrub', 'Awakened Tree',
    ],
    'Ooze': [
        'Black Pudding', 'Gelatinous Cube', 'Gray Ooze', 'Ochre Jelly',
        'Gelatinous Sphere', 'Green Slime', 'Sewer Moss',
    ],
    'Undead': [
        'Banshee', 'Death Tyrant', 'Crawling Claw', 'Death Knight',
        'Demilich', 'Dracolich', 'Flameskull', 'Ghost',
        'Ghoul', 'Ghast', 'Lich', 'Mummy', 'Mummy Lord', 'Bone Naga',
        'Revenant', 'Shadow', 'Skeleton', 'Warhorse Skeleton',
        'Minotaur Skeleton', 'Specter', 'Poltergeist', 'Vampire',
        'Vampire Caster', 'Vampire Warrior', 'Vampire Spawn', 'Wight',
        'Will-o-wisp', 'Wraith', 'Zombie', 'Ogre Zombie',
        'Beholder Zombie',
    ],
}, key_bias="truffle_shuffle")
Ejemplo n.º 7
0
random_spell = FlexCat({
    "cantrip": (
        "Acid Splash",
        "Blade Ward",
        "Chill Touch",
        "Dancing Lights",
        "Fire Bolt",
        "Friends",
        "Guidance",
        "Light",
        "Mage Hand",
        "Mending",
        "Message",
        "Minor Illusion",
        "Poison Spray",
        "Prestidigitation",
        "Ray of Frost",
        "Resistance",
        "Sacred Flame",
        "Shocking Grasp",
        "Spare the Dying",
        "Thaumaturgy",
        "True Strike",
        "Vicious Mockery",
    ),
    "level_1": (
        "Alarm",
        "Animal Friendship",
        "Bane",
        "Bless",
        "Burning Hands",
        "Charm Person",
        "Chromatic Orb",
        "Color Spray",
        "Command",
        "Comprehend Languages",
        "Create or Destroy Water",
        "Cure Wounds",
        "Detect Evil and Good",
        "Detect Magic",
        "Detect Poison and Disease",
        "Disguise Self",
        "Dissonant Whispers",
        "Expeditious Retreat",
        "Faerie Fire",
        "False Life",
        "Feather Fall",
        "Find Familiar",
        "Fog Cloud",
        "Grease",
        "Guiding Bolt",
        "Healing Word",
        "Heroism",
        "Identify",
        "Illusory Script",
        "Inflict Wounds",
        "Jump",
        "Longstrider",
        "Mage Armor",
        "Magic Missile",
        "Protection from Evil and Good",
        "Purify Food and Drink",
        "Ray of Sickness",
        "Sanctuary",
        "Shield",
        "Shield of Faith",
        "Silent Image",
        "Sleep",
        "Speak with Animals",
        "Tasha's Hideous Laughter",
        "Tenser's Floating Disk",
        "Thunderwave",
        "Unseen Servant",
        "Witch Bolt",
    ),
    "level_2": (
        "Aid",
        "Alter Self",
        "Animal Messenger",
        "Arcane Lock",
        "Augury",
        "Blindness/Deafness",
        "Blur",
        "Calm Emotions",
        "Cloud of Daggers",
        "Continual Flame",
        "Crown of Madness",
        "Darkness",
        "Darkvision",
        "Detect Thoughts",
        "Enhance Ability",
        "Enlarge/Reduce",
        "Enthrall",
        "Find Traps",
        "Flaming Sphere",
        "Gentle Repose",
        "Gust of Wind",
        "Heat Metal",
        "Hold Person",
        "Invisibility",
        "Knock",
        "Lesser Restoration",
        "Levitate",
        "Locate Animals or Plants",
        "Locate Object",
        "Magic Mouth",
        "Magic Weapon",
        "Melf's Acid Arrow",
        "Mirror Image",
        "Misty Step",
        "Nystul's Magic Aura",
        "Phantasmal Force",
        "Prayer of Healing",
        "Protection from Poison",
        "Ray of Enfeeblement",
        "Rope Trick",
        "Scorching Ray",
        "See Invisibility",
        "Shatter",
        "Silence",
        "Spider Climb",
        "Spiritual Weapon",
        "Suggestion",
        "Warding Bond",
        "Web",
        "Zone of Truth",
    ),
    "level_3": (
        "Animate Dead",
        "Beacon of Hope",
        "Bestow Curse",
        "Blink",
        "Clairvoyance",
        "Counterspell",
        "Create Food and Water",
        "Daylight",
        "Dispel Magic",
        "Fear",
        "Feign Death",
        "Fireball",
        "Fly",
        "Gaseous Form",
        "Glyph of Warding",
        "Haste",
        "Hypnotic Pattern",
        "Leomund's Tiny Hut",
        "Lightning Bolt",
        "Magic Circle",
        "Major Image",
        "Mass Healing Word",
        "Meld into Stone",
        "Nondetection",
        "Phantom Steed",
        "Plant Growth",
        "Protection from Energy",
        "Remove Curse",
        "Revivify",
        "Sending",
        "Sleet Storm",
        "Slow",
        "Speak with Dead",
        "Speak with Plants",
        "Spirit Guardians",
        "Stinking Cloud",
        "Tongues",
        "Vampiric Touch",
        "Water Breathing",
        "Water Walk",
    ),
    "level_4": (
        "Arcane Eye",
        "Banishment",
        "Blight",
        "Compulsion",
        "Confusion",
        "Conjure Minor Elementals",
        "Control Water",
        "Death Ward",
        "Dimension Door",
        "Divination",
        "Evard's Black Tentacles",
        "Fabricate",
        "Faithful Hound",
        "Fire Shield",
        "Freedom of Movement",
        "Greater Invisibility",
        "Guardian of Faith",
        "Hallucinatory Terrain",
        "Ice Storm",
        "Leomund's Secret Chest",
        "Locate Creature",
        "Mordenkainen's Private Sanctum",
        "Otiluke's Resilient Sphere",
        "Phantasmal Killer",
        "Polymorph",
        "Stone Shape",
        "Stoneskin",
        "Wall of Fire",
    ),
    "level_5": (
        "Animate Objects",
        "Awaken",
        "Bigby's Hand",
        "Cloudkill",
        "Commune Contagion",
        "Cone of Cold",
        "Conjure Elemental",
        "Contact Other Plane",
        "Creation",
        "Dispel Evil and Good",
        "Dominate Person",
        "Dream",
        "Flame Strike",
        "Geas",
        "Greater Restoration",
        "Hallow",
        "Hold Monster",
        "Insect Plague",
        "Legend Lore",
        "Mass Cure Wounds",
        "Mislead",
        "Modify Memory",
        "Passwall",
        "Planar Binding",
        "Raise Dead",
        "Rary's Telepathic Bond",
        "Scrying",
        "Seeming",
        "Telekinesis",
        "Teleportation Circle",
        "Wall of Force",
        "Wall of Stone",
    ),
    "level_6": (
        "Arcane Gate",
        "Blade Barrier",
        "Chain Lightning",
        "Circle of Death",
        "Contingency",
        "Create Undead",
        "Disintegrate",
        "Drawmij's Instant Summons",
        "Eyebite",
        "Find the Path",
        "Flesh to Stone",
        "Forbiddance",
        "Harm",
        "Globe of Invulnerability",
        "Guards and Wards",
        "Heal",
        "Heroes' Feast",
        "Magic Jar",
        "Mass Suggestion",
        "Move Earth",
        "Otiluke's Freezing Sphere",
        "Otto's Irresistible Dance",
        "Planar Ally",
        "Programmed Illusion",
        "Sunbeam",
        "True Seeing",
        "Wall of Ice",
        "Word of Recall",
    ),
    "level_7": (
        "Conjure Celestial",
        "Delayed Blast",
        "Divine Word",
        "Etherealness",
        "Finger of Death",
        "Fire Storm",
        "Forcecage",
        "Mirage Arcane",
        "Mordenkainen's Magnificent Mansion",
        "Mordenkainen's Sword",
        "Plane Shift",
        "Prismatic Spray",
        "Project Image",
        "Regenerate",
        "Resurrection",
        "Reverse Gravity",
        "Sequester",
        "Simulacrum",
        "Symbol",
        "Teleport",
    ),
    "level_8": (
        "Antimagic Field",
        "Antipathy/Sympathy",
        "Clone",
        "Control Weather",
        "Demiplane",
        "Dominate Monster",
        "Earthquake",
        "Feeblemind",
        "Glibness",
        "Holy Aura",
        "Incendiary Cloud",
        "Maze",
        "Mind Blank",
        "Power Word Stun",
        "Sunburst",
        "Telepathy",
        "Trap the Soul",
    ),
    "level_9": (
        "Astral Projection",
        "Foresight",
        "Gate",
        "Imprisonment",
        "Mass Heal",
        "Meteor Swarm",
        "Power Word Heal",
        "Power Word Kill",
        "Prismatic Wall",
        "Shapechange",
        "Time Stop",
        "True Polymorph",
        "True Resurrection",
        "Weird",
        "Wish",
    )
})