Tiny Big Woods

Malan's DragonMUD Adventure

The scene is based on 1800s northeast Alabama on Sand Mountain, a plateau 70 miles long rising 700 feet and running to the northeast. There was a wilderness there the Indians called the Big Woods.

This document is a collection of my notes and thoughts as I learn building at DragonMUD.

All the Best of Life,
(Northeast Tower, Room 308)

          o                d   |\
          |            o   o   o o
          C---o         \ /    |/
         / \             o     o
        o   o--o          \    |
             \ |           o   |
              \|               |


TinyBigWoods Feature Summary

  1. Listen to Menawa's hints
  2. Meet Talisa
  3. Break your leg
  4. Get rescued
  5. Get bit by a snake
  6. Find a cure for snake-bite or die
  7. Visit the spring
  8. The spring inspires you to remember
  9. Explore cave. There are many ways to die
  10. Get lost in cave crevice, unless you heeded Menawa's hint

Misc. Notes

  1. I experimented with both the group lock and action lock techniques for "listen to Menawa". I think the action lock technique is more appropriate for displaying sequential messages, because it is (perhaps) easier to maintain. However the group lock technique has some additional benefits and is required (I think) for what I'm trying to do in Spring of Memories. Now I can't help but wonder about an application where the two techniques are combined ;-) [edit: see "Remember" below for an example of combining the two techniques]
  2. I made-up my own names for these two techniques because I didn't know what else to call them. Applications of the action lock technique are referred to as "alternate exits" and "chaining" in Jopsy's excellent Doors tutorial. Now that I think about it, alternate exits (or alternate actions) seems to be the most appropriate name for what I've been calling the action lock technique. I would be interested in hearing other common terminology used by DragonMUD builders. [edit: I'm now refining and redefining my use of technique names and I'm wondering if they should be called patterns instead of techniques - I'll have it done soon (not that I think anyone is actually reading this, but I'm having fun with it)]
  3. Why do I care about giving names to these techniques? Well, it helps me to identify patterns, and also by the time I've studied it enough to give it an appropriate name then I usually understand it pretty well. (the following is incomplete, i'm still thinking about it)
  4. I've run into something that I don't know how best to solve. Sometimes I would like "look action_name" to be the same as typing "action_name". But maybe I'm forcing inappropriate semantics on these constructs? Instead of using the same message for both the desc and succ of an Action, I guess I could put the message as the succ and for the desc use something like: "don't just look at it, think it" - but I really don't like that. I know there should be something in the desc which allows the player to decide that other actions are available - but how do I do that without explicitly telling the player what they are thinking, or what they should do? ~ I'm learning. I think I did ok with this issue in Spring of Memories where I lead the player with looking at nouns to a point where the player uses a verb as a command.
  5. The "look" command is like an "action" the player performs. Can we add Effects to it? I noticed that I can add effects to the room (and to "things"), but it doesn't seem to do anything.
  6. The "[Commands: ...]" section is displayed inside the <PRE> element used for displaying the map. If there are many commands this will cause a horizontal scrollbar in the user's client. This is not a big deal - however, it seems there are times when the closing PRE tag is omitted (for example in a room with no exits). Now nothing will wrap and most all text will use the PRE font. This is easily fixed, just type: "</pre>
  7. From Town Square you can go to the "Wall". But many of the objects there have < and > characters in their names so if you're in html-mode it will screw things up.
  8. I found an appropriate use for the @hint and @warn attributes on the toli ball.
  9. Exits are visible, and in the Pueblo client are displayed as clickable links, but Actions are not. What am I missing? Actually, I usually don't want Actions to be displayed so this may be an intended feature - but I just want to make sure I understand it.
  10. On this page there is a discussion of new features... but they don't seem to have been implemented. Will they be (or are they being) implemented?
  11. I can use @detach and @attach to move an action to another room. But how do you do that with an Exit? @detach and @attach don't seem to work with exits, only Actions. If I want to re-order all actions in a room the only way I know to do that now is to @recyc them then re-create them. Is there a better way?

Programming Constructs

