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. 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, if that attribute is a string. $me.xxx (or, equivalently, $self.xxx) is replaced by the xxx attribute of the object which is actually running the macro, if that attribute is a string. $here.xxx (or, equivalently, $locale.xxx) is replaced by the xxx attribute of the location of the player whose actions led to this macro being run, if that attribute is a string. 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. 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 file "ferret.unter".