Create a Janitor to clean rooms if too much debris appears
This commit is contained in:
parent
d2fda42a32
commit
503dd0301a
7 changed files with 1813 additions and 133 deletions
|
|
@ -288,10 +288,7 @@ class CmdGM(MuxCommand):
|
||||||
msg = routput(self.args)
|
msg = routput(self.args)
|
||||||
for o in send_to:
|
for o in send_to:
|
||||||
if o.is_typeclass('typeclasses.rooms.Room'):
|
if o.is_typeclass('typeclasses.rooms.Room'):
|
||||||
# Send the message to all characters and any recording
|
o.msg_contents(msg)
|
||||||
# scribes in attendance:
|
|
||||||
chars = o.contents_get(None, 'character') + [o.has(Scribe)]
|
|
||||||
send_emote(me, chars, msg, 'say', None)
|
|
||||||
elif o.is_typeclass('typeclasses.characters.Character'):
|
elif o.is_typeclass('typeclasses.characters.Character'):
|
||||||
o.msg(msg)
|
o.msg(msg)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,24 +10,11 @@
|
||||||
#+PROPERTY: header-args:yaml :tangle ~/src/moss-n-puddles/world/hints.yaml
|
#+PROPERTY: header-args:yaml :tangle ~/src/moss-n-puddles/world/hints.yaml
|
||||||
#+PROPERTY: header-args :results none :eval no-export :comments no
|
#+PROPERTY: header-args :results none :eval no-export :comments no
|
||||||
|
|
||||||
|
- [ ] The Troll’s gambling den … part of the bar? under the bridge?
|
||||||
- [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.
|
|
||||||
- [ ] Create goggles to show /gold tint/, and remove the /tint/ otherwise
|
- [ ] 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
|
- [ ] Create /Peddler/, the goblin, and his Emporium and Home Furnishings
|
||||||
- A new =buy= command that exchanges money for an item.
|
- A new =buy= command that exchanges money for an item.
|
||||||
- Need a sign with the items and money … come from a YAML file?
|
- 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
|
* Evennia Server
|
||||||
** Background
|
** 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.
|
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.
|
Then wake it.
|
||||||
|
|
||||||
#+BEGIN_SRC evennia
|
#+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
|
#+END_SRC
|
||||||
|
|
||||||
And his description:
|
And his description:
|
||||||
|
|
@ -1696,6 +1683,12 @@ It will wake at 8am …
|
||||||
@set beast/wake_hour = 8
|
@set beast/wake_hour = 8
|
||||||
#+END_SRC
|
#+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:
|
Let’s set some behavior levels. For instance, the beast is sad when he doesn’t see its friends:
|
||||||
|
|
||||||
#+BEGIN_src evennia
|
#+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."
|
@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
|
#+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
|
#+BEGIN_SRC tcl
|
||||||
send "leave\n"
|
send "leave\n"
|
||||||
|
|
@ -4044,6 +4037,25 @@ Test if it is readable:
|
||||||
expectit "This granny knot"
|
expectit "This granny knot"
|
||||||
#+END_SRC
|
#+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
|
*** Raven
|
||||||
Here for hints … and a bit of a distraction.
|
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.
|
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
|
#+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.
|
@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.
|
@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
|
#+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.
|
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?
|
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:
|
And let’s not let anyone pick it up:
|
||||||
|
|
||||||
#+BEGIN_SRC evennia
|
#+BEGIN_SRC evennia
|
||||||
|
@lock butterfly = get:false()
|
||||||
|
#
|
||||||
@set butterfly/get_err_msg = "It quickly flutters away, only to land a few feet away."
|
@set butterfly/get_err_msg = "It quickly flutters away, only to land a few feet away."
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
|
@ -5221,19 +5236,19 @@ And give him the powers he deserves:
|
||||||
#+BEGIN_src evennia
|
#+BEGIN_src evennia
|
||||||
@set gnome/pose_sleep = "sleeping soundly in a large, overstuffed chair"
|
@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
|
#+END_SRC
|
||||||
|
|
||||||
And a good description that I can rework:
|
And a good description that I can rework:
|
||||||
|
|
||||||
#+BEGIN_src evennia
|
#+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
|
#+end_src
|
||||||
|
|
||||||
And an un-puppeted, sleeping, description:
|
And an un-puppeted, sleeping, description:
|
||||||
|
|
||||||
#+BEGIN_src evennia
|
#+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
|
#+END_SRC
|
||||||
|
|
||||||
And we create a couple of objects:
|
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.
|
The pipe is little more than messages to the smoker and everyone else in the room.
|
||||||
|
|
||||||
#+BEGIN_src evennia
|
#+BEGIN_src evennia
|
||||||
@create pipe: typeclasses.things.Pipe
|
@create carved pipe: typeclasses.things.Pipe
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
And a description:
|
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.
|
@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
|
#+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:
|
Initial default state is unfinished:
|
||||||
|
|
||||||
#+BEGIN_SRC evennia
|
#+BEGIN_SRC evennia
|
||||||
|
|
@ -7407,7 +7430,7 @@ Character 3: Twiggy, an automaton or golem made from sticks. When he drinks tea
|
||||||
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
Get the hell out of dodge:
|
Get the hell out of dodge and back to the Grove:
|
||||||
#+BEGIN_SRC tcl
|
#+BEGIN_SRC tcl
|
||||||
send "leave\n"
|
send "leave\n"
|
||||||
expectit "Dark Tunnel"
|
expectit "Dark Tunnel"
|
||||||
|
|
@ -7420,12 +7443,6 @@ Get the hell out of dodge:
|
||||||
|
|
||||||
send "west\n"
|
send "west\n"
|
||||||
expectit "Grove of the Matriarchs"
|
expectit "Grove of the Matriarchs"
|
||||||
|
|
||||||
send "west\n"
|
|
||||||
expectit "Grotto"
|
|
||||||
|
|
||||||
send "door\n"
|
|
||||||
expectit "Cozy House"
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** Deep Forest
|
** Deep Forest
|
||||||
The deep forest is a place where all the Puppets can hang out when not in use.
|
The deep forest is a place where all the Puppets can hang out when not in use.
|
||||||
|
|
@ -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 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.
|
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
|
#+END_SRC
|
||||||
|
|
||||||
Finally, let’s awaken him:
|
Finally, let’s awaken him:
|
||||||
|
|
@ -7749,18 +7765,759 @@ Finally, let’s awaken him:
|
||||||
#+BEGIN_SRC evennia
|
#+BEGIN_SRC evennia
|
||||||
py rick = me.search("rick") ; rick.backstory("barbarian")
|
py rick = me.search("rick") ; rick.backstory("barbarian")
|
||||||
#+END_SRC
|
#+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. <morning>The morning sun peaks above the colossal trees and the snow-capped mountains beyond.</morning><afternoon>The afternoon sun peaks out briefly from misty clouds.</afternoon><evening>The evening sun begins to set on a watery horizon.</evening><night>The moon peaks out from behind wispy clouds.</night>
|
||||||
|
#+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
|
** 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
|
||||||
|
<<ticker-handler-script>>
|
||||||
|
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:
|
And now that we are done, say it:
|
||||||
|
|
||||||
#+BEGIN_src evennia
|
#+BEGIN_src evennia
|
||||||
@teleport/quiet mp05
|
@teleport/quiet mp01
|
||||||
#
|
#
|
||||||
say I have finished this, the first version, of my creation.
|
say I have finished this, the first version, of my creation.
|
||||||
#+END_SRC
|
#+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
|
** Finish Testing
|
||||||
Can we quickly walk back through the world, gathering ingredients, and then going back into the Secret Room to make potions?
|
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"
|
send "west\n"
|
||||||
expectit "Grove"
|
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"
|
send "disembark\n"
|
||||||
expectit "Lonely Island"
|
expectit "Lonely Island"
|
||||||
|
|
||||||
|
|
@ -8150,24 +8896,6 @@ You sample from your teacup.
|
||||||
> =throw book in fire=
|
> =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.
|
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
|
* 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.
|
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.
|
||||||
|
|
||||||
|
|
|
||||||
95
typeclasses/janitor.py
Executable file
95
typeclasses/janitor.py
Executable file
|
|
@ -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)
|
||||||
|
|
@ -570,7 +570,12 @@ class WeeBeastie(Friendly, Familiar, Listener, AI):
|
||||||
|
|
||||||
|
|
||||||
class BHB(Friendly, 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):
|
def return_appearance(self, looker):
|
||||||
|
"""The beast looks different when it is sleeping."""
|
||||||
if self.db.is_awake:
|
if self.db.is_awake:
|
||||||
return super().return_appearance(looker)
|
return super().return_appearance(looker)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -353,7 +353,7 @@ class Wood(Litterable):
|
||||||
]))
|
]))
|
||||||
|
|
||||||
|
|
||||||
class Stick(Consumable):
|
class Stick(Object):
|
||||||
"An object to throw."
|
"An object to throw."
|
||||||
def at_object_creation(self):
|
def at_object_creation(self):
|
||||||
self.cmdset.add_default(CmdSetStick)
|
self.cmdset.add_default(CmdSetStick)
|
||||||
|
|
|
||||||
|
|
@ -1204,11 +1204,95 @@ expectit "Frog Meadow"
|
||||||
send "west\n"
|
send "west\n"
|
||||||
expectit "Grove of the Matriarchs"
|
expectit "Grove of the Matriarchs"
|
||||||
|
|
||||||
send "west\n"
|
send "south\n"
|
||||||
expectit "Grotto"
|
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"
|
send "door\n"
|
||||||
expectit "Cozy House"
|
expectit "Escape Hallway"
|
||||||
|
|
||||||
send "leave\n"
|
send "leave\n"
|
||||||
expectit "Grotto"
|
expectit "Grotto"
|
||||||
|
|
@ -1346,17 +1430,6 @@ expectit "Frog Meadow"
|
||||||
send "west\n"
|
send "west\n"
|
||||||
expectit "Grove"
|
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"
|
send "disembark\n"
|
||||||
expectit "Lonely Island"
|
expectit "Lonely Island"
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue