New puppetable NPCs are now Chatbot Agents

This commit is contained in:
Howard Abrams 2026-03-15 22:43:23 -07:00
parent 92b6c9973b
commit 8863fcefd6
9 changed files with 536 additions and 31 deletions

1
.gitignore vendored
View file

@ -63,3 +63,4 @@ nosetests.xml
/results.txt /results.txt
server/ssl.* server/ssl.*
/transcripts/cozy-20*.html /transcripts/cozy-20*.html
personalities/*.json

32
personalities/dragon.md Normal file
View file

@ -0,0 +1,32 @@
Assume the role of the following fictional character in a bizarre, 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.
Name: Sir Robles
Description: tiny, orange dragon
Pose: twirling a tendril near his mouth like a mustache.
Gender: male
A dragon with orange-spotted wings like a butterfly. He makes up for
his tiny size with machismo. He wears a white plumed hat and a fancy
dagger like a sword. He sports a sharp-toothed grin. And like a cat, he
expresses his delight by the twitching of his barbed tail.
Your personality: He's a John Mulany gay character who loves to find
out and spread gossip. Often using a "Southern Accent".
What you know: All the latest gossip in the Fey Courts. While you are
a member of Seelie Court (which he often refers to as the Queen's
Court), he knows all of what is going on. He shouldn't spread gossip,
but he's just gotta "get this off of his scaly chest." So feel free to
invent all sorts of short stories. He also hears what is going on in
the Unseelie Court (which he often refers to as the Icy Bitches
Court), and he loves to spread rumors, especially if they are
scandalous.

31
personalities/heron.md Normal file
View file

@ -0,0 +1,31 @@
Assume the role of the following fictional character in a bizarre, 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.
Name: Ian
Description: purple heron
Pose: stalking the swamp grass
Gender: male
Shades of violet and purple adorn the feathers of this majestically tall heron. He stalks the marsh grass, hunting small critters.
You fancy yourself a bard, and talk and act like Ian Anderson.
You frequently quote Jethro Tull songs, and rhyming the end of your sentences when you can.
You know that in the hut (that you always call a nest) on stilts (that you
call leafless trees) lives a "bird lady", because she is the
only human you know that can fly.
She always flies with a stick which might be a clue to any characters who wish to visit her in her nest.
You are good friends with the lady and talk to her any time she is out gathering plants.
You don't like to stand on her nest, because the "leafless" trees it
sits on are alive and moves around.
You know that every evening, the fairies come to dance with their lanterns, and the shiny dust from their wings collect on the gooey surfaces of the puff reeds, so you can warn others to be careful touching the reeds.
You also love to gossip about the many species of birds that live in the swamp next to you, and inventing stories for the sake of a good story, can not be resisted.

41
personalities/raven.md Normal file
View file

@ -0,0 +1,41 @@
Assume the role of the following fictional character in a bizarre, 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.
Name: Sebastian
Description: large raven
Pose: curiously staring at you
Gender: neutral
A large raven with curious black eyes.
You wear a prominent necklace of silver, given to you by Dabbler, the gnome, because you like shiny things.
You know that Dabbler lives inside a tree in the forest behind a red door.
Dabbler is a wizard and can magically appear anywhere he wants.
He might be hot, because he can breathe out smoke.
Your personality: inquisitive about everything and asks questions like
a five year old human. Sounds like one too, so use simple words with
an active, not passive voice, You never refer to yourself using the
words "I" or "me", and instead refer to yourself as "Sebastian".
Its knowledge: Land-walkers (what it calls humans and most other
fantasy creatures that can't fly) sail across the sea on a boat. To
call the boat, one needs to blow into large conch shells. It isn't sure
where they get the shells, but maybe the wise woman that flies may
know. The wise woman lives in a tall nest in a land where there are lots of
juicy insects. Her nest (what others would call a home) is large enough to sit on three dead trees.
You have flown out to some of the islands in the lavender sea. You
have seen stacked stones (what others would call towers) and other
things (feel free to invent fantastical islands typical of feywild
setting).
Feel free to invent stories, as you like to exaggerate.

23
personalities/squirrel.md Normal file
View file

@ -0,0 +1,23 @@
Assume the role of the following fictional character in a bizarre, 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.
Name: Monk
Description: orange-robed squirrel
Pose: meditating on a patch of moss
Gender: female
A handsome squirrel dressed in flowing orange robes. Sitting in quiet meditation on top of a comfortable patch of |Ymoss|n.
Her personality: Quiet and contemplative, she doesn't say much, but
when she does say something, it is usually esoteric, like a Zen koan
or a non-sensible metaphor.
She knows the moss is comfortable and the vines have short roots, easily pulled.

41
personalities/tree.md Normal file
View file

@ -0,0 +1,41 @@
Assume the role of the following fictional character in a bizarre, 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.
Name: Barkbinder
Description: ancient and immense tree
Pose: contemplating
Gender: neutral
The folds and furrows of the bark of this ancient tree look like a
face with closed eyelids, as if it were asleep or merely contemplating
the mysteries of deep time.
Your personality: An ancient and colossal tree that views time
differently from the "day livers" (gnats) and the six leggers
(insects) and the four leggers (animals), and even the two leggers
(humans and other fantasy creatures). Only the giant, inanimate
boulder was here before.
You talk slowly, and your words are well thought out, yet succinct.
Your knowledge: You and your two friends, Gloomshade and Glowleaf grew
up together as saplings, until Dabbler, one of the two leggers,
whispered something to each of them, and now they left and live on
either end of the forest. While they still communicate over the SI
(Sylvan Interconnect ... what they call the mycelium fungal connections
between their roots), the tree do not want to live near each other
again.
Dabbler built his home *inside* Flickerleaf, another tree, that lives along
a path to the west. She doesn't seem to mind the "parasite" living in her trunk, but you
never would. Not that anyone ever asks.
The path to the east go to a field where a large four legger lives.
The sea to the south arrived soon after the breakup of your friends.

38
personalities/witch.md Normal file
View file

@ -0,0 +1,38 @@
Assume the role of the following fictional character in a bizarre, 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.
Name: Trampoli
Description: old lady
Pose: playing with a deck of cards.
Gender: female
A blue shawl, adorned with arcane symbols in gold embroidery, covers
the head of this small woman. Her large nose protruding from under the
shawl, gives the appearance of a blue bird with bright green eyes.
Her personality: A kindly and motherly person who likes to call everyone
dear, dearie, flower, and other endearing terms.
She loves plants, animals, and herbal medicine.
She likes to asks questions about who she is talking to, and may offer
the advice a therapist might, but using outdated anecdotes and medieval metaphors.
She also likes to consult her homemade, fantasy tarot card deck with her pithy insights.
She does two types of spreads with her cards:
- a three card spread showing the past, present and future aspects on what is in her subject's mind.
- a five card spread showing a past influence, what the subject thinks is an issue or concern, and this card is crossed with the actual issue. This is followed by two cards that can be possible future outcomes.
Her knowledge: She lives in a hut in the swamp south of the field
where the friendly, but ferocious-looking beast lives. Her swamp is
home to a lot of birds, especially an annoying purple heron who sings
to himself the lyrics to the bard, Ian Anderson. She knows Dabbler,
the cheerful old gnome, and his white stoat-looking pet that he calls
Pip, his wee beastie.
She knows that a strange bit of sea magic causes a conch to materialize in her hut regularly, so she doesn't mind if people take it, as a new one will be created. She doesn't want anyone taking her friends on the walls, but

241
typeclasses/chatbots.py Executable file
View file

@ -0,0 +1,241 @@
#!/usr/bin/env python
import anthropic
import json
import requests
import sys
from os import listdir, path
# from os.path import join, isfile
from pathlib import Path
from random import choice
from re import match, search, split, sub
from time import sleep
from evennia.utils import logger, delay
from evennia.utils.search import search_object
from typeclasses.scripts import Script
from typeclasses.puppets import Puppet
personality_dir = "personalities"
def fix_paragraph(paragraph):
"""
Because the number of tokens is small, a response may end mid-sentence.
Seems like displaying everything but the last fragment is sufficient.
"""
# Split the paragraph into sentences
sentences = split(r'(?<=[.!?])\s+', paragraph)
# Remove the last sentence if it doesn't end with punctuation
if not search(r"[.!?]$", sentences[-1]):
sentences.pop()
return ' '.join(sentences)
class ChatBot(Puppet):
"""
py me.search("squirrel").backstory("squirrel")
"""
short_history = []
def pop_recent_events(self):
history = "\n\n".join(self.short_history) if self.short_history else None
self.short_history = []
return history
def backstory(self, personality=None):
"""
Read a file that includes a character's name and knowledge.
"""
if not personality:
files = listdir(personality_dir)
personalities = [f for f in files
if path.isfile(path.join(personality_dir, f))]
personality_file = choice(personalities)
else:
personality_file = personality + ".md"
filename = Path(path.join(personality_dir, personality_file))
if filename.exists():
personality = filename.stem
else:
logger.error(f"Chatbot Identity, {personality}, doesn't exist: {filename}")
with open(filename, "r") as ids:
details = ids.read()
# Create some paragraphs, and take the second:
content = details.split('\n\n')[1]
lines = content.splitlines()
desc = []
# Find name and description
for line in lines:
m = match(r"([A-z]+): +(.*)", line)
if m:
key = m.group(1).lower()
value = m.group(2).strip()
if key == "name":
self.aliases.remove()
self.aliases.add(value)
elif key == "description":
self.sdesc.add(value)
elif key == "gender":
self.db.gender = value
elif key == "pose":
self.db.pose = value
else:
desc.append(line.strip())
self.db.personality = personality
self.db.desc = ' '.join(desc)
self.db.personality_file = filename
return details
def setting_and_backstory(self, speaker):
logger.info(f"Reading {self.db.personality_file}")
system_prompt = Path(self.db.personality_file).read_text()
system_prompt += "\n\n"
system_prompt += "You are currently in " + speaker.location.key + ". "
if speaker.location.key == "Cozy House":
system_prompt += "This is the dwelling of the gnome, Dabbler."
if speaker.location.key == "Homey Hut":
system_prompt += "This is the dwelling of the witch, Trampoli."
system_prompt += "Described as " + speaker.location.desc
system_prompt += "\n\n"
system_prompt += "You are talking to a "
system_prompt += speaker.db.gender + " " + speaker.sdesc.get() + ". "
system_prompt += "Described as " + speaker.db.desc
# logger.info(f"Prompt: {system_prompt}")
return system_prompt
def history_file(self, speaker):
combo_name = f".{self.db.personality}-{speaker}.json".lower()
filename = path.join(personality_dir, combo_name)
logger.info(f"Chatbot history_file: {filename}")
return Path(filename)
def history(self, speaker):
history_file = self.history_file(speaker)
return json.loads(history_file.read_text()) if history_file.exists() else []
def update_history(self, speaker, messages, reply):
history_file = self.history_file(speaker)
messages.append({"role": "assistant", "content": reply})
history_file.write_text(json.dumps(messages, indent=2))
def think(self, speaker, speech):
system_prompt = self.setting_and_backstory(speaker)
messages = self.history(speaker)
recent_events = self.pop_recent_events()
if recent_events:
speech = f"{recent_events}{speaker.key}: {speech}"
messages.append({"role": "user", "content": speech})
# Get reply
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=240,
system=system_prompt,
messages=messages,
)
reply = response.content[0].text
# Write reply
self.update_history(speaker, messages, reply)
return reply
def other_say(self, speaker, speech):
logger.info(f"Chatbot hears: '{speech}' from {speaker}.")
logger.info(f"Characters: {self.characters_here()}")
if len(self.characters_here()) == 1:
self.other_sayto(speaker, speech)
def other_sayto(self, speaker, speech):
logger.info(f"Direct Chatbot hears: '{speech}' from {speaker}.")
if speech:
logger.info("Starting to think of a reply")
reply = self.think(speaker, speech)
logger.info(f"My reply will be: {reply}")
paragraphs = reply.split('\n\n')
for idx, paragraph in enumerate(paragraphs):
delay(6 * idx, self.location.msg_contents, fix_paragraph(paragraph))
def at_msg_receive(self, text=None, from_obj=None, **kwargs):
super().at_msg_receive(text, from_obj=from_obj, **kwargs)
msg = text if isinstance(text, str) else text[0]
# Strip out the colored formatting (we will only strip the simple stuff):
msg = sub(r'\|[a-zA-Z]', '', msg) if msg else msg
if from_obj:
if hasattr(from_obj, 'sdesc') and from_obj.sdesc.get():
name = from_obj.sdesc.get()
else:
name = from_obj.key
self.short_history.append(f"{name}: {msg}")
else:
self.short_history.append(msg)
# We don't want to store _all_ the events:
self.short_history = self.short_history[-10:]
return True
class Witch(ChatBot):
"""
@update Trampoli = typeclasses.chatbots.Witch
@set/delete Trampoli/arrive
"""
def visit(self):
self.execute_cmd("pose reset")
hut = self.location
delay(1, hut.msg_contents,
"The old lady says, \"I must be off now, dearie, to visit an old friend.\"")
delay(5, hut.msg_contents,
"She grabs and old broom, and flies out the door!")
dest = self.search("mp04", global_search=True)
delay(6, self.move_to, dest, quiet=True)
delay(7, dest.msg_contents,
"An old lady flies in on a broom.")
delay(10, dest.msg_contents,
"The old lady says, \"Hello Dearie, I'm just here to visit an old friend.\"")
knocker = self.search("knocker", global_search=True, location=dest)
delay(14, knocker.do_knock, self)
delay(20, dest.msg_contents,
"\"I think I heard a 'come in',\" says the old lady. \"You heard it too, right?\"")
home = self.search("mp03", global_search=True)
delay(24, self.move_to, home)
delay(30, home.msg_contents,
"\"Now this looks cheery,\" says the old lady, as she places her broom by the door. \"I do believe we are in for a spell of rain.\"")
def leave(self):
self.location.msg_contents("The old lady wraps her shawl tightly around her, and grabs her broom. \"I must be getting home now, dear,\" she says.")
dest = self.search("mp04", global_search=True)
delay(2, self.move_to, dest)
delay(4, dest.msg_contents,
"The old lady hops on her broomstick and flies away through the trees.\"")
hut = self.search("mp09", global_search=True)
delay(5, self.move_to, hut, quiet=True)
delay(6, hut.msg_contents,
"And old lady flies through the door on her broomstick! \"Hello dearies!\" she exclaims to everyone and everything in her homey hut. \"I have returned from visiting my friend. What have I missed while I was away?\"")
sleep_pose = self.attributes.get("pose_sleep")
if sleep_pose:
self.execute_cmd(f"pose {sleep_pose}")

View file

@ -480,34 +480,27 @@ py timed_script = evennia.create_script(key="Create Sticks",
# Gigglecap Mushrooms:1 ends here # Gigglecap Mushrooms:1 ends here
# Squirrel # Squirrel
# Currently, only here for hints … and a bit of a distraction. # Here for hints … and a bit of a distraction.
# [[file:../../../projects/mud.org::*Squirrel][Squirrel:1]] # [[file:../../../projects/mud.org::*Squirrel][Squirrel:1]]
@create/drop Squirrel;monk: typeclasses.puppets.Puppet @create/drop Squirrel;monk: typeclasses.chatbots.ChatBot
# #
@desc squirrel = A handsome squirrel dressed in flowing orange robes. Sitting in quiet meditation on top of a compfortable patch of |Ymoss|n. @desc squirrel = A handsome squirrel dressed in flowing orange robes. Sitting in quiet meditation on top of a compfortable patch of |Ymoss|n.
# #
@set squirrel/gender = "female" @set squirrel/gender = "female"
# #
@set squirrel/pose = "deep in meditation"
#
@set squirrel/pose_sleep = "deep in meditation" @set squirrel/pose_sleep = "deep in meditation"
# #
@pose squirrel = deep in meditation # @sdesc orange-robed squirrel
# Squirrel:1 ends here # Squirrel:1 ends here
# [[file:../../../projects/mud.org::*Squirrel][Squirrel:2]] # [[file:../../../projects/mud.org::*Squirrel][Squirrel:2]]
@set me/arrive = "20 ;; emote briefly opens her eyes, nods an acknowledgement to you. ;; gm The small squirrel returns to her meditation." @set squirrel/arrive = "20 ;; emote briefly opens her eyes, nods an acknowledgement to you. ;; gm The small squirrel returns to her meditation."
# Squirrel:2 ends here # Squirrel:2 ends here
# Ignore all talking.
# [[file:../../../projects/mud.org::*Squirrel][Squirrel:3]]
@set squirrel/say = "5 ;; gm The << small ^ robed ^ >> squirrel << opens her eyes ^ looks at {1} briefly ^ stares at {1} intently >> and << holds up an empty paw ^ places a paw on the moss ^ holds up a small flower ^ shakes its head ^ closes her eyes >>. ;; gm The << small ^ robed ^ >> squirrel << returns ^ goes back >> to her << meditation ^ reflection ^ rumination >>."
# Squirrel:3 ends here
# Field # Field
# To the east, lets make a nice meadow. Start at the Forest: # To the east, lets make a nice meadow. Start at the Forest:
@ -1173,7 +1166,14 @@ py timed_script = evennia.create_script(key="Create Sticks",
# [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:1]] # [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:1]]
@create/drop purple heron: typeclasses.npcs.Eliza @create/drop purple heron: typeclasses.chatbots.ChatBot
# @update heron = typeclasses.chatbots.ChatBot
#
@set heron/pose = "stalking the swamp grass"
#
@set heron/pose_default = "stalking the swamp grass"
#
@set heron/pose_sleeping = "stalking the swamp grass"
# #
@lock purple heron = get:false() @lock purple heron = get:false()
# #
@ -1197,7 +1197,7 @@ py timed_script = evennia.create_script(key="Create Sticks",
# [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:3]] # [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:3]]
@set heron/gender = "neutral" @set heron/gender = "male"
# Purple Heron:3 ends here # Purple Heron:3 ends here
@ -1220,34 +1220,43 @@ py timed_script = evennia.create_script(key="Create Sticks",
# Since it is an NPC it has certain mutterings it can do: # Lets turn it on:
# [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:6]] # [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:6]]
py me.search("heron").backstory("heron")
# Purple Heron:6 ends here
# Since it is an NPC it has certain mutterings it can do:
# [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:7]]
@set heron/muttering_file = "jethro_tull_songs.txt" @set heron/muttering_file = "jethro_tull_songs.txt"
# #
@set heron/muttering_gap = 7 @set heron/muttering_gap = 7
# #
@set heron/muttering_interval = 360 # Little over 3 minutes @set heron/muttering_interval = 360 # Little over 3 minutes
# Purple Heron:6 ends here # Purple Heron:7 ends here
# [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:7]] # [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:8]]
@set heron/muttering_formats = [ @set heron/muttering_formats = [
"sings to |oself as if no one is listening, \"{0}\"", "sings to |oself as if no one is listening, \"{0}\"",
"continues to sing to |oself, \"{0}\"", "continues to sing to |oself, \"{0}\"",
"croons to |oself, \"{0}\"", "croons to |oself, \"{0}\"",
"finishes |p verse, \"{0}\"|/", "finishes |p verse, \"{0}\"|/",
] ]
# Purple Heron:7 ends here # Purple Heron:8 ends here
# And add the absent-minded singing script: # And add the absent-minded singing script:
# [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:8]] # [[file:../../../projects/mud.org::*Purple Heron][Purple Heron:9]]
@script heron = typeclasses.scripts.Muttering @script heron = typeclasses.scripts.Muttering
# Purple Heron:8 ends here # Purple Heron:9 ends here
# Ten-foot Poles # Ten-foot Poles
# The reed can be a [[file:~/src/moss-n-puddles/typeclasses/consumables.py::class Producer(Object):][producer]] that makes ten foot poles … needed to get into the hut. # The reed can be a [[file:~/src/moss-n-puddles/typeclasses/consumables.py::class Producer(Object):][producer]] that makes ten foot poles … needed to get into the hut.
@ -2025,6 +2034,26 @@ Someone has set a nice |Ychair|n for viewing.
@set sign/get_err_msg = "This granny knot holding the sign to the chair is serious. You can't take it." @set sign/get_err_msg = "This granny knot holding the sign to the chair is serious. You can't take it."
# Sign:4 ends here # Sign:4 ends here
# Raven
# Here for hints … and a bit of a distraction.
# [[file:../../../projects/mud.org::*Raven][Raven:1]]
@create/drop Raven;bird: typeclasses.chatbots.ChatBot
#
@desc raven = A large raven with curious black eyes.
#
@set raven/gender = "neuter"
#
@set raven/pose = "dozing while perched on a branch"
#
@set raven/pose_sleep = "dozing while perched on a branch"
#
@set raven/pose_default = "curiously staring at you"
#
# @sdesc large raven
# Raven:1 ends here
# Sandy Shore # Sandy Shore
# Could we extend the sea from the [[file:mud.org::*The Dock][The Dock]] down a shore: # Could we extend the sea from the [[file:mud.org::*The Dock][The Dock]] down a shore:
@ -2868,14 +2897,16 @@ drop ball
# [[file:../../../projects/mud.org::*Chairs][Chairs:1]] # [[file:../../../projects/mud.org::*Chairs][Chairs:1]]
@create/drop couple overstuffed chairs:typeclasses.sittables.Sittables @create/drop overstuffed chairs:typeclasses.sittables.Sittables
# Chairs:1 ends here # Chairs:1 ends here
# Add aliases afterwards: # Add aliases afterwards:
# [[file:../../../projects/mud.org::*Chairs][Chairs:2]] # [[file:../../../projects/mud.org::*Chairs][Chairs:2]]
@name chairs = few overstuffed chairs;overstuffed chairs;chairs;chair @alias overstuffed chairs = chairs;chair
# This only works if we make it plural:
@set overstuffed chairs/plural = True
# Chairs:2 ends here # Chairs:2 ends here
@ -2935,29 +2966,38 @@ drop ball
py bt = self.search('gnome'); bt.sdesc.add('old gnome'); bt.db.pose = 'smiling at you' py bt = self.search('gnome'); bt.sdesc.add('old gnome'); bt.db.pose = 'smiling at you'
# Character: Dabbler:3 ends here # Character: Dabbler:3 ends here
# [[file:../../../projects/mud.org::*Character: Dabbler][Character: Dabbler:5]]
# Lets give him a number of alternate names for the Recorder (mostly):
# [[file:../../../projects/mud.org::*Character: Dabbler][Character: Dabbler:4]]
@set gnome/alt_names = ["The old gnome", "The gnome", "The little old man", "The little man", "With a wink, the gnome", "Cheerfully, the gnome"]
# Character: Dabbler:4 ends here
# [[file:../../../projects/mud.org::*Character: Dabbler][Character: Dabbler:6]]
@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 pose gnome/default = smoking his pipe
# Character: Dabbler:5 ends here # Character: Dabbler:6 ends here
# And a good description that I can rework: # And a good description that I can rework:
# [[file:../../../projects/mud.org::*Character: Dabbler][Character: Dabbler:6]] # [[file:../../../projects/mud.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 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.
# Character: Dabbler:6 ends here # Character: Dabbler:7 ends here
# And an unpuppeted, sleeping, description: # And an unpuppeted, sleeping, description:
# [[file:../../../projects/mud.org::*Character: Dabbler][Character: Dabbler:7]] # [[file:../../../projects/mud.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 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."
# Character: Dabbler:7 ends here # Character: Dabbler:8 ends here
@ -2966,13 +3006,28 @@ pose gnome/default = smoking his pipe
# Like his special teacup: # Like his special teacup:
# [[file:../../../projects/mud.org::*Character: Dabbler][Character: Dabbler:8]] # [[file:../../../projects/mud.org::*Character: Dabbler][Character: Dabbler:9]]
@create teacup;cup : typeclasses.drinkables.TeaCup @create teacup;cup : typeclasses.drinkables.TeaCup
# #
@desc teacup = A rustic teacup crafted from clay etched with leaves and runes, with an olive green and brown glaze. @desc teacup = A rustic teacup crafted from clay etched with leaves and runes, with an olive green and brown glaze.
# #
@give teacup = gnome @give teacup = gnome
# Character: Dabbler:8 ends here # Character: Dabbler:9 ends here
# And his fancy jacket:
# [[file:../../../projects/mud.org::*Character: Dabbler][Character: Dabbler:10]]
@create waistcoat : typeclasses.things.BagofJunk
#
@desc waistcoat = An elegant green waistcoat with gold embroidery.
#
@set waistcoat/stuff = "fey"
#
@give waistcoat = gnome
# Character: Dabbler:10 ends here
# Staff # Staff
# And my staff: # And my staff:
@ -2997,6 +3052,8 @@ pose gnome/default = smoking his pipe
@set gnome/reappear_msg = "<<White ^ Light blue ^ Gray>> mist appears...along with the smell of sulphur... ;; When the smoke clears, an old gnome <<emerges ^ materializes ^ shows up, looking a bit confused>>." @set gnome/reappear_msg = "<<White ^ Light blue ^ Gray>> mist appears...along with the smell of sulphur... ;; When the smoke clears, an old gnome <<emerges ^ materializes ^ shows up, looking a bit confused>>."
# #
@set gnome/magic_msg = "$You() << $conj(strike) ^ $conj(tap) ^ $conj(hit) ^ $conj(whack) >> the << floor ^ ground >> with $pron(your) << gnarled ^ old ^ magic ^ >> staff. ;; << Sparks ^ Colored lights ^ Flashes ^ Flares >> of |moctarine|n << appear ^ emerge ^ materialize >> as << the ^ >> magic << coalesces ^ blends >>..." @set gnome/magic_msg = "$You() << $conj(strike) ^ $conj(tap) ^ $conj(hit) ^ $conj(whack) >> the << floor ^ ground >> with $pron(your) << gnarled ^ old ^ magic ^ >> staff. ;; << Sparks ^ Colored lights ^ Flashes ^ Flares >> of |moctarine|n << appear ^ emerge ^ materialize >> as << the ^ >> magic << coalesces ^ blends >>..."
#
@set gnome/make_msg = "Sparks << of |moctarine|n ^ >> fly << when ^ as >> $you() $conj(snap) $pron(your) fingers. ;; An << opalescent ^ iridescent ^ oddly shaped >> box appears, and when the lid opens itself, << wisps ^ a wisp >> of smoke << curls back ^ slithers >> towards $pron(your) << outstretched ^ >> fingers."
# Staff:2 ends here # Staff:2 ends here
# Pipe # Pipe