/
umud/DOC/
umud/DOC/examples/
umud/DOC/internals/
umud/DOC/wizard/
umud/MISC/
umud/MISC/dbchk/
umud/RWHO/rwhod/
	Dirty Tricks
	============

	This document is an effort to describe some useful techniques for
general purpose building. It's a series of very clever or at least cute ideas
thought up mostly by me or Moira. The really smart ideas may be freely
attributed to the latter party, though I like to think I've had an idea or two
worthy of merit. This document is written largely from the perpective of a user
of v1.11. v1.12 allows more powerful contructs, but should not break any of
what follows.

	First off, a word about permissions. Macros are not run as the player,
they are run as the object that the macro is attached to. Therefore, you never
have to worry about a macro somewhere changing your description for you; it
can't, unless it happens to own you (or it has a wizard bit). This also means
that anything the macro does that requires a 'set' or 'teleport' command
will require that the object the macro is on own whatever it is it's trying
to fiddle with. If you have an exit that has a macro as its fail that changes
the room's description, that exit must own the room. If you have a room that
has a macro that teleports an object in, that room must either own the object,
or the object must be linkok. (See the teleport rules). 

	Macros with Arguments
	=====================

	Generally, when you want a 'kick dog' command, you should use an exit
with that name. This also allows several aliases for the command, and so on.
For instance, either:

]str fail=You kick the dog savagely.
]str ofail=kicks the dog savagely.

or:

]cmd fail=@do kicks the dog savagely.

on a locked exit named "kick dog" would work. At times, this is not quite
practical, as in the case of a system macro or macros tied to objects
intended to be used. UnterMud does not, at present, support exits attached
to things, nor exit-style command matching on anything other than exits.
Thus, it is sometimes necessary to resort to the following trick:

]cmd kick=X${1}z
]cmd Xdogz=@do kicks the dog savagely.

	When the user types 'kick <something>', the macro 'kick' is called with
a single argument, '<something>'. This macro runs through the variable
substitutor, and expands to X<something>z. In the case of 'kick dog', this is
Xdogz. The Xdogz macro gets called, and the indicated @do command executed.
In the case of 'kick lizard', well, the command 'Xlizardz' results, and a Huh?
message gets displayed to the user. This cannot really be helped.

	Coding Strings on the Object
	============================

	This is a really simple idea, and really really useful. The problem
here is that often a long complex macro has a bunch of strings hardcoded in it,
and in the absence of good building tools, typos can be hard to correct.
Further, the 512 character limit on commands sent to the server may make it
hard to fit it all in. It is handy, then, to let the variable substitutor do
some of the work for us.

]cmd summon=@tel <object ID> here;@_echo $me.summonstr
]str summonstr=The pot appears in a flash of light!

	The 'summon' macro teleports the specified object (a pot, in this case)
to the user's location, and then _echo's the string found in the 'summonstr'
attribute of whatever the above attributes are hooked to. The variable
substitutor graciously converts '$me.summonstr' into 'The pot appears in a
flash of light!' for us.

	Coding Booleans on the Object
	=============================

	The easiest way to keep track of 'state' in UnterMud is by directly
saving it on some convenient object (the object that needs to know what state
it is in, generally). Again, the variable substitutor gets a workout. Imagine
the following attached to a room which may or may not be, say, partially filled
with water.

]cmd splash=@_if $me.wet "@do splashes around." else "@_echo 'splash?'"
]cmd drain=@_echo "You let the water out";@set me str wet F
]cmd fill=@_echo "You fill the room with water";@set me str wet T
]str wet=T

	The two macros 'drain' and 'fill' change the state of the room. In a
more sophisticated example, they could re-write the room's description and so
forth. Here, they just change the string coded in the 'wet' attribute, and echo
something to the player. The 'splash' macro uses the variable substitutor to
see if the room has water in it or not, and either executes a suitable @do, or
asks the player what it thinks it's doing splashing in a dry room.

	Whatever these attributes are attached to needs to own itself, to be
able to set the 'wet' attribute back and forth.

	Another way to do state changes that isn't quite as pretty to look
at, is to let the macro rewrite itself to the opposite state every time it
is run. For the above example with the water in the room, you could do:

]cmd splash=@do splashes around.
]cmd drain=@_echo "You let the water out";@set $me cmd splash "@_echo 'splash?'"
]cmd fill=@_echo "You fill the room with water";@set $me cmd splash "@do 
 splashes around."

	This way also requires that the room (or whatever) owns itself, so