Locks and effects provide you with certain conventional programming constructs. I'm sure I have not discovered them all, but the following are a few I have noticed.

"if" Construct

An action's Lock and its effects provide an if construct.

// Basic Action

if (action.lock)
  show action.succ
  show action.osucc
  eval action.effect[1]
  eval action.effect[n]
  if (action.isExit)
    goto exit.destination
  show action.fail
  show action.ofail

"if else if" Chain Construct

Multiple actions with the same first name provide an if else if construct. However, there is an interesting twist to this such that the following pseudo code is not exactly correct. The action actually executed (successful) will be chosen at random from all the actions whose locks eval to true [some wiz please tell me if i'm right or wrong about this]. If all the actions' locks eval to false then only the last action's fail and ofail messages will be displayed. So... I don't really know yet how to show all this with simple pseudocode.

// Alternate Actions

if (action[1].lock)
  // same as above
else if (action[n].lock)
  // same as above
  show action[n].fail
  show action[n].ofail

"if" Sequence Construct

Lock's on groups provide a sequence of if constructs.

// Group Filters on an Action's Effects

if (action.lock)
  show action.succ
  show action.osucc
  for (i = 1; i < action.effect.length; ++i)
    if (action.effect[i].group.filter_lock)
      if (action.effect[i].op == 'ADD')
        add action.effect[i].group : action.effect.target
        show action.effect[i].group.succ
      else if (action.effect[i].op == 'REM')
        remove action.effect[i].group : action.effect.target
        show action.effect[i].group.fail
      // does anything happen here?
  if (action.isExit)
    goto exit.destination
  show action.fail
  show action.ofail

DragonMUD Code

Here are some DragonMUD toys that I've built:

Call for Help in Cliff Bottom

This implements the CAA pattern. It requires the player to call for help three times. On the third call the player receives help.

@action call for help;call help;call;help;call0=here
@action call for help;call help;call;help;call1=here
@action call for help;call help;call;help;call2=here
@set call0=sticky,dark
@set call1=sticky,dark
@set call2=dark
@lock call0 = !+nightmode & +talisa.brokenleg & !call0
@lock call1 = !+nightmode & +talisa.brokenleg & !call1 & call0
@lock call2 = !+nightmode & +talisa.brokenleg & call1
@succ call2 = Talisa hears you and climbs down the cliff to help you. She cleans your wounds, gives you water and then becomes very still and silent for a long time. Your pain stops and you fall asleep. When you awake Talisa is gone and...
@fail call2 = It seems that Talisa is not on the slope now.
@eff call2 = rem +talisa.brokenleg
@eff call2 = add +talisa.friend
@eff call2 = rem call0
@eff call2 = rem call1

Listen to Menawa in Camp of the Red Sticks

I tried this with both the CAA and CGF patterns. I settled on using CAA. It provides chained/sequential messages. Each time the player "listens" they hear the next message until all have been heard, then the process repeats.

" 'listen to Menawa' using the CAA technique

@action listen to menawa;listen menawa;listen;ltm;lm;lm0=here
@action listen to menawa;listen menawa;listen;ltm;lm;lm1=here
@action listen to menawa;listen menawa;listen;ltm;lm;lm2=here
@action listen to menawa;listen menawa;listen;ltm;lm;lm3=here
@action listen to menawa;listen menawa;listen;ltm;lm;lm4=here
@set lm0=sticky,dark
@set lm1=sticky,dark
@set lm2=sticky,dark
@set lm3=sticky,dark
@set lm4=dark
@lock lm0 = +nightmode & !lm0
@lock lm1 = +nightmode & !lm1 & lm0
@lock lm2 = +nightmode & !lm2 & lm1 & lm0
@lock lm3 = +nightmode & !lm3 & lm2 & lm1 & lm0
@lock lm4 = +nightmode & lm3
@succ lm0 = We are on...
@succ lm1 = The mount...
@succ lm2 = The white...
@succ lm3 = In these ...
@succ lm4 = There is ...
@fail lm4 = The dayti...
@eff lm4 = rem lm0
@eff lm4 = rem lm1
@eff lm4 = rem lm2
@eff lm4 = rem lm3
@eff lm4 = add +menawa.listener

" 'listen to Menawa' using the CGF technique

@makegroup menawa.msg1
@set menawa.msg1 = !tattle,dark
@makegroup menawa.msg2
@set menawa.msg2 = !tattle,dark
@makegroup menawa.msg3
@set menawa.msg3 = !tattle,dark
@makegroup menawa.msg4
@set menawa.msg4 = !tattle,dark
@makegroup menawa.msgend
@set menawa.msgend = !tattle,dark

@succ +menawa.msg1 = We are the last of the ...
@succ +menawa.msg2 = Our enemies have set tr...
@succ +menawa.msg3 = We are on the southern ...
@succ +menawa.msg4 = There is a spring to th...
@succ +menawa.msgend = There is an extra bed...
@fail +menawa.msgend = Again?  Very well...

@lock +menawa.msg1 = me ; #0 ; menawa.msgend | !+menawa.msg1
@lock +menawa.msg2 = me ; #0 ; menawa.msgend | (+menawa.msg1 & !+menawa.msg2)
@lock +menawa.msg3 = me ; #0 ; menawa.msgend | (+menawa.msg1 & +menawa.msg2 & !+menawa.msg3)
@lock +menawa.msg4 = me ; #0 ; +menawa.msgend | (+menawa.msg1 & +menawa.msg2 & +menawa.msg3 & !+menawa.msg4)
@lock +menawa.msgend = me;#0 ; +menawa.msgend | (+menawa.msg1 & +menawa.msg2 & +menawa.msg3 & +menawa.msg4)

@action listen to menawa;listen menawa;ltm;lm = here
@lock lm = +nightmode
@fail lm = menawa is not here now.
@succ lm = You listen closely to menawa...
@eff lm = toggle +menawa.msgend
@eff lm = toggle +menawa.msg4
@eff lm = toggle +menawa.msg3
@eff lm = toggle +menawa.msg2
@eff lm = toggle +menawa.msg1

Toli Ball

This ball can be thrown back and forth between two rooms. In this case the rooms are Camp and Clearing. You need two players to see all the effects.

" While in Clearing create the ball and an action to throw it up to the Camp:

@create toli ball
@set toli ball = copy
@lock toli ball = ! toli ball ; ! toli ball
@desc toli ball = A ball used in kapucha toli ("ball play") - the little brother to war.
@hint toli ball = you need a ball to throw
@warn toli ball = drop the ball
@link toli ball = here

@action throw the ball;throw ball;throw;tbnw = here
@set tbnw = dark
@lock tbnw = toli ball
@fail tbnw = Throw what?
@succ tbnw = You throw the ball up to the camp.
@ofail tbnw = pretends to throw a ball.
@osucc tbnw = throws the ball up to the camp.
@eff tbnw = rem toli ball
@eff tbnw = rem toli ball : here
" #37766 is Camp
@eff tbnw = add toli ball : #37766
@eff tbnw = notify #37766.

" While in Camp create an action to throw the ball down the slope:

@action throw the ball;throw ball;throw;tbse = here
@set tbse = dark
@lock tbse = toli ball
@fail tbse = Throw what?
@succ tbse = You throw the ball down the slope.
@ofail tbse = pretends to throw a ball.
@osucc tbse = throws the ball down the slope.
@eff tbse = rem toli ball
@eff tbse = rem toli ball : here
" #37967 is Clearing
@eff tbse = add toli ball : #37967
@eff tbse = notify #37967

Listen to Talisa in Clearing

This implements the MEAA pattern. A specific message is displayed only when a specific condition is true. It does not provide chained (sequential) messages.

@action listen to Talisa;listen talisa;listen;ltt;lt;lt0 = here
@set lt0 = dark
@lock lt0 = +snake.bite1
@succ lt0 = You must act ...

@action listen to Talisa;listen talisa;listen;ltt;lt;lt1 = here
@set lt1 = dark
@lock lt1 = +talisa.friend & !+snake.bite1
@succ lt1 = Have you seen ...

@action listen to Talisa;listen talisa;listen;ltt;lt;lt2 = here
@set lt2 = dark
@lock lt2 = !+snake.bite1 & !+talisa.friend
@succ lt2 = You should take ...

Remember in Spring of Memories

This is a combination of two patterns I've been playing with: CAA+GF. It gives the player "memories" by looking at the player's group memberships. It provides the memories in three sets of three. The display of the sets is chained, and group filters are used to conditionally display the individual memories.

" Remember in Spring of Memories

@makegroup spring.mem0
@set spring.mem0 = !tattle,dark
@makegroup spring.mem1
@set spring.mem1 = !tattle,dark
@makegroup spring.mem2
@set spring.mem2 = !tattle,dark
@makegroup spring.mem3
@set spring.mem3 = !tattle,dark
@makegroup spring.mem4
@set spring.mem4 = !tattle,dark
@makegroup spring.mem5
@set spring.mem5 = !tattle,dark
@makegroup spring.mem6
@set spring.mem6 = !tattle,dark
@makegroup spring.mem7
@set spring.mem7 = !tattle,dark
@makegroup spring.mem8
@set spring.mem8 = !tattle,dark

" Group Succ
@succ +spring.mem0 = ...climbing trees
@succ +spring.mem1 = ...easy money
@succ +spring.mem2 = ...the depths of chaos
@succ +spring.mem3 = ...a deep mud
@succ +spring.mem4 = ...travel to the stars
@succ +spring.mem5 = ...toad death
@succ +spring.mem6 = ...understanding
@succ +spring.mem7 = ...loving sex
@succ +spring.mem8 = ...inner conflict

" Group Locks
@lock +spring.mem0 = me ; #0 ; +In Robore Virtus
@lock +spring.mem1 = me ; #0 ; +Thief
@lock +spring.mem2 = me ; #0 ; +Chaos Scholar
@lock +spring.mem3 = me ; #0 ; +Muddy! & +DeepVisitors
@lock +spring.mem4 = me ; #0 ; +Stargazers
@lock +spring.mem5 = me ; #0 ; +Toaded & +Stone Cold Dead
@lock +spring.mem6 = me ; #0 ; +Philosopher
@lock +spring.mem7 = me ; #0 ; +Sex Slave
@lock +spring.mem8 = me ; #0 ; +Chaos Scholar & +Bound to Order

" Action r0
@action remember;r0 = here
@set r0 = dark,sticky
@lock r0 = !r0
@succ r0 = You ride the first of three ripples, and you remember...
@osucc r0 = is in a trance.
@eff r0 = add +spring.mem0
@eff r0 = add +spring.mem1
@eff r0 = add +spring.mem2
@eff r0 = rem +spring.mem0
@eff r0 = rem +spring.mem1
@eff r0 = rem +spring.mem2

" Action r1
@action remember;r1 = here
@set r1 = dark,sticky
@lock r1 = !r1 & r0
@succ r1 = Up the second ripple, and you remember...
@osucc r1 = is in a deep trance.
@eff r1 = add +spring.mem3
@eff r1 = add +spring.mem4
@eff r1 = add +spring.mem5
@eff r1 = rem +spring.mem3
@eff r1 = rem +spring.mem4
@eff r1 = rem +spring.mem5

" Action r2
@action remember;r2 = here
@set r2 = dark
@lock r2 = r1
@succ r2 = Over the crest of the third ripple, and you remember...
@osucc r2 = is one with the water.
@eff r2 = add +spring.mem6
@eff r2 = add +spring.mem7
@eff r2 = add +spring.mem8
@eff r2 = rem +spring.mem6
@eff r2 = rem +spring.mem7
@eff r2 = rem +spring.mem8
@eff r2 = rem r0
@eff r2 = rem r1

The structure above has the potential for interesting applications. Instead of chaining the actions, they could be mutually exclusive, or random, or a combination of the two. The group filters could be chained or could be mutually exclusive in some other way.