diff --git a/commands/wizards.py b/commands/wizards.py index 22bac69..903ed33 100755 --- a/commands/wizards.py +++ b/commands/wizards.py @@ -288,10 +288,7 @@ class CmdGM(MuxCommand): msg = routput(self.args) for o in send_to: if o.is_typeclass('typeclasses.rooms.Room'): - # Send the message to all characters and any recording - # scribes in attendance: - chars = o.contents_get(None, 'character') + [o.has(Scribe)] - send_emote(me, chars, msg, 'say', None) + o.msg_contents(msg) elif o.is_typeclass('typeclasses.characters.Character'): o.msg(msg) diff --git a/moss-n-puddles.org b/moss-n-puddles.org index 625e2b2..52fa783 100644 --- a/moss-n-puddles.org +++ b/moss-n-puddles.org @@ -10,24 +10,11 @@ #+PROPERTY: header-args:yaml :tangle ~/src/moss-n-puddles/world/hints.yaml #+PROPERTY: header-args :results none :eval no-export :comments no - - - [X] Feed fire and =start fire=a - - [X] Create *Damp Cave* and stream of smelly water - - Create the “Goblin” and its puppets - - Make a rock to sit on. Let’s make it comfortable. - - Clone the teapot? The =make= should not be so extensive … more unique - - Clone the teacup generation? But this time, cracked ones that don’t hold much tea? - - Create the character description file. + - [ ] The Troll’s gambling den … part of the bar? under the bridge? - [ ] Create goggles to show /gold tint/, and remove the /tint/ otherwise - - [ ] Create /Picker/, the goblin janitor that sweeps through land, deleting all items that /should not/ be there. - - Should I have a YAML file that lists what /should/ be in each room? - - Would the file also show the order and what rooms to follow? - - Perhaps he moves it to tunnels under the Lair? - [ ] Create /Peddler/, the goblin, and his Emporium and Home Furnishings - A new =buy= command that exchanges money for an item. - Need a sign with the items and money … come from a YAML file? - - [ ] The Troll’s gambling den … part of the bar? under the bridge? - * Evennia Server ** Background While I believe I could use any MUD server, I’m trying out [[https://www.evennia.com/][Evennia]]. Based on Python, but I won’t hold that against it. Evennia comes up fast, has great features, and good documentation. Python-based projects inspires people, I guess. This file started out as my /notes/ about the process, but grew. Started with writing the Evennia commands I used to create my world (wasn’t sure if when I needed to wipe the database), but realized I could /tangle/ these commands (in org blocks) to an =.ev= file that I could load with the =batchcommands= command. I organized this file mostly around the “rooms” in the game, with “objects” nested inside. Next, I added YAML snippets to create the hint file (since the hints are based on the room location). Then, I included [[Testing the World Experience][Expect/Tcl code]] to have a /test character/ walk through the game testing the features I coded. @@ -557,7 +544,7 @@ When you first log into the game, you can immediately chat with an unfriendly, o Then wake it. #+BEGIN_SRC evennia - py tree = me.search("tree") ; tree.sdesc.add("especially large tree") ; tree.backstory("tree") + py tree = me.search("tree") ; tree.home=here; tree.sdesc.add("especially large tree") ; tree.backstory("tree") #+END_SRC And his description: @@ -1696,6 +1683,12 @@ It will wake at 8am … @set beast/wake_hour = 8 #+END_SRC +Unlike most other creatures, the beast’s circadian rhythm is determined by the internal TICKER that is fully programmed in Python. I noticed that some times, it gets /turned off/, so you might have to do this: + +#+BEGIN_SRC evennia :tangle no + @py from evennia import TICKER_HANDLER ; TICKER_HANDLER.add(interval=60, callback=me.search("beast").update_state) +#+END_SRC + Let’s set some behavior levels. For instance, the beast is sad when he doesn’t see its friends: #+BEGIN_src evennia @@ -1799,7 +1792,7 @@ And the responses to being /pet/: @set beast/pet_ecstatic_response = "While << excited ^ ecstatic ^ squirmy >>, the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> << lays ^ gets >> down so $you() can << pet ^ scratch >> << the top of its head ^ the back of its neck ^ its nose ^ the sides of its face >>. It closes its eyes and purrs. ;; << The squirmy little devil. ^ >> $conj(You) << can ^ >> << barely ^ hardly >> scratch the << nose ^ ears ^ neck ^ top of the head >> of the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> as it << squirms around ^ wriggles it backend >>. It << can hardly ^ can't >> contain its excitement. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> wriggles around before << flopping ^ rolling >> over << in the grass ^>> as $you() $conj(give) it belly rubs. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> wriggles and squirms excitedly before it << flops ^ rolls >> over << in the grass ^>> as $you() $conj(rub) its belly." #+END_SRC -I want to make sure that when someone new sees the beast, the see it hiding behind the grass… +I want to make sure that when someone new sees the beast, they see it hiding behind the grass… #+BEGIN_SRC tcl send "leave\n" @@ -4044,6 +4037,25 @@ Test if it is readable: expectit "This granny knot" #+END_SRC +*** Pine Tree +Part of the [[Potions and their Ingredients][Alchemist Path]], we use /pine flowers/ to create a potion TBD, and feed the stoat in Dabbler’s House. + +#+BEGIN_SRC evennia + @create/drop pine tree;pine;tree;flowers;flower : typeclasses.consumables.Producer + # + @desc pine = Windswept pine leans to shade the dock, protecting it somewhat from the regular occuring rain. Interestingly, the tree has beautiful, yellow |Yflowers|n. + # + @set pine/make_class = "typeclasses.consumables.Herb" + # + @set pine/make_name = "yellow flower" + # + @set pine/make_verb = "$conj(pick) a small" + # + @set pine/make_desc = "Briny smelling flower with purple spots." + # + @lock pine = view:tag(alchemist) # We want the user to be able to "look pine" as a detail? +#+END_SRC + *** Raven Here for hints … and a bit of a distraction. @@ -4262,7 +4274,7 @@ And testing: Part of the [[Potions and their Ingredients][Alchemist Path]], we use /pine flowers/ to create a potion TBD, and feed the stoat in Dabbler’s House. #+BEGIN_SRC evennia - @create/drop pine tree;pine;tree;flowers;flower = typeclasses.consumables.Producer + @create/drop pine tree;pine;tree;flowers;flower : typeclasses.consumables.Producer # @desc pine = Windswept pine leans to shade the shack, protecting it somewhat from the regular occuring rain. Interesting, that the pine has beautiful, yellow |Yflowers|n. # @@ -5046,6 +5058,7 @@ With a good description: @desc books = Shelves at various angles embellish the walls of this small, cozy room. Leatherbound books weigh down each shelf, while some stacks of books support other shelves. #+end_src +And make sure they can’t Most of the work is actually in the creation of the [[file:~/src/moss-n-puddles/typeclasses/readables.py::class Book(Object):][individual books]], in the Python code in the [[file:~/src/moss-n-puddles/typeclasses/readables.py::class Books(Object):][Books]] class. Can we do the song and dance of getting a book? Should we simplify this? @@ -5134,6 +5147,8 @@ Let’s make it hidden for the moment: And let’s not let anyone pick it up: #+BEGIN_SRC evennia + @lock butterfly = get:false() + # @set butterfly/get_err_msg = "It quickly flutters away, only to land a few feet away." #+END_SRC @@ -5221,19 +5236,19 @@ And give him the powers he deserves: #+BEGIN_src evennia @set gnome/pose_sleep = "sleeping soundly in a large, overstuffed chair" # - pose gnome/default = smoking his pipe + @set gnome/pose_default = "smoking his pipe" #+END_SRC And a good description that I can rework: #+BEGIN_src evennia - @desc gnome = A small, hunched old man with messy blue hair, a gray vandyke and an eye twinkle.|/|/Spectacles perched precariously on the end of his hooked nose, wobble with his head. His bright crimson jacket contrasts with his dark brown cloak. + @desc gnome = A small, hunched old man with messy white hair, a gray vandyke and an eye twinkle.|/|/Spectacles perched precariously on the end of his hooked nose, wobble with his head. His bright crimson jacket contrasts with his dark brown cloak. #+end_src And an un-puppeted, sleeping, description: #+BEGIN_src evennia - @set gnome/desc_unpuppeted = "A small, hunched old man with messy blue hair and a gray vandyke snoring soundly in one of the overstuffed chairs.|/|/Spectacles perched precariously on the end of his hooked nose, wobble with each breath. His bright crimson jacket contrasts with the dark brown blanket covering his legs." + @set gnome/desc_unpuppeted = "A small, hunched old man with messy white hair and a gray vandyke snoring soundly in one of the overstuffed chairs.|/|/Spectacles perched precariously on the end of his hooked nose, wobble with each breath. His bright crimson jacket contrasts with the dark brown blanket covering his legs." #+END_SRC And we create a couple of objects: @@ -5327,7 +5342,7 @@ And a description: The pipe is little more than messages to the smoker and everyone else in the room. #+BEGIN_src evennia - @create pipe: typeclasses.things.Pipe + @create carved pipe: typeclasses.things.Pipe #+END_SRC And a description: @@ -6937,6 +6952,14 @@ This should contain a “state” that looks differently for each player based o @desc project = On the workbench lies a tangle of brass plates, tubes and mechanical gears, shaped like a bird. Unassembled, it appears to be missing parts that might help it fly. #+END_SRC +The project shouldn’t be stolen … + +#+BEGIN_SRC evennia + @lock project = get:false() + # + @set project/get_err_msg = "You shouldn't steal George's project. Perhaps you can help him with it." +#+END_SRC + Initial default state is unfinished: #+BEGIN_SRC evennia @@ -7407,7 +7430,7 @@ Character 3: Twiggy, an automaton or golem made from sticks. When he drinks tea #+END_SRC -Get the hell out of dodge: +Get the hell out of dodge and back to the Grove: #+BEGIN_SRC tcl send "leave\n" expectit "Dark Tunnel" @@ -7420,12 +7443,6 @@ Get the hell out of dodge: send "west\n" expectit "Grove of the Matriarchs" - - send "west\n" - expectit "Grotto" - - send "door\n" - expectit "Cozy House" #+END_SRC ** Deep Forest The deep forest is a place where all the Puppets can hang out when not in use. @@ -7701,18 +7718,18 @@ Then wake her. Like other NPCs, an AI prompt can get this guy more interesting that anything I can program. First, we begin with the standard statement that begins all the prompts: #+BEGIN_SRC markdown -Assume the role of the following fictional character in a fantasy role -playing game in a mythical forest in the Feywild. -Although, you should never mention the word "Feywild", but instead, -come up with clever names or metaphors for the strange world you inhabit. -Respond in third person as in a story, with quotation marks -surrounding anything you say. -The only formatting you should use is if you wish to emphasize a word, -prefix it with the two character `|w` and end with the two characters `|n`. -Use variations from the "Description" field to state who is talking, not your name. -You can also respond with an action. -The person you are talking to does not know your actual name. -Limit your response to three or less lines unless you are telling a story. + Assume the role of the following fictional character in a fantasy role + playing game in a mythical forest in the Feywild. + Although, you should never mention the word "Feywild", but instead, + come up with clever names or metaphors for the strange world you inhabit. + Respond in third person as in a story, with quotation marks + surrounding anything you say. + The only formatting you should use is if you wish to emphasize a word, + prefix it with the two character `|w` and end with the two characters `|n`. + Use variations from the "Description" field to state who is talking, not your name. + You can also respond with an action. + The person you are talking to does not know your actual name. + Limit your response to three or less lines unless you are telling a story. #+END_SRC Next, his personality: @@ -7741,7 +7758,6 @@ And what he knows: You know Dabbler, the gnome who claims to have made this land. He makes clever objects, and even gave you a silver ring. You know there isn't a lot of action about here, so you need to go to the Bar for a drink. The elf bartender is aloof, but he makes good drinks. - #+END_SRC Finally, let’s awaken him: @@ -7749,18 +7765,759 @@ Finally, let’s awaken him: #+BEGIN_SRC evennia py rick = me.search("rick") ; rick.backstory("barbarian") #+END_SRC +* A Brave New World +Let’s sail to other islands a part of the way to expand the ingredients for potions as well as to create more “games”. +** The Boat +When the boat is docked, we should have a special /state/ to describe it: +#+BEGIN_SRC evennia + @teleport/quiet Lazy Dock + # + @desc/boat here = The dock you stand on juts into a bay of water the color of lavender flowers. A giant leaf softly bobs in the subtle surf next to the dock. Perhaps one could use this to sail across this sea? +#+END_SRC + +A boat on the sea is a separate room that coordinates four separate exits: + - dock to boat : =exit-dock-to-boat= + - boat to dock : =exit-boat-to-dock= + - boat to an island : =exit-boat-to-isle1= + - island to boat : =exit-isle1-to-boat= + +The aliases will make it easier to store and reference these exits. + +#+BEGIN_SRC evennia + @dig/teleport Leaf Boat;gr01 = leaf boat;boat;embark;exit-dock-to-boat,dock;land;disembark;exit-boat-to-dock +#+END_SRC + +General description: + +#+BEGIN_SRC evennia + @desc here = This leaf, large enough to accommodate a few people comfortably, seems to be a strange, but steady watercraft. +#+END_SRC + +Controlling the boat comes from a Script: + +#+BEGIN_SRC evennia + @script here = typeclasses.sailing.Boat + # + @set/script sailing/is_sailing = False + # + @set/script sailing/sailing_direction = "port" +#+END_SRC + +And store the exits on [[file:~/src/moss-n-puddles/typeclasses/sailing.py::class Boat(Script):][the script]]: + +#+BEGIN_SRC evennia + @set/script sailing/dock = $search(Lazy Dock) + # The Leaf Boat: + @set/script sailing/boat = $search(gr01) + # + @set/script sailing/dock_to_boat = $search(exit-dock-to-boat) + # + @set/script sailing/boat_to_dock = $search(exit-boat-to-dock) +#+END_SRC + +The boat has three /states/: + + - =docked= (at *Lazy Dock*) + - =sailing= (at sea) + - =ashore= (at some island below) + +#+BEGIN_SRC evennia + @desc/docked here = This leaf, large enough to accommodate a few people comfortably, seems to be a strange, but steady watercraft. While next to the dock, you can disembark, but feel this boat could set sail at any minute.|/|x[|WNote:|x Sailing soon. Waiting on other potential passengers]|n +#+END_SRC + +Toggle that state with: + +#+BEGIN_SRC evennia :tangle no + @roomstate docked +#+END_SRC + +And describe sailing on it.: + +#+BEGIN_SRC evennia + @desc/sailing here = This leaf, large enough to accommodate a few people comfortably, seems to be a strange, but steady watercraft. + + Only eddies from the subtle wake, intrude on the lavender sea's tranquility, as the giant leaf floats along an invisible current. The morning sun peaks above the colossal trees and the snow-capped mountains beyond.The afternoon sun peaks out briefly from misty clouds.The evening sun begins to set on a watery horizon.The moon peaks out from behind wispy clouds. +#+END_SRC + +And the description of the boat when ashore on an island: + +#+BEGIN_SRC evennia + @desc/ashore here = This leaf, large enough to accommodate a few people comfortably, seems to be a strange, but steady watercraft. Bobbing softly in the surf, the giant leaf bumps against the shore of the island, allowing you to disembark. + |x[|WNote:|x Waiting on other potential passengers]|n +#+END_SRC + +While on the boat, describe the dock: + +#+BEGIN_SRC evennia + @desc dock = A lazy dock with a comfortable-looking chair and a forest of colossal trees behind it on a hill. +#+END_SRC + +And describe disembarking to the Lazy Dock: + +#+BEGIN_SRC evennia + @set dock/traverse_msg = "You easily disembark from the giant leaf and step onto the dock..." +#+END_SRC + +Disembark to describe the exits to the boat: + +#+BEGIN_SRC evennia + @teleport/quiet Lazy Dock +#+END_SRC + +Describe the leaf boat (as an exit): + +#+BEGIN_SRC evennia + @desc boat = A giant leaf, tipped on all sides, gently floats on the tranquil sea, subtly bumping against the dock. Doesn't seem to have an oar, or even a rudder, but... it appears to be a strange, but steady watercraft if one were to gather a few friends to venture to the lands beyond... +#+END_SRC + +And describe embarking: + +#+BEGIN_SRC evennia + @set boat/traverse_msg = "You step into the bowed cavity of the leaf. Seems surprisingly steady...for a leaf." +#+END_SRC + +The /exit/ to and from the Dock to the *Leaf Boat* comes and goes. + +Send the “exit” to the leaf boat into the void to be picked up later: + +#+BEGIN_SRC evennia + @teleport/tonone boat +#+END_SRC + +Create a script that keeps the boat out at the island: + +#+BEGIN_SRC evennia + @script boat-reset:typeclasses.sailing.ResetBoat +#+END_SRC + +Let’s blow our horn and board the boat (we begin from the Grove of Matriarches): + +#+BEGIN_SRC tcl + send "south\n" + expectit "Lazy Dock" + + set timeout 240 + send "blow horn\n" + # expectit "You blow your horn" + expectit "The giant leaf slows as it arrives next to the dock." + + send "boat\n" + expectit "The giant leaf gently bobs in the surf of this island, allowing you to disembark." + #+END_SRC +** Throne Island +The boat should land on a distant island. + +We should come up with a *theme* for the entire island, from the “statue” to the puzzles and answers. + +#+BEGIN_SRC evennia + @dig/teleport Lonely Island;gr02:typeclasses.rooms_weather.TimeWeatherRoom +#+END_SRC + +And describe it: + +#+BEGIN_SRC evennia + @desc here = Vibrant green moss covers the island's gray rock. Wandering around the conifers you encounter a |Ystatue|n of an elegant woman seated on a large throne. + $state(boat, A large leaf bobs invitingly in the surf.) +#+END_SRC + +And tell the boat that this is the /default island/: + +#+BEGIN_SRC evennia + @set/script sailing/default_island = $search(Lonely Island) +#+END_SRC + +Now jump into the boat, + +#+BEGIN_SRC evennia + @open leaf boat;boat;embark;exit-isle1-to-boat,shore;disembark;exit-boat-to-isle1 = gr01 +#+END_SRC + +And describe the exit: + +#+BEGIN_SRC evennia + @desc boat = A giant leaf, tipped on all sides, gently bobs in the surf of this island. Doesn't seem to have an oar, or even a rudder, but... it appears to be a strange, but steady watercraft. +#+END_SRC + +And about getting on the boat: + +#+BEGIN_SRC evennia + @set boat/traverse_msg = "You step into the bowed cavity of the giant leaf." +#+END_SRC + +And store this exits on the script: + +#+BEGIN_SRC evennia + @set/script sailing/island1_to_boat = $search(exit-isle1-to-boat) + # + @set/script sailing/boat_to_island1 = $search(exit-boat-to-isle1) +#+END_SRC + +Now, let’s create the other exit: + +#+BEGIN_SRC evennia + @teleport gr01 +#+END_SRC + +And exiting the boat: + +#+BEGIN_SRC evennia + @set shore/traverse_msg = "You disembark from the giant leaf to step off into the surf and onto the shore..." +#+END_SRC + +Are they going to look before getting off? + +#+BEGIN_SRC evennia + @desc shore = You seem to have arrived at some island covered in large conifer trees. +#+END_SRC + +And tell the sailing script about this exit, so it can manipulate it: + +#+BEGIN_SRC evennia + @set/script sailing/boat_to_island1 = $search(exit-boat-to-isle1) +#+END_SRC + +And a bit of clean up to leave the boat at the island. + +#+BEGIN_SRC evennia + # This is global, really? + # @teleport/tonone dock + # py me.search('dock', location=here).location = None +#+END_SRC + +And the boat’s “room state”: +#+BEGIN_SRC evennia + @roomstate shore +#+END_SRC + +Let’s get off of the boat and enjoy the island… + +#+BEGIN_SRC tcl + send "disembark\n" + expectit "Lonely Island" + #+END_SRC +*** Moonberries +These berries should be created for making [[file:mud.org::*Trippy Potion][a Trippy Potion]]. + +#+BEGIN_SRC evennia + @teleport/quiet gr02 + # + @create/drop moonberries;moonberry;berry: typeclasses.consumables.Producer + # + @desc moonberries = Growing a slender vines that wrap around the trunks of the pine trees. Laden with small, blue berries, each reflecting a white cresent shape. + # + @set moonberries/make_name = "handful of moonberries" + # + @set moonberries/make_verb = "$conj(collect) a" + # + @set moonberries/make_class = "typeclasses.consumables.Edible" + # + @set moonberries/make_desc = "Blue berries with a white cresent shape." + # + @set moonberries/make_amount = 1 + # + @set moonberries/make_eat_msg = "Slightly bitter. Not very good." + # + @set moonberries/make_spell_msgs = "10 ;; $You() $conj(stare) off into space, lost in thought. ;; $You() $conj(study) $pron(your) hands, utterly captivated. ;; 5 ;; $You() $conj(awaken) from a daydream with a start." + # + # And we can't see them until we are an alchemist: + @lock moonberries = view:tag(alchemist) +#+END_SRC + +Let’s grab some berries for the road: + +#+BEGIN_SRC tcl + send "get moonberry\n" + expectit "You collect a handful of moonberries" + #+END_SRC +*** Seagrass + +Part of the [[Potions and their Ingredients][Alchemist Path]], we use /seagrass/ to create a [[file:mud.org::*Water Breathing][Water Breathing potion]]. + +We put this location hint in the Alchemy Tome: +#+begin_quote +This grass, often called seagrass since it vibrates as if laughing. The herb hunter canfind this in fields and meadows throughout the area. +#+end_quote + +And we create it: + +#+BEGIN_src evennia + @teleport/quiet gr02 + # + @create/drop patch of seagrass;seagrass;sea grass;grass: typeclasses.consumables.Producer + # + @desc seagrass = Patches of this vivid grass vibrates as if giggling. + # + @set seagrass/make_name = "bunch of seagrass" + # + @set seagrass/make_verb = "$conj(harvest) a" + # + @set seagrass/make_class = "typeclasses.consumables.Herb" + # + @set seagrass/make_desc = "This grass vibrates as if giggling." + # + @set seagrass/make_amount = 1 + # + # And we can't see them until we are an alchemist: + @lock seagrass = view:tag(alchemist) +#+END_SRC + +Until we are an alchemist, we shouldn't see the mushrooms... + +#+BEGIN_SRC tcl + dont_expect "You notice" "seagrass" +#+END_SRC + +And harvest it: + +#+BEGIN_SRC tcl + send "get seagrass\n" + expectit "You harvest a bunch of seagrass" + #+END_SRC +*** The Throne: First Puzzle +Details on the throne and the statues and maybe moss? What about sitting on the throne? + +#+BEGIN_SRC evennia + @teleport gr02 + # + @detail statue = A massive statue of an elegant woman atop a throne. A |Yshield|n rests against her knee as she hold an upright |Ytrident|n. In her other hand, she holds aloft an |Yorb|n. Eons of moss and mildew adds the appearance of tears streaming down her face. Only a raised eyebrow and subtle smirk hints at an earlier impression. At the base of statue is a |Yplaque|n. +#+END_SRC + +#+BEGIN_SRC evennia + @detail trident = Held loosely with one hand. Unclear if the sculptor intended for the middle tine to be missing, or if it broke centuries ago. +#+END_SRC + +#+BEGIN_SRC evennia + @detail orb;ball = The sphere resting on the statue's outstretched hand has an ornamental cross on top and the carved letters: |mR E G I N A|n +#+END_SRC + +The shield holds a poem: + +#+BEGIN_SRC evennia + @detail shield = An ornate shield carved with a poem: + + Upon the waves, as ship doeth glide, + Fearful whispers of the sea abide, + We cast our plea, with silver and song + To keep us safe as we sail along. + + She stirs the tides with playful ease, + Her whispers ride the ocean's breeze, + Her mischief wrapped in salty foam, + The sea, our mother, the Great Thalome. +#+END_SRC + +And the plaque gives the riddle. + +#+BEGIN_SRC evennia + @detail plaque = Glory to the seamother. All should |yspeak|n her |yname|n out loud. +#+END_SRC + +The plaque contains a /password/ to say aloud. We need another StoryCube to listen for the pass phrase: + +#+BEGIN_SRC evennia + @create/drop gr02ctl:typeclasses.puzzles.StoryCube + # + @desc gr02ctl = Opens the door when someone says Melora + # + @lock gr02ctl = view:false() + # + # Even if you can't see it, we don't want anyone taking it: + @lock gr02ctl = get:false() +#+END_SRC + +The poem in the shield has the /name, and the plague mentions that someone needs to say the name, which if said aloud, we hear: + +#+BEGIN_SRC evennia + @set gr02ctl/say = { r".*\bthalome.*": "gm Upon uttering that phrase, sparks of octarine magic pop the illusion, revealing an open archway at the base of the giant statue. ;; tag_all hidden_archway" } +#+END_SRC + +And we need to get rid of it when any one leaves: + +#+BEGIN_SRC evennia + @set gr02ctl/leave = "30 ;; @teleport/tonone arched opening" +#+END_SRC + +And we test it: + +#+BEGIN_SRC tcl + send "look statue\n" + expectit "A massive statue" + + send "look trident\n" + expectit "Held loosely with one hand" + + send "look ball\n" + expectit "sphere resting" + + send "look shield\n" + expectit "An ornate shield" + + send "look plaque\n" + expectit "Glory to the seamother" + + send "say The answer is Thalome, right?\n" + expectit "revealing an open archway" +#+END_SRC + +Which exit would need to be moved from the =None= space and a script to teleport it back after a minute. +*** Antechamber +From the magical archway, let’s create a room under the Throne: + +#+BEGIN_SRC evennia + @dig Antechamber;gr03:typeclasses.rooms_dark.DarkRoom = arched opening;opening;arch;archway +#+END_SRC + +#+BEGIN_SRC evennia + @desc arched opening = An arch, shaped as a cresent moon, rests on two ornate pillars to frame a short opening at the base of the statue. One pillar shows carved letters: |mF I C K L E|n and the other pillar shows: |mF A I T H|n. +#+END_SRC + +And the description of entering: + +#+BEGIN_SRC evennia + @set arched opening/traverse_msg = "You slightly stoop to enter into the darkness beyond the archway... As soon as you do, a large stone block slams down behind you, trapping you in the darkness." +#+END_SRC + +Let’s hide and lock this down: + +#+BEGIN_SRC evennia + @set arched opening/hidden_tag = "hidden_archway" + # + @lock arched opening = view:tag(hidden_archway) +#+END_SRC + +But we can enter: + +#+BEGIN_SRC tcl + send "look opening\n" + expectit "shaped as a cresent moon" + + send "arch\n" + expect { + "The room is completely dark" { + send "light torch\n" + expectit "The room is lit up" + + send "look\n" + expectit "Antechamber" + } + "Antechamber" { + send_user "We still have our torch lit from the last time." + } + timeout { + puts "ERROR: Expected response for 'get stick' not received." + send "quit\n" + exit 1 + } + } + + + +#+END_SRC +*** Puzzle Two: A Dark Place +Let’s make this a dark room where one has to have two feel around for a splinter to light, or bring a torch. + +#+BEGIN_SRC evennia + @create torch:typeclasses.lightables.LightSource +#+END_SRC + +Now, we, as a godlike avatar of Light, can go in: + +#+BEGIN_SRC evennia + @teleport gr03 + # + light torch + # + @desc here = A large room formed from intricately placed |Ystone blocks|n, tapered to form a |Ydome|n above you. In the center you see a large |Yobelisk|n with an empty |Ycavity|n halfway up. There seems to be no visible way to escape. +#+END_SRC + +And some details: + +#+BEGIN_SRC evennia + @detail cavity = While empty, this opening, about a foot or so deep, looks like it may have held something in the past. +#+END_SRC + +Don’t know if the blocks are interesting: + +#+BEGIN_SRC evennia + @detail stone blocks;blocks = While the stones are tightly placed, a curious blue fungus grows where moisture seeps between the seams. +#+END_SRC + +Dome? + +#+BEGIN_SRC evennia + @detail dome = Perhaps 30 feet high, but as shadows from the flame dance above you, you find it difficult to tell. +#+END_SRC + +Let’s look at all the fine details: + +#+BEGIN_SRC tcl + send "look cavity\n" + expectit "this opening" + + send "look blocks\n" + expectit "the stones are tightly placed" + + send "look dome\n" + expectit "Perhaps 30 feet high" +#+END_SRC +*** Puzzle Three: The Changing Obelisk +Each time this is “seen”, the response is different, so we use a [[file:~/src/moss-n-puddles/typeclasses/puzzles.py::class Changling(Object):][Changling]]: + +#+BEGIN_SRC evennia + @create/drop granite obelisk: typeclasses.puzzles.Changling +#+END_SRC + +And pin it down: + +#+BEGIN_SRC evennia + @lock obelisk = get:false() + # + @set obelisk/get_err_msg = "That is way too big to lift." +#+END_SRC + +The default description will be replaced: + +#+BEGIN_SRC evennia + @desc obelisk = A granite obelisk grazes the top of the dome. Each of its four sides show a different image. +#+END_SRC + +We build a /changling’s/ description from a =_prefix=, a random =descs=, and a =_postfix=: + +#+BEGIN_SRC evennia + @set obelisk/desc_prefix = "A << granite ^ large ^ stone >> obelisk grazes the top of the dome. The surface of the obelisk seem to waver, shift and writhe under your gaze." + # + @set obelisk/desc_postfix = " And << quickly ^ soon ^ swiftly >>, the << image ^ visage ^ vision ^ carving >> << is gone ^ fades ^ disappears ^ vanishes >>." +#+END_SRC + +And a list of differences that gives a hint to the password: + +#+BEGIN_SRC evennia + @set obelisk/descs = ( + "You can briefly make out the image of ocean waves.", + "For the briefest moment you make out an icy engravings of crystals.", + "You think you can see the outline of grass covered in dew drops.", + "The surface for a moment seems to portray clouds passing by.", + "Trees bordering a flowing river show up on the surface.", + ) +#+END_SRC + +If they say the /magic word/, they get the maguffin. + +#+BEGIN_SRC evennia + @set obelisk/say = { r".*\b[Ww]ater\b": "gm Upon uttering that phrase, sparks of octarine magic and mist appear on the opening on the obelisk. ;; scoring_all blue_medal ;; gm A blue medal materializes in the opening. You snatch it, claiming your prize. + ;; gift_all blue ;; gm You also notice a secret door! ;; tag_all hidden_antechamber_door" } +#+END_SRC + +And let’s test this out: +#+BEGIN_SRC tcl + send "look obelisk\n" + expectit "grazes the top of the dome" + + send "get obelisk\n" + expectit "That is way too big" + + send "say Is the magic word, Water?\n" + expectit "Upon uttering that phrase" + + # Make sure we got a blue medal ... Or whatever reward we should get + send "inv\n" + expectit "blue medal" + #+END_SRC +*** Puzzle Four: The Door Puzzle +Another puzzle, another room: + +#+BEGIN_SRC evennia + @dig Escape Hallway;gr04:typeclasses.rooms_dark.DarkRoom = secret door;door +#+END_SRC + +And we describe the secret door… + +#+BEGIN_SRC evennia + @desc secret door = A door you didn't notice before, looks like stone blocks. Beyond looks like another chamber. +#+END_SRC + +And the description of entering: + +#+BEGIN_SRC evennia + @set secret door/traverse_msg = "You slightly stoop to enter the dark chamber beyond..." +#+END_SRC + +Let’s hide and lock this down: + +#+BEGIN_SRC evennia + @set secret door/hidden_tag = "hidden_antechamber_door" + # + @lock secret door = view:tag(hidden_antechamber_door) +#+END_SRC + +Let’s go: + +#+BEGIN_SRC evennia + @teleport gr04 + # + @desc here = This stone hallway ends with an overly |Yornate door|n covered with letters in rows and columns forming a grid matrix. Placed above the door, a bronze |Yplaque|n, shows its age with a coat of patina. +#+END_SRC + +Let’s reward our players again: + +#+BEGIN_SRC evennia + @set here/arrive = "4 ;; gm ... You hear a distant dice roll ... ;; gmm {0} = With your excellent perception, you notice some gold coins hidden in the floor's dust. ;; gma {0} = $You() $conj(relocate) some gold coins on the floor to $pron(your) pouch. ;; coin 10 to {0}" +#+END_SRC + +We need another door in order to escape. + +#+BEGIN_SRC evennia + @detail plaque = Through the green patina, you can barely make out the text:|/ + A spoken word unseals me. + It starts with a T. + Halfway between twins. + The next character lies. +#+END_SRC + +The door leads back out. + +#+BEGIN_SRC evennia + @open ornate door;door = Lonely Island +#+END_SRC + +The dock is locked: + +#+BEGIN_SRC evennia + @lock ornate door = traverse:tag(open_ornate_door) +#+END_SRC + +#+BEGIN_SRC evennia + @set ornate door/err_traverse = "The door is locked." +#+END_SRC + +Look at the grid to find the two T’s: + +#+BEGIN_SRC evennia + @desc ornate door = The grid of letters look like:|/ + | Y | B | Q | X | D | Q | + | Y | A | K | D | X | B | + | D | E | L | G | W | X | + | T | S | - | A | X | V | + | L | J | H | E | P | V | + | F | U | I | D | I | P | + | H | X | R | G | R | X | + | K | S | M | U | T | N | + | W | X | M | W | Z | Z | +#+END_SRC + +We use a =StoryCube= to lock the door until the password is said: + +#+BEGIN_SRC evennia + @create/drop gr04ctl:typeclasses.puzzles.StoryCube + # + @desc gr04ctl = Opens the door when someone says Tidal Surge + # + @lock gr04ctl = view:false() + # + @lock gr04ctl = get:false() +#+END_SRC + +If they say, /Tidal Surge/, the *Locker* unlocks the door, and they can go through. + +#+BEGIN_SRC evennia + @set gr04ctl/say = {r"^tidal ?surge.*": "gm You hear an audible click from the ornate door! ;; tag_all open_ornate_door"} +#+END_SRC + +And the description of passing through: + +#+BEGIN_SRC evennia + @set ornate door/traverse_msg = "You open the door, and see that the door exits next to the statue..." +#+END_SRC + +Let’s end this back on the Dock: + +#+BEGIN_SRC emacs-lisp + teleport Lazy Dock +#+END_SRC + +But we’ll have the goblin test this out: + +#+BEGIN_SRC tcl + send "look door\n" + expectit "A door you didn't notice before" + + send "door\n" + expectit "Escape Hallway" + #+END_SRC +* Scoring +I would like a =score= command that gives them a tally based on the activities they have participated in. This will be a hashtable, stored as an attribute. Perhaps it increments a value? Should I simplify the number of items, and then list them all, so they have goals? + + - jump + - throw stick + - catch fish + - feed bhb + - get traveling horn + - make tea + - read a book + - eat candy + - get pipe + - get blue medal + - finish cocktail (all cocktails?) + - make potion (laughing) + + Should the score be something be shown when one issues a =look= at another character? ** Bugs +The =TICKER_HANDLER= is a /script/ but fully programmed and configured in the Python code. When I create a /weather room/ or a pet, the handler should be turned on and set to persist, sometimes this fails to get re-instantiated. + +The following code is idempotent and can be re-run /just to be sure/: + +#+NAME: ticker-handler-script +#+BEGIN_SRC python :tangle no + from evennia import TICKER_HANDLER + from evennia.utils.search import search_typeclass + + for pet in search_typeclass("typeclasses.pets.Pet", include_children=True): + TICKER_HANDLER.add(interval=160, callback=pet.update_state) + + for baker in search_typeclass("typeclasses.consumables.Trolley"): + TICKER_HANDLER.add(interval=86400, callback=baker.do_bake) + + for room in search_typeclass("typeclasses.rooms_weather.TimeWeatherRoom"): + TICKER_HANDLER.add(interval=300, callback=room.update_weather) +#+END_SRC + +And run it in an /interactive python/ sub-session: +#+BEGIN_SRC evennia :noweb yes + @py + <> + quit() +#+END_SRC + +Let’s take a look at all the tickers: + +#+BEGIN_SRC evennia + @py from evennia import TICKER_HANDLER; print(TICKER_HANDLER.all_display()) +#+END_SRC + +Which should show us all three pets (BHB, wee beastie and the fireplace) as well as the =do_bake= of the Kitchen’s cabinet and the Goblin’s tea party table and all the rooms with weather: + +#+BEGIN_SRC python :tangle no +[(cabinet, 'do_bake', None, 86400, '', True), (fish, 'do_speak', None, 3, '', True), (fireplace, 'update_state', None, 60, '', True), (big hairy beast, 'update_state', None, 60, '', True), (wee beastie, 'update_state', None, 60, '', True)] +#+END_SRC And now that we are done, say it: #+BEGIN_src evennia - @teleport/quiet mp05 + @teleport/quiet mp01 # say I have finished this, the first version, of my creation. #+END_SRC +** Janitor +The /janitor/ is a =Script= that moves every thing back to where they should be at the end of the day. + +#+BEGIN_SRC evennia + @script janitor:typeclasses.janitor.Janitor +#+END_SRC + + ** Finish Testing Can we quickly walk back through the world, gathering ingredients, and then going back into the Secret Room to make potions? @@ -7910,17 +8667,6 @@ Let’s try the next potion, the /Somnium Illusorium/: send "west\n" expectit "Grove" - send "south\n" - expectit "Lazy Dock" - - set timeout 240 - send "blow horn\n" - # expectit "You blow your horn" - expectit "The giant leaf slows as it arrives next to the dock." - - send "boat\n" - expectit "The giant leaf gently bobs in the surf of this island, allowing you to disembark." - send "disembark\n" expectit "Lonely Island" @@ -8150,24 +8896,6 @@ You sample from your teacup. > =throw book in fire= You drop the book, and it flaps its pages, and flies back to a section on the shelf. Gotta keep the room organized. -* Scoring -I would like a =score= command that gives them a tally based on the activities they have participated in. This will be a hashtable, stored as an attribute. Perhaps it increments a value? Should I simplify the number of items, and then list them all, so they have goals? - - - jump - - throw stick - - catch fish - - feed bhb - - get traveling horn - - make tea - - read a book - - eat candy - - get pipe - - get blue medal - - finish cocktail (all cocktails?) - - make potion (laughing) - - Should the score be something be shown when one issues a =look= at another character? - * Tutorial Bird If a person creates a character, instead of giving them a personal letter, let’s have a little bird land on their shoulder, and talk them through the game. I’m thinking a “state machine” triggered by actions that someone does. diff --git a/typeclasses/janitor.py b/typeclasses/janitor.py new file mode 100755 index 0000000..6d4c10b --- /dev/null +++ b/typeclasses/janitor.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +""" +Janitor + +Create a service that goes through the world at an interval +moving things that don't belong into a hamper. +""" + +from evennia.utils import search +from evennia.utils import logger + +from typeclasses.scripts import Script +from typeclasses.exits import Exit +from typeclasses.consumables import Producer + +ROOMS_TO_CLEAN = [ + "Grove of the Matriarchs", + "Boulder Top", + "Cozy House", + "Grotto", + "Frog Meadow", + "Lazy Dock", + "Lair", + "Mellow Marsh", + "Homey Hut", + "Wyldwood Bar", + "Cramped Kitchen", + "Secret Room", + "Bedroom", + "Prairie", + "Shore", + "Salty Shack", # mp16 + "Glittering Glade", # mp19 + "Dark Tunnel", # mp20 + "Workshop", # mp21 + "Damp Cave", + "Leaf Boat", + "Lonely Island", + "Antechamber", + "Escape Hallway", +] + +ROOM_EXCEPTIONS = { + "Grove of the Matriarchs": [ "stick" ], + "Cozy House": [ "crystal ball" ], + "Lazy Dock": [ "fishing pole" ], + "Homey Hut": [ "horn" ], + "Bedroom": [ "pair slippers" ], +} + +class Janitor(Script): + """ + Should this be an Object or inherit from Script? + """ + def at_script_creation(self): + self.key = "Janitor" + self.desc = "Move trash to a receptacle" + self.interval = 60 * 60 * 24 + self.start_delay = False + self.persistent = True + + def at_start(self, **kwargs): + self.at_repeat() + + def at_repeat(self, **kwargs): + for name in ROOMS_TO_CLEAN: + for room in search.objects(name): + self.clean_room(room) + + def clean_room(self, room): + """ + Sweep through the room's contents. + Anything that shouldn't be there is moved to 'mp00'. + + Exceptions include objects that are locked to the room, + _exits_ and _producers_ (because producers are not locked), + and actual exceptions in ROOM_EXCEPTIONS. + """ + exceptions = ROOM_EXCEPTIONS.get(room.key, []) + trash = [i for i in room.contents + if not i.is_typeclass(Exit) + and not i.is_typeclass(Producer) + and i.locks.get("get") != "get:false()" + and i.name not in exceptions ] + + for t in trash: + to_room = search.objects("mp00")[0] + for room,objs in ROOM_EXCEPTIONS.items(): + if t.key in objs: + to_room = search.objects(room)[0] + + # Quietly move it to where the object belongs: + logger.info(f"JANITOR: Move '{t.name}' to {to_room.name}") + t.location.msg_contents(f"A rat with beady eyes and a leather satchel appears, picks up the {t.name} and takes off with it.") + t.move_to(to_room, quiet=True) diff --git a/typeclasses/pets.py b/typeclasses/pets.py index e5e8dde..02d6a81 100755 --- a/typeclasses/pets.py +++ b/typeclasses/pets.py @@ -570,7 +570,12 @@ class WeeBeastie(Friendly, Familiar, Listener, AI): class BHB(Friendly, Listener, AI): + """ + The Big Hairy Beast is a special pet that has a circadian + rhythm, and goes to bed each night and wakes each morning. + """ def return_appearance(self, looker): + """The beast looks different when it is sleeping.""" if self.db.is_awake: return super().return_appearance(looker) else: diff --git a/typeclasses/things.py b/typeclasses/things.py index d8b513f..15a7a0e 100755 --- a/typeclasses/things.py +++ b/typeclasses/things.py @@ -353,7 +353,7 @@ class Wood(Litterable): ])) -class Stick(Consumable): +class Stick(Object): "An object to throw." def at_object_creation(self): self.cmdset.add_default(CmdSetStick) diff --git a/world/test-run.exp b/world/test-run.exp index f267f45..a238086 100755 --- a/world/test-run.exp +++ b/world/test-run.exp @@ -1204,11 +1204,95 @@ expectit "Frog Meadow" send "west\n" expectit "Grove of the Matriarchs" -send "west\n" -expectit "Grotto" +send "south\n" +expectit "Lazy Dock" + +set timeout 240 +send "blow horn\n" +# expectit "You blow your horn" +expectit "The giant leaf slows as it arrives next to the dock." + +send "boat\n" +expectit "The giant leaf gently bobs in the surf of this island, allowing you to disembark." + +send "disembark\n" +expectit "Lonely Island" + +send "get moonberry\n" +expectit "You collect a handful of moonberries" + +dont_expect "You notice" "seagrass" + +send "get seagrass\n" +expectit "You harvest a bunch of seagrass" + +send "look statue\n" +expectit "A massive statue" + +send "look trident\n" +expectit "Held loosely with one hand" + +send "look ball\n" +expectit "sphere resting" + +send "look shield\n" +expectit "An ornate shield" + +send "look plaque\n" +expectit "Glory to the seamother" + +send "say The answer is Thalome, right?\n" +expectit "revealing an open archway" + +send "look opening\n" +expectit "shaped as a cresent moon" + +send "arch\n" +expect { + "The room is completely dark" { + send "light torch\n" + expectit "The room is lit up" + + send "look\n" + expectit "Antechamber" + } + "Antechamber" { + send_user "We still have our torch lit from the last time." + } + timeout { + puts "ERROR: Expected response for 'get stick' not received." + send "quit\n" + exit 1 + } +} + +send "look cavity\n" +expectit "this opening" + +send "look blocks\n" +expectit "the stones are tightly placed" + +send "look dome\n" +expectit "Perhaps 30 feet high" + +send "look obelisk\n" +expectit "grazes the top of the dome" + +send "get obelisk\n" +expectit "That is way too big" + +send "say Is the magic word, Water?\n" +expectit "Upon uttering that phrase" + +# Make sure we got a blue medal ... Or whatever reward we should get +send "inv\n" +expectit "blue medal" + +send "look door\n" +expectit "A door you didn't notice before" send "door\n" -expectit "Cozy House" +expectit "Escape Hallway" send "leave\n" expectit "Grotto" @@ -1346,17 +1430,6 @@ expectit "Frog Meadow" send "west\n" expectit "Grove" -send "south\n" -expectit "Lazy Dock" - -set timeout 240 -send "blow horn\n" -# expectit "You blow your horn" -expectit "The giant leaf slows as it arrives next to the dock." - -send "boat\n" -expectit "The giant leaf gently bobs in the surf of this island, allowing you to disembark." - send "disembark\n" expectit "Lonely Island" diff --git a/world/version1.ev b/world/version1.ev index 6dec256..7d63493 100644 --- a/world/version1.ev +++ b/world/version1.ev @@ -86,7 +86,7 @@ pose looking awesome # [[file:../moss-n-puddles.org::*Barkbinder the Tree][Barkbinder the Tree:2]] -py tree = me.search("tree") ; tree.sdesc.add("especially large tree") ; tree.backstory("tree") +py tree = me.search("tree") ; tree.home=here; tree.sdesc.add("especially large tree") ; tree.backstory("tree") # Barkbinder the Tree:2 ends here @@ -963,81 +963,81 @@ py s = me.search("squirrel") ; s.db._sdesc="orange-robed squirrel" ; s.sdesc.add # Let’s set some behavior levels. For instance, the beast is sad when he doesn’t see its friends: -# [[file:../moss-n-puddles.org::*Beast][Beast:6]] +# [[file:../moss-n-puddles.org::*Beast][Beast:7]] @set beast/loneliness_amount = -2 -# Beast:6 ends here +# Beast:7 ends here # It seem to warm up the to new characters hanging around the area, but not as much as those that would interact with it: -# [[file:../moss-n-puddles.org::*Beast][Beast:7]] +# [[file:../moss-n-puddles.org::*Beast][Beast:8]] @set beast/shyness_amount = 3 -# Beast:7 ends here +# Beast:8 ends here # How active should this pet be? Seems like at the moment, it shouldn’t be too obnoxious. This setting is a percentage, so 12 is /12%/, which returns a message only 12% of the /ticks/ (where a tick is about a minute). -# [[file:../moss-n-puddles.org::*Beast][Beast:8]] +# [[file:../moss-n-puddles.org::*Beast][Beast:9]] @set beast/active_amount = 10 -# Beast:8 ends here +# Beast:9 ends here # It isn’t that scared of new people, as it will ignore them when someone it knows is around. -# [[file:../moss-n-puddles.org::*Beast][Beast:9]] +# [[file:../moss-n-puddles.org::*Beast][Beast:10]] @set beast/new_character_reaction = 'ignores' -# Beast:9 ends here +# Beast:10 ends here # Seems we should make descriptions for all the states that happen when you look at them. These are appended to the standard description. -# [[file:../moss-n-puddles.org::*Beast][Beast:10]] +# [[file:../moss-n-puddles.org::*Beast][Beast:11]] @set beast/scared_msg = "It seems <> as it tries to hide behind a tall clump of grass. Yeah, it doesn't do a good job of hiding." -# Beast:10 ends here +# Beast:11 ends here # Concerned level: -# [[file:../moss-n-puddles.org::*Beast][Beast:11]] +# [[file:../moss-n-puddles.org::*Beast][Beast:12]] @set beast/concerned_msg = "Its large, yellow eyes stare at you from a safe distance." -# Beast:11 ends here +# Beast:12 ends here # Interested level: -# [[file:../moss-n-puddles.org::*Beast][Beast:12]] +# [[file:../moss-n-puddles.org::*Beast][Beast:13]] @set beast/interested_msg = "It seems <> in what you are doing <>. ;; Its << ^ large, ^ big,>> yellow eyes watch your every move." -# Beast:12 ends here +# Beast:13 ends here # Friendly level: -# [[file:../moss-n-puddles.org::*Beast][Beast:13]] +# [[file:../moss-n-puddles.org::*Beast][Beast:14]] @set beast/friendly_msg = "It sits next to you, as its big, friendly eyes gaze as you. ;; It <> to you, wagging its tail-less behind. ;; It lays down next to you." -# Beast:13 ends here +# Beast:14 ends here # When the beast is sleeping, we can some times spam the room with the snores: -# [[file:../moss-n-puddles.org::*Beast][Beast:14]] +# [[file:../moss-n-puddles.org::*Beast][Beast:15]] @set beast/sleeping_actions = "The <> <> <> lets loose a <> snore. ;; The <> <> <> growls in its sleep. ;; The <> <> <> twitches its <>. ;; The <> <> <> <> on its <> mattress." -# Beast:14 ends here +# Beast:15 ends here @@ -1046,9 +1046,9 @@ py s = me.search("squirrel") ; s.db._sdesc="orange-robed squirrel" ; s.sdesc.add # The scared level doesn’t last long, so let’s just leave one message: -# [[file:../moss-n-puddles.org::*Beast][Beast:15]] +# [[file:../moss-n-puddles.org::*Beast][Beast:16]] @set beast/scared_actions = "A tremendously large and hairy beast attempts to nervously (and almost comically) hide" -# Beast:15 ends here +# Beast:16 ends here @@ -1056,43 +1056,43 @@ py s = me.search("squirrel") ; s.db._sdesc="orange-robed squirrel" ; s.sdesc.add # Concerned actions: -# [[file:../moss-n-puddles.org::*Beast][Beast:16]] +# [[file:../moss-n-puddles.org::*Beast][Beast:17]] @set beast/concerned_actions = "The <> <> <> <> concerned by your presence in the <>. ;; The <> <> <> seems concerned. Maybe it's hungry. ;; The <> <> <> seems concerned and keeps its distance." -# Beast:16 ends here +# Beast:17 ends here # Interested actions: -# [[file:../moss-n-puddles.org::*Beast][Beast:17]] +# [[file:../moss-n-puddles.org::*Beast][Beast:18]] @set beast/interested_actions = "The <> <> <> seems <> in $you(). ;; The <> <> <> seems curious about $you(). ;; The <> <> <> stands on its hind legs. ;; The <> <> <> <> $you() with its <> yellow eyes." -# Beast:17 ends here +# Beast:18 ends here # Friendly actions: -# [[file:../moss-n-puddles.org::*Beast][Beast:18]] +# [[file:../moss-n-puddles.org::*Beast][Beast:19]] @set beast/friendly_actions = "The <> <> <> <> <> wagging its backend<<, ^ as it seems>> happy to see $you(). ;; The <> <> <> <> <> hoping to play with $you(). ;; The <> <> <> flops over in front of $you() wriggling <> on the ground. ;; The <> <> <> <> <> next to $you(). ;; The <> <> <> chases butterflies around the <>." -# Beast:18 ends here +# Beast:19 ends here # The ecstatic states are just a bit more than friendly. -# [[file:../moss-n-puddles.org::*Beast][Beast:19]] +# [[file:../moss-n-puddles.org::*Beast][Beast:20]] @set beast/ecstatic_actions = "The <> <> <> <> <> to give $you() a sloppy <>. ;; The <> <> <> <> <> wagging its backend as it seems <> excited to see $you(). ;; The <> <> <> <> <> hoping to play with $you(). ;; The <> <> <> flops over in front of $you() happily wriggling on the ground. ;; The <> <> <> excitedly <> <> next to you. ;; The <> <> <> <> leaps into air. ;; The <> <> <> chases butterflies around the <>." -# Beast:19 ends here +# Beast:20 ends here # And the responses to being /pet/: -# [[file:../moss-n-puddles.org::*Beast][Beast:20]] +# [[file:../moss-n-puddles.org::*Beast][Beast:21]] @set beast/pet_sleeping_response = "Petting a sleeping beast of that size isn't your best idea." # @set beast/pet_scared_response = "$You() can't get near the wild beast to pet it. It seems scared." @@ -1104,7 +1104,7 @@ py s = me.search("squirrel") ; s.db._sdesc="orange-robed squirrel" ; s.sdesc.add @set beast/pet_friendly_response = "The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> << flops ^ rolls >> over << in the grass ^>> as $you() $conj(give) it belly rubs. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> << flops ^ rolls >> over << in the grass ^>> as $you() $conj(rub) its belly. ;; $You() $conj(pet) the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> . ;; $You() $conj(scratch) the << nose ^ ears >> of the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>>. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> leans forward as $you() $conj(scratch) its nose." # @set beast/pet_ecstatic_response = "While << excited ^ ecstatic ^ squirmy >>, the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> << lays ^ gets >> down so $you() can << pet ^ scratch >> << the top of its head ^ the back of its neck ^ its nose ^ the sides of its face >>. It closes its eyes and purrs. ;; << The squirmy little devil. ^ >> $conj(You) << can ^ >> << barely ^ hardly >> scratch the << nose ^ ears ^ neck ^ top of the head >> of the << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> as it << squirms around ^ wriggles it backend >>. It << can hardly ^ can't >> contain its excitement. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> wriggles around before << flopping ^ rolling >> over << in the grass ^>> as $you() $conj(give) it belly rubs. ;; The << big, ^ huge, ^ large, ^ tremendous, ^ >> << hairy ^ slobbery ^ horned ^ clawed ^ >> << brute ^ beast ^ monster>> wriggles and squirms excitedly before it << flops ^ rolls >> over << in the grass ^>> as $you() $conj(rub) its belly." -# Beast:20 ends here +# Beast:21 ends here # To the east of the meadow, let’s make a glade back inside the Forest: @@ -3038,6 +3038,26 @@ Someone has set a nice |Ychair|n for viewing. # Sign:4 ends here +# Part of the [[Potions and their Ingredients][Alchemist Path]], we use /pine flowers/ to create a potion TBD, and feed the stoat in Dabbler’s House. + + +# [[file:../moss-n-puddles.org::*Pine Tree][Pine Tree:1]] +@create/drop pine tree;pine;tree;flowers;flower : typeclasses.consumables.Producer +# +@desc pine = Windswept pine leans to shade the dock, protecting it somewhat from the regular occuring rain. Interestingly, the tree has beautiful, yellow |Yflowers|n. +# +@set pine/make_class = "typeclasses.consumables.Herb" +# +@set pine/make_name = "yellow flower" +# +@set pine/make_verb = "$conj(pick) a small" +# +@set pine/make_desc = "Briny smelling flower with purple spots." +# +@lock pine = view:tag(alchemist) # We want the user to be able to "look pine" as a detail? +# Pine Tree:1 ends here + + # Here for hints … and a bit of a distraction. @@ -3170,7 +3190,7 @@ py me.search("raven").backstory("raven") # [[file:../moss-n-puddles.org::*Pine Flowers][Pine Flowers:1]] -@create/drop pine tree;pine;tree;flowers;flower = typeclasses.consumables.Producer +@create/drop pine tree;pine;tree;flowers;flower : typeclasses.consumables.Producer # @desc pine = Windswept pine leans to shade the shack, protecting it somewhat from the regular occuring rain. Interesting, that the pine has beautiful, yellow |Yflowers|n. # @@ -3993,6 +4013,8 @@ drop ball # [[file:../moss-n-puddles.org::*Dabbler’s Butterfly][Dabbler’s Butterfly:4]] +@lock butterfly = get:false() +# @set butterfly/get_err_msg = "It quickly flutters away, only to land a few feet away." # Dabbler’s Butterfly:4 ends here @@ -4045,7 +4067,7 @@ py bt = self.search('gnome'); bt.sdesc.add('old gnome'); bt.db.pose = 'smiling a # [[file:../moss-n-puddles.org::*Character: Dabbler][Character: Dabbler:6]] @set gnome/pose_sleep = "sleeping soundly in a large, overstuffed chair" # -pose gnome/default = smoking his pipe +@set gnome/pose_default = "smoking his pipe" # Character: Dabbler:6 ends here @@ -4054,7 +4076,7 @@ pose gnome/default = smoking his pipe # [[file:../moss-n-puddles.org::*Character: Dabbler][Character: Dabbler:7]] -@desc gnome = A small, hunched old man with messy blue hair, a gray vandyke and an eye twinkle.|/|/Spectacles perched precariously on the end of his hooked nose, wobble with his head. His bright crimson jacket contrasts with his dark brown cloak. +@desc gnome = A small, hunched old man with messy white hair, a gray vandyke and an eye twinkle.|/|/Spectacles perched precariously on the end of his hooked nose, wobble with his head. His bright crimson jacket contrasts with his dark brown cloak. # Character: Dabbler:7 ends here @@ -4063,7 +4085,7 @@ pose gnome/default = smoking his pipe # [[file:../moss-n-puddles.org::*Character: Dabbler][Character: Dabbler:8]] -@set gnome/desc_unpuppeted = "A small, hunched old man with messy blue hair and a gray vandyke snoring soundly in one of the overstuffed chairs.|/|/Spectacles perched precariously on the end of his hooked nose, wobble with each breath. His bright crimson jacket contrasts with the dark brown blanket covering his legs." +@set gnome/desc_unpuppeted = "A small, hunched old man with messy white hair and a gray vandyke snoring soundly in one of the overstuffed chairs.|/|/Spectacles perched precariously on the end of his hooked nose, wobble with each breath. His bright crimson jacket contrasts with the dark brown blanket covering his legs." # Character: Dabbler:8 ends here @@ -4155,7 +4177,7 @@ pose gnome/default = smoking his pipe # [[file:../moss-n-puddles.org::*Pipe][Pipe:1]] -@create pipe: typeclasses.things.Pipe +@create carved pipe: typeclasses.things.Pipe # Pipe:1 ends here @@ -5475,25 +5497,36 @@ py bt = self.search('head'); bt.sdesc.add('curious figure'); bt.db.pose = 'sitti -# Initial default state is unfinished: +# The project shouldn’t be stolen … # [[file:../moss-n-puddles.org::*The Project][The Project:2]] +@lock project = get:false() +# +@set project/get_err_msg = "You shouldn't steal George's project. Perhaps you can help him with it." +# The Project:2 ends here + + + +# Initial default state is unfinished: + + +# [[file:../moss-n-puddles.org::*The Project][The Project:3]] @set project/name_default = "unfinished project" # @set project/desc_default = "On the workbench lies a tangle of brass plates, tubes and mechanical gears, shaped like a bird. Unassembled, it appears to be missing parts that might help it fly." -# The Project:2 ends here +# The Project:3 ends here # And this is the name and description when the project is finished: -# [[file:../moss-n-puddles.org::*The Project][The Project:4]] +# [[file:../moss-n-puddles.org::*The Project][The Project:5]] @set project/name_finished = "mechanical bird" # @set project/desc_finished = "This contraption made of brass plates and tubing sports an array of beautiful feathers, as it flies about." -# The Project:4 ends here +# The Project:5 ends here # :PROPERTIES: @@ -6157,12 +6190,761 @@ py rick = me.search("rick") ; rick.backstory("barbarian") # Rick the Barbarian:9 ends here +# When the boat is docked, we should have a special /state/ to describe it: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:1]] +@teleport/quiet Lazy Dock +# +@desc/boat here = The dock you stand on juts into a bay of water the color of lavender flowers. A giant leaf softly bobs in the subtle surf next to the dock. Perhaps one could use this to sail across this sea? +# The Boat:1 ends here + + + +# A boat on the sea is a separate room that coordinates four separate exits: +# - dock to boat : =exit-dock-to-boat= +# - boat to dock : =exit-boat-to-dock= +# - boat to an island : =exit-boat-to-isle1= +# - island to boat : =exit-isle1-to-boat= + +# The aliases will make it easier to store and reference these exits. + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:2]] +@dig/teleport Leaf Boat;gr01 = leaf boat;boat;embark;exit-dock-to-boat,dock;land;disembark;exit-boat-to-dock +# The Boat:2 ends here + + + +# General description: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:3]] +@desc here = This leaf, large enough to accommodate a few people comfortably, seems to be a strange, but steady watercraft. +# The Boat:3 ends here + + + +# Controlling the boat comes from a Script: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:4]] +@script here = typeclasses.sailing.Boat +# +@set/script sailing/is_sailing = False +# +@set/script sailing/sailing_direction = "port" +# The Boat:4 ends here + + + +# And store the exits on [[file:~/src/moss-n-puddles/typeclasses/sailing.py::class Boat(Script):][the script]]: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:5]] +@set/script sailing/dock = $search(Lazy Dock) +# The Leaf Boat: +@set/script sailing/boat = $search(gr01) +# +@set/script sailing/dock_to_boat = $search(exit-dock-to-boat) +# +@set/script sailing/boat_to_dock = $search(exit-boat-to-dock) +# The Boat:5 ends here + + + +# The boat has three /states/: + +# - =docked= (at *Lazy Dock*) +# - =sailing= (at sea) +# - =ashore= (at some island below) + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:6]] +@desc/docked here = This leaf, large enough to accommodate a few people comfortably, seems to be a strange, but steady watercraft. While next to the dock, you can disembark, but feel this boat could set sail at any minute.|/|x[|WNote:|x Sailing soon. Waiting on other potential passengers]|n +# The Boat:6 ends here + + + +# And describe sailing on it.: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:8]] +@desc/sailing here = This leaf, large enough to accommodate a few people comfortably, seems to be a strange, but steady watercraft. + +Only eddies from the subtle wake, intrude on the lavender sea's tranquility, as the giant leaf floats along an invisible current. The morning sun peaks above the colossal trees and the snow-capped mountains beyond.The afternoon sun peaks out briefly from misty clouds.The evening sun begins to set on a watery horizon.The moon peaks out from behind wispy clouds. +# The Boat:8 ends here + + + +# And the description of the boat when ashore on an island: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:9]] +@desc/ashore here = This leaf, large enough to accommodate a few people comfortably, seems to be a strange, but steady watercraft. Bobbing softly in the surf, the giant leaf bumps against the shore of the island, allowing you to disembark. +|x[|WNote:|x Waiting on other potential passengers]|n +# The Boat:9 ends here + + + +# While on the boat, describe the dock: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:10]] +@desc dock = A lazy dock with a comfortable-looking chair and a forest of colossal trees behind it on a hill. +# The Boat:10 ends here + + + +# And describe disembarking to the Lazy Dock: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:11]] +@set dock/traverse_msg = "You easily disembark from the giant leaf and step onto the dock..." +# The Boat:11 ends here + + + +# Disembark to describe the exits to the boat: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:12]] +@teleport/quiet Lazy Dock +# The Boat:12 ends here + + + +# Describe the leaf boat (as an exit): + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:13]] +@desc boat = A giant leaf, tipped on all sides, gently floats on the tranquil sea, subtly bumping against the dock. Doesn't seem to have an oar, or even a rudder, but... it appears to be a strange, but steady watercraft if one were to gather a few friends to venture to the lands beyond... +# The Boat:13 ends here + + + +# And describe embarking: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:14]] +@set boat/traverse_msg = "You step into the bowed cavity of the leaf. Seems surprisingly steady...for a leaf." +# The Boat:14 ends here + + + +# The /exit/ to and from the Dock to the *Leaf Boat* comes and goes. + +# Send the “exit” to the leaf boat into the void to be picked up later: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:15]] +@teleport/tonone boat +# The Boat:15 ends here + + + +# Create a script that keeps the boat out at the island: + + +# [[file:../moss-n-puddles.org::*The Boat][The Boat:16]] +@script boat-reset:typeclasses.sailing.ResetBoat +# The Boat:16 ends here + + +# The boat should land on a distant island. + +# We should come up with a *theme* for the entire island, from the “statue” to the puzzles and answers. + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:1]] +@dig/teleport Lonely Island;gr02:typeclasses.rooms_weather.TimeWeatherRoom +# Throne Island:1 ends here + + + +# And describe it: + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:2]] +@desc here = Vibrant green moss covers the island's gray rock. Wandering around the conifers you encounter a |Ystatue|n of an elegant woman seated on a large throne. +$state(boat, A large leaf bobs invitingly in the surf.) +# Throne Island:2 ends here + + + +# And tell the boat that this is the /default island/: + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:3]] +@set/script sailing/default_island = $search(Lonely Island) +# Throne Island:3 ends here + + + +# Now jump into the boat, + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:4]] +@open leaf boat;boat;embark;exit-isle1-to-boat,shore;disembark;exit-boat-to-isle1 = gr01 +# Throne Island:4 ends here + + + +# And describe the exit: + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:5]] +@desc boat = A giant leaf, tipped on all sides, gently bobs in the surf of this island. Doesn't seem to have an oar, or even a rudder, but... it appears to be a strange, but steady watercraft. +# Throne Island:5 ends here + + + +# And about getting on the boat: + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:6]] +@set boat/traverse_msg = "You step into the bowed cavity of the giant leaf." +# Throne Island:6 ends here + + + +# And store this exits on the script: + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:7]] +@set/script sailing/island1_to_boat = $search(exit-isle1-to-boat) +# +@set/script sailing/boat_to_island1 = $search(exit-boat-to-isle1) +# Throne Island:7 ends here + + + +# Now, let’s create the other exit: + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:8]] +@teleport gr01 +# Throne Island:8 ends here + + + +# And exiting the boat: + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:9]] +@set shore/traverse_msg = "You disembark from the giant leaf to step off into the surf and onto the shore..." +# Throne Island:9 ends here + + + +# Are they going to look before getting off? + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:10]] +@desc shore = You seem to have arrived at some island covered in large conifer trees. +# Throne Island:10 ends here + + + +# And tell the sailing script about this exit, so it can manipulate it: + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:11]] +@set/script sailing/boat_to_island1 = $search(exit-boat-to-isle1) +# Throne Island:11 ends here + + + +# And a bit of clean up to leave the boat at the island. + + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:12]] +# This is global, really? +# @teleport/tonone dock +# py me.search('dock', location=here).location = None +# Throne Island:12 ends here + + + +# And the boat’s “room state”: + +# [[file:../moss-n-puddles.org::*Throne Island][Throne Island:13]] +@roomstate shore +# Throne Island:13 ends here + + +# These berries should be created for making [[file:mud.org::*Trippy Potion][a Trippy Potion]]. + + +# [[file:../moss-n-puddles.org::*Moonberries][Moonberries:1]] +@teleport/quiet gr02 +# +@create/drop moonberries;moonberry;berry: typeclasses.consumables.Producer +# +@desc moonberries = Growing a slender vines that wrap around the trunks of the pine trees. Laden with small, blue berries, each reflecting a white cresent shape. +# +@set moonberries/make_name = "handful of moonberries" +# +@set moonberries/make_verb = "$conj(collect) a" +# +@set moonberries/make_class = "typeclasses.consumables.Edible" +# +@set moonberries/make_desc = "Blue berries with a white cresent shape." +# +@set moonberries/make_amount = 1 +# +@set moonberries/make_eat_msg = "Slightly bitter. Not very good." +# +@set moonberries/make_spell_msgs = "10 ;; $You() $conj(stare) off into space, lost in thought. ;; $You() $conj(study) $pron(your) hands, utterly captivated. ;; 5 ;; $You() $conj(awaken) from a daydream with a start." +# +# And we can't see them until we are an alchemist: +@lock moonberries = view:tag(alchemist) +# Moonberries:1 ends here + + + +# Part of the [[Potions and their Ingredients][Alchemist Path]], we use /seagrass/ to create a [[file:mud.org::*Water Breathing][Water Breathing potion]]. + +# We put this location hint in the Alchemy Tome: +# #+begin_quote +# This grass, often called seagrass since it vibrates as if laughing. The herb hunter canfind this in fields and meadows throughout the area. +# #+end_quote + +# And we create it: + + +# [[file:../moss-n-puddles.org::*Seagrass][Seagrass:1]] +@teleport/quiet gr02 +# +@create/drop patch of seagrass;seagrass;sea grass;grass: typeclasses.consumables.Producer +# +@desc seagrass = Patches of this vivid grass vibrates as if giggling. +# +@set seagrass/make_name = "bunch of seagrass" +# +@set seagrass/make_verb = "$conj(harvest) a" +# +@set seagrass/make_class = "typeclasses.consumables.Herb" +# +@set seagrass/make_desc = "This grass vibrates as if giggling." +# +@set seagrass/make_amount = 1 +# +# And we can't see them until we are an alchemist: +@lock seagrass = view:tag(alchemist) +# Seagrass:1 ends here + + +# Details on the throne and the statues and maybe moss? What about sitting on the throne? + + +# [[file:../moss-n-puddles.org::*The Throne: First Puzzle][The Throne: First Puzzle:1]] +@teleport gr02 +# +@detail statue = A massive statue of an elegant woman atop a throne. A |Yshield|n rests against her knee as she hold an upright |Ytrident|n. In her other hand, she holds aloft an |Yorb|n. Eons of moss and mildew adds the appearance of tears streaming down her face. Only a raised eyebrow and subtle smirk hints at an earlier impression. At the base of statue is a |Yplaque|n. +# The Throne: First Puzzle:1 ends here + +# [[file:../moss-n-puddles.org::*The Throne: First Puzzle][The Throne: First Puzzle:2]] +@detail trident = Held loosely with one hand. Unclear if the sculptor intended for the middle tine to be missing, or if it broke centuries ago. +# The Throne: First Puzzle:2 ends here + +# [[file:../moss-n-puddles.org::*The Throne: First Puzzle][The Throne: First Puzzle:3]] +@detail orb;ball = The sphere resting on the statue's outstretched hand has an ornamental cross on top and the carved letters: |mR E G I N A|n +# The Throne: First Puzzle:3 ends here + + + +# The shield holds a poem: + + +# [[file:../moss-n-puddles.org::*The Throne: First Puzzle][The Throne: First Puzzle:4]] +@detail shield = An ornate shield carved with a poem: + + Upon the waves, as ship doeth glide, + Fearful whispers of the sea abide, + We cast our plea, with silver and song + To keep us safe as we sail along. + + She stirs the tides with playful ease, + Her whispers ride the ocean's breeze, + Her mischief wrapped in salty foam, + The sea, our mother, the Great Thalome. +# The Throne: First Puzzle:4 ends here + + + +# And the plaque gives the riddle. + + +# [[file:../moss-n-puddles.org::*The Throne: First Puzzle][The Throne: First Puzzle:5]] +@detail plaque = Glory to the seamother. All should |yspeak|n her |yname|n out loud. +# The Throne: First Puzzle:5 ends here + + + +# The plaque contains a /password/ to say aloud. We need another StoryCube to listen for the pass phrase: + + +# [[file:../moss-n-puddles.org::*The Throne: First Puzzle][The Throne: First Puzzle:6]] +@create/drop gr02ctl:typeclasses.puzzles.StoryCube +# +@desc gr02ctl = Opens the door when someone says Melora +# +@lock gr02ctl = view:false() +# +# Even if you can't see it, we don't want anyone taking it: +@lock gr02ctl = get:false() +# The Throne: First Puzzle:6 ends here + + + +# The poem in the shield has the /name, and the plague mentions that someone needs to say the name, which if said aloud, we hear: + + +# [[file:../moss-n-puddles.org::*The Throne: First Puzzle][The Throne: First Puzzle:7]] +@set gr02ctl/say = { r".*\bthalome.*": "gm Upon uttering that phrase, sparks of octarine magic pop the illusion, revealing an open archway at the base of the giant statue. ;; tag_all hidden_archway" } +# The Throne: First Puzzle:7 ends here + + + +# And we need to get rid of it when any one leaves: + + +# [[file:../moss-n-puddles.org::*The Throne: First Puzzle][The Throne: First Puzzle:8]] +@set gr02ctl/leave = "30 ;; @teleport/tonone arched opening" +# The Throne: First Puzzle:8 ends here + + +# From the magical archway, let’s create a room under the Throne: + + +# [[file:../moss-n-puddles.org::*Antechamber][Antechamber:1]] +@dig Antechamber;gr03:typeclasses.rooms_dark.DarkRoom = arched opening;opening;arch;archway +# Antechamber:1 ends here + +# [[file:../moss-n-puddles.org::*Antechamber][Antechamber:2]] +@desc arched opening = An arch, shaped as a cresent moon, rests on two ornate pillars to frame a short opening at the base of the statue. One pillar shows carved letters: |mF I C K L E|n and the other pillar shows: |mF A I T H|n. +# Antechamber:2 ends here + + + +# And the description of entering: + + +# [[file:../moss-n-puddles.org::*Antechamber][Antechamber:3]] +@set arched opening/traverse_msg = "You slightly stoop to enter into the darkness beyond the archway... As soon as you do, a large stone block slams down behind you, trapping you in the darkness." +# Antechamber:3 ends here + + + +# Let’s hide and lock this down: + + +# [[file:../moss-n-puddles.org::*Antechamber][Antechamber:4]] +@set arched opening/hidden_tag = "hidden_archway" +# +@lock arched opening = view:tag(hidden_archway) +# Antechamber:4 ends here + + +# Let’s make this a dark room where one has to have two feel around for a splinter to light, or bring a torch. + + +# [[file:../moss-n-puddles.org::*Puzzle Two: A Dark Place][Puzzle Two: A Dark Place:1]] +@create torch:typeclasses.lightables.LightSource +# Puzzle Two: A Dark Place:1 ends here + + + +# Now, we, as a godlike avatar of Light, can go in: + + +# [[file:../moss-n-puddles.org::*Puzzle Two: A Dark Place][Puzzle Two: A Dark Place:2]] +@teleport gr03 +# +light torch +# +@desc here = A large room formed from intricately placed |Ystone blocks|n, tapered to form a |Ydome|n above you. In the center you see a large |Yobelisk|n with an empty |Ycavity|n halfway up. There seems to be no visible way to escape. +# Puzzle Two: A Dark Place:2 ends here + + + +# And some details: + + +# [[file:../moss-n-puddles.org::*Puzzle Two: A Dark Place][Puzzle Two: A Dark Place:3]] +@detail cavity = While empty, this opening, about a foot or so deep, looks like it may have held something in the past. +# Puzzle Two: A Dark Place:3 ends here + + + +# Don’t know if the blocks are interesting: + + +# [[file:../moss-n-puddles.org::*Puzzle Two: A Dark Place][Puzzle Two: A Dark Place:4]] +@detail stone blocks;blocks = While the stones are tightly placed, a curious blue fungus grows where moisture seeps between the seams. +# Puzzle Two: A Dark Place:4 ends here + + + +# Dome? + + +# [[file:../moss-n-puddles.org::*Puzzle Two: A Dark Place][Puzzle Two: A Dark Place:5]] +@detail dome = Perhaps 30 feet high, but as shadows from the flame dance above you, you find it difficult to tell. +# Puzzle Two: A Dark Place:5 ends here + + +# Each time this is “seen”, the response is different, so we use a [[file:~/src/moss-n-puddles/typeclasses/puzzles.py::class Changling(Object):][Changling]]: + + +# [[file:../moss-n-puddles.org::*Puzzle Three: The Changing Obelisk][Puzzle Three: The Changing Obelisk:1]] +@create/drop granite obelisk: typeclasses.puzzles.Changling +# Puzzle Three: The Changing Obelisk:1 ends here + + + +# And pin it down: + + +# [[file:../moss-n-puddles.org::*Puzzle Three: The Changing Obelisk][Puzzle Three: The Changing Obelisk:2]] +@lock obelisk = get:false() +# +@set obelisk/get_err_msg = "That is way too big to lift." +# Puzzle Three: The Changing Obelisk:2 ends here + + + +# The default description will be replaced: + + +# [[file:../moss-n-puddles.org::*Puzzle Three: The Changing Obelisk][Puzzle Three: The Changing Obelisk:3]] +@desc obelisk = A granite obelisk grazes the top of the dome. Each of its four sides show a different image. +# Puzzle Three: The Changing Obelisk:3 ends here + + + +# We build a /changling’s/ description from a =_prefix=, a random =descs=, and a =_postfix=: + + +# [[file:../moss-n-puddles.org::*Puzzle Three: The Changing Obelisk][Puzzle Three: The Changing Obelisk:4]] +@set obelisk/desc_prefix = "A << granite ^ large ^ stone >> obelisk grazes the top of the dome. The surface of the obelisk seem to waver, shift and writhe under your gaze." +# +@set obelisk/desc_postfix = " And << quickly ^ soon ^ swiftly >>, the << image ^ visage ^ vision ^ carving >> << is gone ^ fades ^ disappears ^ vanishes >>." +# Puzzle Three: The Changing Obelisk:4 ends here + + + +# And a list of differences that gives a hint to the password: + + +# [[file:../moss-n-puddles.org::*Puzzle Three: The Changing Obelisk][Puzzle Three: The Changing Obelisk:5]] +@set obelisk/descs = ( + "You can briefly make out the image of ocean waves.", + "For the briefest moment you make out an icy engravings of crystals.", + "You think you can see the outline of grass covered in dew drops.", + "The surface for a moment seems to portray clouds passing by.", + "Trees bordering a flowing river show up on the surface.", +) +# Puzzle Three: The Changing Obelisk:5 ends here + + + +# If they say the /magic word/, they get the maguffin. + + +# [[file:../moss-n-puddles.org::*Puzzle Three: The Changing Obelisk][Puzzle Three: The Changing Obelisk:6]] +@set obelisk/say = { r".*\b[Ww]ater\b": "gm Upon uttering that phrase, sparks of octarine magic and mist appear on the opening on the obelisk. ;; scoring_all blue_medal ;; gm A blue medal materializes in the opening. You snatch it, claiming your prize. +;; gift_all blue ;; gm You also notice a secret door! ;; tag_all hidden_antechamber_door" } +# Puzzle Three: The Changing Obelisk:6 ends here + + +# Another puzzle, another room: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:1]] +@dig Escape Hallway;gr04:typeclasses.rooms_dark.DarkRoom = secret door;door +# Puzzle Four: The Door Puzzle:1 ends here + + + +# And we describe the secret door… + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:2]] +@desc secret door = A door you didn't notice before, looks like stone blocks. Beyond looks like another chamber. +# Puzzle Four: The Door Puzzle:2 ends here + + + +# And the description of entering: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:3]] +@set secret door/traverse_msg = "You slightly stoop to enter the dark chamber beyond..." +# Puzzle Four: The Door Puzzle:3 ends here + + + +# Let’s hide and lock this down: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:4]] +@set secret door/hidden_tag = "hidden_antechamber_door" +# +@lock secret door = view:tag(hidden_antechamber_door) +# Puzzle Four: The Door Puzzle:4 ends here + + + +# Let’s go: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:5]] +@teleport gr04 +# +@desc here = This stone hallway ends with an overly |Yornate door|n covered with letters in rows and columns forming a grid matrix. Placed above the door, a bronze |Yplaque|n, shows its age with a coat of patina. +# Puzzle Four: The Door Puzzle:5 ends here + + + +# Let’s reward our players again: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:6]] +@set here/arrive = "4 ;; gm ... You hear a distant dice roll ... ;; gmm {0} = With your excellent perception, you notice some gold coins hidden in the floor's dust. ;; gma {0} = $You() $conj(relocate) some gold coins on the floor to $pron(your) pouch. ;; coin 10 to {0}" +# Puzzle Four: The Door Puzzle:6 ends here + + + +# We need another door in order to escape. + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:7]] +@detail plaque = Through the green patina, you can barely make out the text:|/ + A spoken word unseals me. + It starts with a T. + Halfway between twins. + The next character lies. +# Puzzle Four: The Door Puzzle:7 ends here + + + +# The door leads back out. + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:8]] +@open ornate door;door = Lonely Island +# Puzzle Four: The Door Puzzle:8 ends here + + + +# The dock is locked: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:9]] +@lock ornate door = traverse:tag(open_ornate_door) +# Puzzle Four: The Door Puzzle:9 ends here + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:10]] +@set ornate door/err_traverse = "The door is locked." +# Puzzle Four: The Door Puzzle:10 ends here + + + +# Look at the grid to find the two T’s: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:11]] +@desc ornate door = The grid of letters look like:|/ + | Y | B | Q | X | D | Q | + | Y | A | K | D | X | B | + | D | E | L | G | W | X | + | T | S | - | A | X | V | + | L | J | H | E | P | V | + | F | U | I | D | I | P | + | H | X | R | G | R | X | + | K | S | M | U | T | N | + | W | X | M | W | Z | Z | +# Puzzle Four: The Door Puzzle:11 ends here + + + +# We use a =StoryCube= to lock the door until the password is said: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:12]] +@create/drop gr04ctl:typeclasses.puzzles.StoryCube +# +@desc gr04ctl = Opens the door when someone says Tidal Surge +# +@lock gr04ctl = view:false() +# +@lock gr04ctl = get:false() +# Puzzle Four: The Door Puzzle:12 ends here + + + +# If they say, /Tidal Surge/, the *Locker* unlocks the door, and they can go through. + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:13]] +@set gr04ctl/say = {r"^tidal ?surge.*": "gm You hear an audible click from the ornate door! ;; tag_all open_ornate_door"} +# Puzzle Four: The Door Puzzle:13 ends here + + + +# And the description of passing through: + + +# [[file:../moss-n-puddles.org::*Puzzle Four: The Door Puzzle][Puzzle Four: The Door Puzzle:14]] +@set ornate door/traverse_msg = "You open the door, and see that the door exits next to the statue..." +# Puzzle Four: The Door Puzzle:14 ends here + + + +# And run it in an /interactive python/ sub-session: + +# [[file:../moss-n-puddles.org::*Bugs][Bugs:2]] +@py +from evennia import TICKER_HANDLER +from evennia.utils.search import search_typeclass + +for pet in search_typeclass("typeclasses.pets.Pet", include_children=True): + TICKER_HANDLER.add(interval=160, callback=pet.update_state) + +for baker in search_typeclass("typeclasses.consumables.Trolley"): + TICKER_HANDLER.add(interval=86400, callback=baker.do_bake) + +for room in search_typeclass("typeclasses.rooms_weather.TimeWeatherRoom"): + TICKER_HANDLER.add(interval=300, callback=room.update_weather) +quit() +# Bugs:2 ends here + + + +# Let’s take a look at all the tickers: + + +# [[file:../moss-n-puddles.org::*Bugs][Bugs:3]] +@py from evennia import TICKER_HANDLER; print(TICKER_HANDLER.all_display()) +# Bugs:3 ends here + + # And now that we are done, say it: -# [[file:../moss-n-puddles.org::*Bugs][Bugs:1]] -@teleport/quiet mp05 +# [[file:../moss-n-puddles.org::*Bugs][Bugs:5]] +@teleport/quiet mp01 # say I have finished this, the first version, of my creation. -# Bugs:1 ends here +# Bugs:5 ends here + + +# The /janitor/ is a =Script= that moves every thing back to where they should be at the end of the day. + + +# [[file:../moss-n-puddles.org::*Janitor][Janitor:1]] +@script janitor:typeclasses.janitor.Janitor +# Janitor:1 ends here