it can set the 'splash' macro on itself.

	Re-writing Macros
	=================

	Sometimes you want to run some text through the tokenizer/macro
substitutor a couple of times. For example, you might want a 'dance' macro that
references an attribute of the object it is attached to based on the name of
the player calling the macro. Ideally, you'd just do $me.${actor.nam}dance
to reference, say, a 'bobdance' attribute when bob calls the 'dance' macro.
Alas, this will not quite work, since it requires two passes through the
variable substitutor, which Unter does not provide. Thus:

]cmd dance=@set $me cmd Xdnc "@do dances: $$me.${actor.nam}dance";Xdnc
]str bobdance=bob hops around.

	If 'bob' calls the 'dance' macro, it will first set a new macro on the
object it's attached to reading:

]cmd Xdnc=@do dances: $me.bobdance

	and then call said macro, with the obvious results. Alas, this will
break for people with multiple word names: Jerry Cornelius would have, instead:

]cmd Xdnc=@do dances: $me.Jerry Corneliusdance

	which would fail unpleasantly. A better solution is:

]cmd dance=@set $me cmd Xdnc "@do dances: $${me.${actor.nam}dance}";Xdnc

	which would produce Xdnc macros:

]cmd Xdnc=@do dances: ${me.bobdance}
]cmd Xdnc=@do dances: ${me.Jerry Corneliusdance}

	which ought to work correctly. The latter will reference an attribute

]str Jerry Corneliusdance=<stuff>

	which may or may not be legal OIF, but works. Again, the object in
question needs to own itself in order to write these macros on itself.

	Choosing Exits Based on Locks
	=============================

	One of the significant ways UnterMud differs from the TinyMud
derivatives is that it does NOT choose unlocked exits in preference to locked
ones, when selecting randomly between exits with the same name. Luckily, _if
provides a way around this. Indeed, there is a school of thought which
maintains that the Unter method is cleaner and easier to maintain, but we
shan't get into that here. To implement a pair of identical exits named, say,
'w;we;wes;west' which take you either to room A or room B depending on whether
or not you are carrying some key, you make only *one* exit named
'w;we;wes;west', and lock it completely. Make two other, unlocked, exits with
names that are hard (impossible) to guess, say XXXwestone and XXXwesttwo that
go to the two possible destinations. Now set the fail of the 'w;we;wes;west'
exit to be something like this:

]cmd fail=_if <key object ID> "@go XXXwestone" else "@go XXXwesttwo"

	The '@go's are actually superfluous. This takes advantage of the fact
that any 'go' operation is applied to the player, so regardless of what this
fail is attached to the player winds up taking the exit specified. In this
case, if the player is carrying the key, it winds up walking through
XXXwestone, otherwise through XXXwesttwo.

	A similar technique, using _rand instead of _if, can be used to build a
set of equi-probable exits (the usual arrangement on UnterMud is to have the
first exit taken 1/2 the time, the 2nd 1/4, the 3rd 1/8 and so on).

	Action at a Distance
	====================

	The basic technique for getting things done in UnterMud is to re-write
objects on the fly. There is no particular reason to restrict this to objects
nearby -- macros in 'this' room can change state anywhere in the MUD. For
example, a working drawbridge, controlled from a control room, could be built
by making an exit like this:

]str nam=flip switch;switch;flip
]boo lok=F
]cmd fail=_if $me.bridgeup XXXlower else XXXraise
]cmd XXXlower=@_echo $me.lowertext;@set $me str bridgeup F;@set <roomID> desc
	$me.downdesc;@set <exitID> lock T
]cmd XXXraise=@_echo $me.raisetext;@set $me str bridgeup T;@set <roomID> desc
	$me.updesc;@set <exitID> lock F
]str lowertext=You hear the drawbridge creak down.
]str raisetext=Creak! Bridge goes up.
]str updesc=The bridge is up.
]str downdesc=The bridge is down.
]str bridgeup=F

	This exit does a lot of stuff. Depending on the state of the Boolean
coded in the 'bridgeup' attribute, it either raises or lowers the drawbridge.
This consists of re-writing the description of the room to indicate the state
of the bridge, echoing text to tell what the bridge is doing, locking or
unlocking an exit (you can only get through the exit if the bridge is down)
and finally re-writing the 'bridgeup' attribute to the other state.

	Note that this exit must own itself, the room and the exit it needs to
lock/unlock -- luckily if you forget, Unter will give you many fine error
messages :-)

	Have fun.

		bob & Moira