Macros and Stuff in General
---------------------------

	When the player types a command, the following, rather lengthy sequence
occurs:

	1) If the command starts with a " or a :, a suitable call to say or
do, with the remaineer of the line passed as the single parameter, is
generated. Thus, anything whatsoever in a " type say, or : type pose is
said or posed without further mashing. If this case occurs, no other processing
is done. Otherwise we proceed as follows:

	2) If 1) is not the case, the line of text is hacked up into
a sequence of sets of tokens. A token is either a word, or a quoted phrase.
Both " and ' are allowable quotes, and one type of quote may be used inside a
phrase quoted with the other. \ escapes also work. The sets of tokens are
delimited by semicolons. Thus:

foo "bar baz";frob "thing's; and other stuff" bop

	breaks up into sets of tokens:

(foo, bar baz)
(frob, things's; and other stuff, bop)

	In addition, the appearance of a equals sign (not in quoted text)
forces the remainder of the line to be treated as a single token. Variable
substitution also takes place at this stage, see below.

	3) Each set of tokens is examined in turn, and an attempt made to match
the first against a 'command' of some sort. When a matching command (or exit,
or what have you -- see below) is found, it is invoked with the remaining
tokens in the set as an argument list.


How Commands Are Matched
------------------------

	If the first token (referred to hereafter as the 'command') starts
with an @, the @ is stripped off, and the remainder of the token is used to
search the server-internal command tables, and then the system macro table
for a match. In event of a match, the matched command is run, and no more
processing occurs on this set of tokens. In the event of no match, an error
is displayed to the player invoking all this, and again, no further processing
is applied to this set of tokens. (Therefore, any command starting with an 
'@' *will* match either a system command or a system macro, and not any
other macro in the area.)

	Next, the command is matched against the list of exits in the room
where the player responsible for invoking all this is. If a match is found,
a suitable call to 'go' is generated. As always, this completes processing on
this set of tokens.

	If all this has failed so far, the command is matched against macros
(attributes of type cmd) on the player, room and the object the player is
holding, in that order. In 1.12 and above, you can define a compile-time
option to make it search the player's entire inventory, after searching
the thing they are holding. If a matching macro is found, then *all* of the
processing described above, starting from the breaking up into tokens,
is applied to the text of the macro. The tokenizer will, at this point, use the
arguments to command (the remaining tokens in the set) to substitute into the
tokens generated by tokenizing the text of the macro (see below, again).
The first matching macro, if any, is the only one called.

	Note that at this stage, we are running recursively. Macros can
certainly invoke other macros and so forth.

	Finally, if no matching macro has been located, the server internal
command table and then the system macro table are searched for a match.

	
Variable Expansion
------------------

	When a macro is matched, we refer to all the tokens in the set
whose first token matched as the arguments of the macro. As the macro text
itself is tokenized, tokens beginning with dollar signs are replaced according
to the following rules:

$$<text>
	Is turned into $<text>. Note *double* dollar signs.

$n
	where n is a number, is replaced with the nth argument to the macro.
	The 0th argument is the first token of the original token set, i.e.
	was the token matched against the macro name.

$*
	is replaced by a *single* token made up of all the arguments to the
	macro, including the macro name itself (the 0th argument), separated
	by spaces.

$+n
	where n is a number, is replaced by the nth and succeeding arguments
	to the macro, again as a single token separated by spaces.

$#
	is replaced by a number signifying the number of arguments given.

$actor.xxx (or, equivalently, $xxx)
	is replaced with the xxx attribute of the player whose actions
	led to this macro being run.

$me.xxx (or, equivalently, $self.xxx)
	is replaced by the xxx attribute of the object which is actually
	running the macro.

$here.xxx (or, equivalently, $locale.xxx)
	is replaced by the xxx attribute of the location of the object
	which is actually running the macro.

$subv (or $Subv, $objv, $Objv, $posv, $Posv)
	is replaced by the subv (or etc) attribute of the player. If
	the player has no such attribute, defaults are used (it/it/its
	and captilized varieties).

	In all above cases, the text following a dollar sign may, optionally, 
be enclosed in { and }, to provide useful blocking. I.E. $me.nam and ${me.nam}
are equivalent. This allows an expansion to be concatenated with the 
surrounding text. Variable substituition is done inside strings quoted with ", 
but NOT inside strings quoted with '.  This allows variable evaluation within
a macro to be defered.

${@thing}
	is replaced with the object id of the matched thing (or nothing
	if no match can be made. Exact matches are taken first, then the
	first partial match is taken). Numeric values are permitted.
	For example: ${@Mol.nam} will match anything in the room that
	matches "Mol", and will return its name. ${@4@MyMUD.name} will
	return the name of the object 4@MyMUD, assuming such an object
	exists in the database.

