From a408169bcc59f6505109ad4fa8e2cf4562e26f30 Mon Sep 17 00:00:00 2001 From: Howard Abrams Date: Sun, 2 Feb 2025 22:23:12 -0800 Subject: [PATCH] Adding a large collection of books to my library --- typeclasses/drinkables.py | 48 +++++---- typeclasses/pets.py | 4 +- typeclasses/readables.py | 213 ++++++++++++++++++++++++++++++++++++++ typeclasses/rooms.py | 8 +- utils/word_list.py | 4 +- 5 files changed, 249 insertions(+), 28 deletions(-) create mode 100755 typeclasses/readables.py diff --git a/typeclasses/drinkables.py b/typeclasses/drinkables.py index 2d9bd41..8f25559 100755 --- a/typeclasses/drinkables.py +++ b/typeclasses/drinkables.py @@ -6,6 +6,28 @@ from utils.word_list import routput, character_has, Token import random +TEA_TYPES = { + "black": "a rich, bold and [malty|fragrant|almost spicy] black tea", + "green": "a green tea with [grassy|floral|vanilla|vegetal] notes", + "oolong": "a complex and [earthy|floral] oolong", + "matcha": "a frothy and aromatic matcha of the most vibrant green", + "white": "a subtle tea with notes of [rose|berries|chamomile flowers]", + "pu-erh": "an earthy, almost mushroom flavored, pu-erh tea", + "puerh": "an earthy, almost mushroom flavored, pu-erh tea", + "barley": "a nutty herbal infusion of barley with just a hint of smokiness", + "chaga": "an earthy, mushroomy chaga infusion", + "hibiscus": "a dark red, tart herbal infusion of roselle flowers", + "chai": "a spicy chai tea, tempered with milk and sweetness", + "herbal": "an herbal infusion of [chamomile|mint|chicory root|lavender]", + "earl": "a flowery Earl Grey tea", + "chamomile": "a relaxing, yet subtle infusion of chamomile flowers that makes you want to go to sleep", + "mint": "a blend of peppermint and spearmint to create the ultimate minty herbal infusion", + "chrysanthemum": "a lovely, floral infusion of chrysanthemum flowers", + "dandelion": "a roasted herbal infusion of dandelions that tastes a bit like coffee", + "rooibos": "an almost [sweet and|] [woody|nutty|vanilla-y] rooibos herbal infusion", + # Why limit to teas ... sure, this tea pot could make coffee ... +} + TEACUP_DESCS = [ "A rustic, clay teacup carefully crafted on a wheel. Beautiful [dark red|olive green|navy blue] glaze.", "A fine example of Royal Albert teacup, sporting a design of violet azaleas. Perfect for a black tea.", @@ -34,16 +56,6 @@ EMPTY_MSGS = [ "It appears that you need to refill your tea cup." ] -TEA_TYPES = { - "black": "a rich and fragrant black tea", - "green": "a subtle green tea", - "oolong": "a complex and earthy oolong", - "macha": "a frothy macha", - "herbal": "an herbal infusion", - "earl": "a flowery Earl Gray", - "unknown": "tea", -} - class TeaCup(Object): fill_amount = 4 @@ -83,15 +95,15 @@ class Teapot(Object): def do_make_tea(self, drinker, args): words = Token(args) - if words.empty() or words.contains("tea"): - self.db.tea_type = random.choice(list(TEA_TYPES.keys())) - else: + tea_choice = [] + if not words.empty(): tea_choice = [tea for tea in TEA_TYPES.keys() if words.contains(tea)] - if len(tea_choice) > 0: - self.db.tea_type = tea_choice[0] - else: - self.db.tea_type = "unknown" - desc = TEA_TYPES[self.db.tea_type] + + if len(tea_choice) > 0: + self.db.tea_type = tea_choice[0] + else: + self.db.tea_type = random.choice(list(TEA_TYPES.keys())) + desc = routput(TEA_TYPES[self.db.tea_type]) self.db.desc = f"A large, brown teapot full of {desc}." drinker.msg(f"You make a teapot of {desc}.") diff --git a/typeclasses/pets.py b/typeclasses/pets.py index 6dcaa63..98ffee7 100755 --- a/typeclasses/pets.py +++ b/typeclasses/pets.py @@ -133,8 +133,10 @@ class Pet(Object): if self.hunger() != curr: self.location.msg_contents("|w%s|n\n" % self.hunger_appearance()) - if self.location.check_light_state: + try: self.location.check_light_state() + except AttributeError as e: + pass def return_appearance(self, looker, **kwargs): """ diff --git a/typeclasses/readables.py b/typeclasses/readables.py new file mode 100755 index 0000000..875c446 --- /dev/null +++ b/typeclasses/readables.py @@ -0,0 +1,213 @@ +#!/usr/bin/python + +from typeclasses.objects import Object +from typeclasses.rooms import DabblersRoom +from evennia import Command, CmdSet +from evennia.prototypes.spawner import spawn +from utils.word_list import routput, character_has, Token + +import random + +BOOK_EMOTIONS = [ + "sad", + "heartfelt", + "intense", + "plot twisting", + "confusing", + "fascinating", + "riveting", + "humorous", +] + +BOOK_TYPES = [ + "story", + "narrative", + "chronicle", + "tale", + "instructional", + "essay collection", +] + +BOOKS = { + # Each value should begin as if it follows an "of": + "I, Golem": "a non-carbon-based person who is also a non-conformist", + "Do Golems Dream of Awakened Sheep?": "a golem reaches out to its creator after years of therapy reveal his anger of his existential crisis is justified", + "The 13 Habits of Highly Effective Necromancers": "", + "Invisible Man": "when spells become permanent", + "Little Women": "famous female gnomes and hobbits through the centuries", + "Are You My Mummy?": "choosing your undead servants", + "How I Ate My Mother": "a lycanthrope confessional", + "Zen and the Art of Punching Dragons in the Face": "a pacifist monk, who's temple is burned, seeks revenge on the dragon who had spicy tacos and indigestion", + + "The Very Hungry Carrion Crawler": "an adorable little larve who grows and grows after consuming graveyard after graveyard", + "Pride and Phylacteries": "a group of narcissistic liches and their struggle for dominance and control of the land of lesser creatures", + "For Whom the Die Rolls": "a fool’s guide to dice games and gambling", + "Life and Mines of a Dwarf Prospector": "a adopted human and his attempt to blend in with her adopted dwarvish parents by starting a mining company. All works well until she delved too deep", + "The Pied Piper": "why you shouldn’t trust bards", + "Around the World in 80 Dimension Doors": "a contest between two wizards who, after a drunken bet, attempt to reach the Ninth Level of Hell and return", + "Along Came a Spider": "a dungeoneer’s guide to driders and the drow", + "The Boy Who Cried Roc": "a classic children’s tale about a boy that thought it funny to announce to the village there was a Roc nearby. One day there was, and the nobody believed him. He was the only survivor", + "Some Like it Hot": "a guide to fire elementals", + "Girls Gone Feywild": "a group of girls who discover a portal to the Wyldwoods, and find themselves attempting to navigate the drama of the Seelie Court of the Summer Queen. Hilarity ensues when they fail to bawk like a chicken when an Archfey utter the secret word, Pancakes", + "50 Shades of Fey": "young elf who discovers more about herself after making a pact with an Archfey of the Unseelie Court", + "A Handmaid’s Tail": "a collection of short stories by notable Tieflings", + "Adventures with Muck, Berries, and Fins": "a herbalist’s guide to useful foraging", + "Bond with the Wind": "a how to summon Air elementals", + "Eat, Prey, Club": "a young orc and her quest for true dominance", + "Fantastic Drinks and Where to Buy Them": "all the taverns in the land (obviously written by Nori Doublefist under the pseudonym, The Drunk Dwarf), cataloging the best and most curious drinks each tavern has to offer", + "For Whom the Bridge Troll": "a tragic love story of a misunderstood troll who lived under a bridge", + "Frank and his Stein": "a poor drunk named Frank", + "Harry Otter": "a young orphan druid who lives with his boring fighter uncle and aunt who denies the existence of druids. The story sees Harry start at the Druid school led by Albus Bumbledoor, the archdruid who loves to be a Bumblebee. Bumbledoor takes Harry under his gravity defying wings and tells him the true story about how his parents died and that he is known by all druids as The Otter Who Lived. He must now meet his destiny and fight the most evil druid of all time, Voldemoth. Featuring the great cast of: Ron the Weasel, Hermione Ranger (some people can never choose only one class), Hagrid the lover of all creatures, Severus Snake and many more", + "Harry Potter and the Sorcerer’s Kidney Stone": "how an ordinarily normal surgery gets complicated due to wild magic leaving Harry with unexpected results. Spoiler Harry gets magic and becomes Dr. Strange after prolonged contact with the Sorcerer’s insides", + "Pride and Prestidigitation": "a coven of witches as they vie for the attention, and affection, of a traveling wizard", + "The Ruler of the Bracelets": "two gnomes who find a bracelet of power, and they have to take it to the Burning Steppes and cast it into the Cauldron. They form the Brotherhood of the Bracelet. Along the way they’re trailed by a murloc named Gottom, who’s obsessed with the bracelet, and nine bracelet bogeymen. It could be a three-parter, called ‘Ruler of the Bracelet’. The first part would be called ‘The Brotherhood of the Bracelet’, followed by ‘A Couple of Towers’, with the climactic ending called ‘Hey, the King’s Back!’ Not bad", + "What to Expect When You’re Spectating": "the history of the four nations written by Xanathar, a famed Beholder and crime-boss", + "The Wyrm in the Willows": "small dragon from the countryside who learns to cook without burning the meal first", +} + +class CmdLookBook(Command): + """ + Respond with a new book to look at. + """ + key = "look book" + aliases = "l book" + + def func(self): + self.obj.do_look(self.caller) + +class CmdTakeBook(Command): + """ + Generate a new book to store it with the reader. + """ + key = "get book" + aliases = "take book" + + def func(self): + self.obj.do_take(self.caller) + +class CmdReadBook(Command): + """ + Return the inside contents of the book. + """ + key = "read" + aliases = "open book" + + def func(self): + self.obj.do_read(self.caller) + +class CmdBurnBook(Command): + """ + Destroy the instance of the book + """ + key = "burn book" + aliases = "burn book" + + def func(self): + self.obj.do_burn(self.caller) + +class CmdDropBook(Command): + """ + Drop the instance of the book + """ + key = "drop book" + aliases = "throw book" + + def func(self): + self.obj.do_burn(self.caller, drop=True) + + +class CmdSetBook(CmdSet): + # mergetype = "Replace" + priority = 2 + + def at_cmdset_creation(self): + self.add(CmdReadBook) + self.add(CmdBurnBook) + self.add(CmdDropBook) + + +class CmdSetShelf(CmdSet): + def at_cmdset_creation(self): + self.add(CmdLookBook) + self.add(CmdTakeBook) + +# ---------------------------------------------------------------------- + +class Book(Object): + def at_object_creation(self): + """ + called at creation + """ + self.cmdset.add_default(CmdSetBook, persistent=True) + + def do_read(self, reader): + reader.msg(self.db.inside) + self.location.msg_contents(routput(f"{reader.name} reads a book. You notice the title, |b{0}|n.".format(self.db.title)), exclude=reader) + + def do_burn(self, reader, drop=False): + if isinstance(reader.location, DabblersRoom): + if drop: + reader.msg("You drop the book, and it flaps its pages, and flies back to a section on the shelf. Gotta keep the room organized.") + else: + reader.msg("You throw the book in the fireplace. It immediately yelps, flaps its pages, and flies back to a section on the shelf.") + self.location.msg_contents(routput(f"{reader.name} throws a book in the fireplace! It immediately yelps, flaps it pages, and flies back to a shelf."), exclude=reader) + self.delete() + else: + if not drop: + reader.msg("I think you would need to go to Dabbler's House and burn the book in the fireplace there.") + self.delete() + + +class Books(Object): + book_prototype = { + "typeclass": "typeclasses.readables.Book", + "key": "book", + "desc": "An old, worn, leather-bound book.", + } + + def at_object_creation(self): + """ + called at creation + """ + self.cmdset.add_default(CmdSetShelf, persistent=True) + + def new_book_details(self): + title = random.choice(list(BOOKS.keys())) + return ( + title, + routput("""a [worn|barely read|pristine copy of a|] + [leather-bound|] book, titled, |b{0}|n + """.format(title)), + routput( + """ + You [open|open up|crack open] your book, entitled, + |b{0}|n, and read the {1} {2} of {3}. + """.format( + title, + random.choice(BOOK_EMOTIONS), + random.choice(BOOK_TYPES), + BOOKS[title] + ) + ) + ) + + def do_look(self, reader): + (self.db.last_title, self.db.last_desc, + self.db.last_inside) = self.new_book_details() + reader.msg(f"You see {self.db.last_desc}.") + + def do_take(self, reader): + if self.db.last_title: + booktype = self.book_prototype + booktype['desc'] = self.db.last_desc + + book = spawn(booktype)[0] + book.db.inside = self.db.last_inside + book.location = reader + + reader.msg("You pick up the book.") + self.db.last_title = None + self.db.last_desc = None + self.db.last_inside = None + else: + reader.msg("Which book do you want to take. The shelves are full of them. Perhaps you want to |blook|n at the |bbooks|n, first.") diff --git a/typeclasses/rooms.py b/typeclasses/rooms.py index e4443c5..f2f64be 100644 --- a/typeclasses/rooms.py +++ b/typeclasses/rooms.py @@ -239,13 +239,6 @@ class DarkRoom(Room): or any(o for o in obj.contents if o.db.is_giving_light) ) - def _heal(self, character): - """ - Heal a character. - """ - health = character.db.health_max or 20 - character.db.health = health - def check_light_state(self, exclude=None): """ This method checks if there are any light sources in the room. @@ -296,6 +289,7 @@ class DarkRoom(Room): # it may be carrying. self.check_light_state(exclude=obj) + class DabblersRoom(Room): teacup_prototype = { "typeclass": "typeclasses.drinkables.TeaCup", diff --git a/utils/word_list.py b/utils/word_list.py index 2195da2..e7faa5c 100755 --- a/utils/word_list.py +++ b/utils/word_list.py @@ -15,7 +15,7 @@ class Token(): def contains(self, word): if len(self.words) > 0: - result = [True for w in self.words if w == word] + result = [True for w in self.words if w.lower() == word.lower()] if len(result) > 0: return result[0] @@ -37,7 +37,7 @@ def character_has(holder, item): def squish(text): "Remove series of spaces from the text." - return re.sub(' *', ' ', text) + return re.sub('[ \n\t]+', ' ', text).strip() def routput(string): """