${!number}
	is replaced with the object id of the matched parameter number (or
	nothing if no match can be made. As always, exact matches are
	preferred, but first partial match will be taken if there is no
	exact match). The numeric value must be within provided 
	parameter count. For example: ${!1.nam} will return the name of the
	object matching $1. If there is an object in the room named
		the large stripy cat
	and there is a command on the player
		cmd pet=@do pets ${!1.nam}.
	which is invoked as 
		pet stripy
	the following occurs:
		So-and-so pets the large stripy cat.

	Chaining of attributes is performed as follows:
Owners (and wizards) can always see all attributes, regardless of the
objects location. The attribute "name" is defined as a PUBLIC attribute,
meaning anyone can get it, regardless of ownership, and regardless of
location. The attributes "description", "text", "subv", "Subv", "objv",
"Objv", "posv", and "Posv" are defined as LOCAL_PUBLIC, meaning anyone
can get those attributes, regardless of ownership, IF the object is in
the same room as the player. All other attributes default to PRIVATE,
meaning only the owner can get them, regardless of location. However, 
any attributes with "+" as the first character in their name are defined
as LOCAL_PUBLIC. 
	As long as an attribute continues to resolve to a valid and
reasonable object, the attribute names are looked up iteratively. For
example:
	_echo ${me.loc.nam}
will first grab "me" (which resolves to an object id), and then look
up the location (which is also an object id), and then will return the
name of that. Similarly:
	_echo ${@45@MyMUD.loc.nam}
will return the name of the location of the object 45@MyMUD, assuming
the player does own that object. It is not necessary for the player to
be able to own the location of 45@MyMUD, because it is returning the
name attribute, which is defined as PUBLIC.
	It is also now possible to get non-strings returned (as strings).
For instance, $here.con will return a list of object ids that are in the
room's contents (assuming the player owns the room). 
	

Examples
--------

	A simple macro:

cmd bonk=@do "BONKs $1"

	If this is an attribute of your player object, typing 'bonk foo'
is entirely equivalent to typing '@do "BONKs foo"'. In detail, 'bonk foo'
tokenizes to

(bonk, foo)

	Since 'bonk' matches the attribute, the macro text is tokenized in to

(@do, "BONKS foo")

	which is the same token set you'd get by typing '@do "BONKs foo"'.

---

	Another simple (and popular) macro:

cmd say=@do "purrs, \"$+1\""

	Now, typing 'say hello, there' tokenizes out nicely to

(@do, "purrs, \"hello, there\"")

	which comes out as

so-and-so purrs, "hello, there"

	Notice the quotes. They had to be escaped in the macro; otherwise
they would have been stripped.  Using '"' instead of 'say' will also 
trigger the 'say' macro.

---

(thanks to Tarrant for inspiring this)

	Suppose you wish to alias 'look' to 'study' with a macro. You want to
be able to use both 'study' and 'study <thing>' to look at the room, or at a
thing. The naive approach is to attach an attribute to yourself:

cmd study=@look $1

	Then typing

study foo

	will work fine, generating a token set (study, foo) which matches the
attribute. Running the macro through the tokenizer will give you (@look, foo)
which will do the right thing. Alas:

study

	will NOT work. This will tokenize to (study), which will match the
macro. Tokenizing the macro, and substituting for the $1 will give
(@look,""). The look command will cheerfully try to match the empty 2nd token
against things here and there, and not find anything. You will NOT see the
room, in particular.

	To make it work right, you get to do this:

cmd study=@set me cmd xxxstudy "look $1";xxxstudy;@unset me xxxstudy

	Now. What happens when you type 'study foo'? First you get the token
list (study, foo). This matches the macro above, and expands into token sets:

(@set, me, cmd, xxxstudy, "look foo")
(xxxstudy)
(@unset, me, xxxstudy)

	The first is run, and generates a NEW attribute on you:

cmd xxxstudy=study foo

	Then the 2nd is run, simply running this new macro, and the 3rd set
tidies up.

	If you type 'study', this happens. The token list (study) is matched
against the study macro, which expands:

(@set, me, cmd, xxxstudy, "look ")
(xxxstudy)
(@unset, me, xxxstudy)

	Which makes a macro

cmd xxxstudy=look

	runs it, and tidies up.

---

For more macro examples for neat building tricks, see the files "ferret.unter"
and "Macro.tricks" (the latter for lots of dirty macro tricks).