This document describes the zMUD
programming language. I am using this to document the new zMUD
parser and prepare for writing the chapter on programming for the
zMUD book. It will also be a reference for any future changes to
the language parser. I want this document to be a complete
reference of syntax, so if I miss something, please send email to zugg@zuggsoft.com
This is for zMUD versions 4.42 and
higher
Last updated:
Overview
There are three modes within zMUD:
- Verbatim mode
- Parse mode
- Script mode
- Trigger pattern mode
Modes 1 and 2 are accessible from the zMUD
command line. Mode 3 is only accessible within a script or
running command. When you enter a command into the zMUD command
line, it is parsed in mode (1) if the Parse setting is turned off
(as indicated by the computer icon to the left of the command
line), and is parsed in mode (2) if the Parse setting is turned
on. Commands executed by reading a script file with the #READ
command, or the commands associated with executing a trigger or
alias all run in mode (3)
In Mode (1), all text is sent to the MUD
without any change or other interpretation. This is called
Verbatim mode.
In Mode (2), the text is parsed as a series
of commands separated by the command separator character
(defaults to ;). Each command consists of the command name
as the first word, preceeded by the command character (defaults
to #). Command separators used within quotes (""
or '') or brackets ([] <> or {}) are ignored in breaking up
the individual commands. For example
#SAY {a;b}
is a single command, where as
#SAY a;b
is two commands
Mode (3) is very similar to mode (2), with
one difference. Before the text is sent to the MUD, any variable
references within the text are expanded.
Mode (4) is used by zMUD when parsing
trigger patterns. The syntax for trigger patterns is different
than normal zMUD commands. In particular, trigger patterns use []
for set matching, while the normal parser uses [] to force
evaluation. Within trigger patterns, only variables beginning
with the variable character (@) are expanded.
While modeless systems are preferred, there
are strong reasons for having these three modes within zMUD.
Obviously, the Verbatim Mode (1) is very important for MUD users,
especially coders and builders, that need their commands to go to
the MUD exactly as typed. The reasons for modes 2 and 3 is that
normally, the MUD user is sending text to the MUD and does not
want it to be processed. However, these users want access to zMUD
commands. In script processing, you want to ensure that variables
and functions are properly expanded. As an example for the
difference, consider the line
chat my email address is zugg@zuggsoft.com
When a user types this line, they probably
do not want the @zuggsoft expanded as a variable...they
want it to go to the MUD verbatim. Also, when they type:
#ALIAS drink {drink @container}
They do not want @container expanded
immediately when the line is typed, they want it expanded when
the drink alias is executed. However, in a script or
trigger, the command
drink @container
is expected to be expanded immediately.
Expansion vs
Evaluation
There are two very important concepts to
understand and distinguish in programming zMUD: expansion
and evaluation.
Expansion means parsing the text and
looking for references to built-in (%name) or user-defined
(@name) variables and functions. The default % and @
variable/function expansion characters are ignored within quotes
("" and ''). Normally, a variable reference starts with
an expansion character (% or @), followed by the
name of the variable, followed by a space or other
non-alphanumeric character. A special syntax of @{name}
(or %{name}) can be used in which the closing } delimits
the end of the variable name. This allows other alphanumeric text
to be appended to a variable reference without disturbing the
name of the variable. For example, if @test contains the
string abc, then
@{test}def
expands to abcdef. If @testdef
was used, a variable named testdef would be expanded
instead.
After the name of a variable, an optional
parameter list enclosed in parentheses can be given to specify
parameters for a built-in or user-defined function. For example
@test(a,b,c)
expands the test function, with a
assigned to parameter 1 (%1), b assigned to
parameter 2 (%2), etc.
When expanding variables, expansion
proceeds recursively. That is, after expanding the contents of a
variable, the contents are itself expanded. Thus, if variable @a
contained the value abc, and @b contained @a 123
and @c contained xyz @b @a, the following happens
when @c is expanded within a string:
First, @c is expanded to xyz @b
@a
Next, the above result is recuresively
expanded...@b is expanded to @a 123 and @a
is expanded to abc, resulting in xyz @a 123 abc
Next, recursive expansion is performed
again, resulting in xyz abc 123 abc
Expansion can be delayed by adding
additional @ or % characters. In the above example,
changing the value of @b to @@a 123 would result in
xyz @a 123 abc when @c is expanded.
In variable evaluation, expansion is
performed, but the results are then evaluated as mathematical
expressions. Mathematical expressions use operations such as +
- * / > < =, etc to form numeric, string, or boolean
expressions. An example of where evaluation is used is in the
test expression for the #IF command
#IF (expression) {true-commands} {false-commands}
When a variable or function is encountered
within an expression, it is recursively expanded as in the
expansion section above, but then it is also evaluated. As an
example, if @a contains 1+1 and the expression (@a*10)
is evaluated, first @a is expanded to 1+1, then it
is evaluated as a mathematical expression, resulting in the value
of 2, which results in an expression of (2*10)
which finally evaluates to 20.
To properly program zMUD, it is crucial to
understand whether a statement will be evaluated, or merely
expanded. If @a has the value of 100, and @b
has the value of 20, expansion of @a/@b
results in 100/20, while evaluation of @a/@b
results in 5. If you want the evaluation to produce the
same output as the expansion, you would have to form it into a
proper expression, such as %concat(@a,"/",@b)
To determine whether a parameter for a
particular command is expanded or evaluated, open the Command or
Function Wizards within zMUD. For each command or built-in
function, each parameter is described, and labelled with a type
(such as string, number, expression, etc). Parameters of type Expression,
or FileNumber are evaluated. Parameters of type String,
and Color are fully expanded. Parameters of type Name,
Filename, WindowName, and TriggerClass are
expanded one level (non-recursive expansion).
zMUD also has a syntax to force expansion,
evaluation, or nothing at all. For verbatim text, enclose it in
quotes (""). This prevents any expansion or evaluation.
For expansion, enclose the text in angle brackets <>. For
evaluation, enclose the text in square brackets []. In all of
these cases, the delimiters are removed after the expansion or
evaluation. In Mode 3, quotes are also removed, but they are not
removed in Mode 2 unless they enclose the entire command. Thus,
if @a is 100 and @b is 5, here are
some examples:
"The answer is @a/@b"
sends the text The answer is @a/@b
to the MUD in both mode 2 and 3 since quotes around the entire
string are always stripped.
The answer is "@a/@b"
sends the text The answer is @a/@b
to the MUD when in Script mode (mode 3), but sends The answer
is "@a/@b" when in mode 2.
The answer is <@a/@b>
sends the text The answer is 100/5
to the MUD in both mode 2 and 3.
The answer is [@a/@b]
sends the text The answer is 20 to
the MUD in both mode 2 and 3.
In mode 2, to avoid expanding or evaluating
with <> and [], just escape the initial brace or bracket.
For example
The answer is ~[@a/@b]
sends the text The answer is [@a/@b]
to the MUD. You can escape the closing brace/bracket if you like,
but it is not needed. Notes that curly braces {} have no parsing
meaning and are just used to group values into single parameters.
When in mode 3 (script), the final command sent to the MUD is
always expanded. Thus, the above example would send The answer
is [100/5] to the MUD in mode 3.
Normally, single quotes ' work like double
quotes ". However, single quotes are not normally stripped
like the other delimiters. You can make ' and " identical by
turning on the Strip ' quote option in the
General Preferences.
Variables and
Functions
Let's look at some examples of expanding
and evaluation using the #VAR command as an example. There
has been much confusion regarding the #VAR command in
various versions of zMUD, so this section should clarify how #VAR
is used.
In the Command Wizard, you will notice that
#VAR takes three parameters. The first is the name of the
variable and is a name type. The second is the value for the
variable, and is also a name. The third is the default value for
the variable to have when the setting file is initially loaded,
and is also a name. The third parameter is optional.
Since all three of the parameters are
names, they are all expanded. Thus, if @a has the value of
100, then
#VAR b @a
assigns the value of 100 to b
since @a is expanded. If @x has the value of y,
then
#VAR @x @a
assigns the value of 100 to y,
since @x expands to y and @a expands to 100.
Using the force operations, we can do the
following. If @a has the value of 100 and @b
has the value of 5, then
#VAR c @a/@b
assigns the string 100/5 to c.
#VAR c [@a/@b]
assigns the value of 20 to c,
and
#VAR c "@a/@b"
assigns the string @a/@b to c.
Finally,
#VAR c <@a/@b>
does the same as the first case with no
delimiters, since #VAR expands the second parameter anyway
(because it has a type of name).
To avoid using the force operators shown
above, additional commands were added to zMUD. The #MATH
command is equivalent to the #VAR command using the []
syntax. Thus #MATH c @a/@b assigns 20 to c.
The #FUNCTION command is equivalent to the #VAR
command using the "" syntax. Thus
#FUNC c @a/@b
assigns @a/@b to c.
Using these different commands or
operations can produce different results, so it is very important
to keep track of what you are doing. Some very powerful
operations are possible with this syntax. Consider the following
example to contrast these commands:
As an example, let's keep track of
hitpoints on the status line using the #STATUS hp: @hp
command. If we do
#VAR hp 100
then hp: 100 is displayed on the
status line. If @a is 100 and @b is 5,
then
#VAR hp @a/@b
displays hp: 100/5 on the command
line. If we now change the value of b to 10, the
status line continues to display 100/5 because the value
of hp is still 100/5. However, if we now do
#FUNC hp @a/@b (or #VAR hp "@a/@b")
then the status line displays hp: 100/10
and if we change @b back to 5, then the status line
automatically updates to hp: 100/5. This is because hp
has the value @a/@b so each time @b changes, this
function results in a different expansion. Finally, if we say
#MATH hp @a/@b (or #VAR hp [@a/@b])
then the status line shows hp: 20
and changing @b does not change the status line since hp
now has the fixed value of 20.
Keep in mind that when using the force
operations, the delimiters ([] <> or "") are
stripped from the parameter. Thus,
#VAR hp "@a/@b"
assigns @a/@b to hp. Since
the #FUNC operation does not require the force delimiters,
#FUNC hp @a/@b
also assigns @a/@b to hp. If
you do
#FUNC hp "@a/@b"
then "@a/@b" is assigned
to hp. If you then expand @hp, it will always
evaluate to @a/@b and the @a and @b will not
be expanded because of the extra set of quotes. In the above
example, #FUNC hp "@a/@b" will display hp:
@a/@b on the status line, and it will not change when @a
or @b are changed. This is the same as doing
#VAR hp ""@a/@b""
Single quotes are not normally stripped,
unless the Strip ' quote option in the General
Preferences is turned on.
Another thing to keep in mind is the number
of parameters taken by the #VAR command, vs the #MATH
and #FUNC commands. #VAR takes 3 parameters, and
the third optional parameter is the default value of the
variable, while #MATH and #FUNC only take two
parameters (the name of the variable and the value). Thus, if you
say
#VAR a one two
then one is assigned to a, not one
two. What you really wanted was probably
#VAR a {one two}
The {} do not change how something is
parsed, but can be used just to group the parameters together.
Since #FUNC only takes 2 parameters, saying
#FUNC a one two
properly stores one two into @a.
For clarity, you can still use the braces to group:
#FUNC a {one two}
You should generally not use the
"", '', <>, or [] delimiters to group text unless
you are aware of the parse mode that will be caused
Function Calls
A variable that uses parameters (%1, %2,
etc) is called a function in zMUD. Try not to confuse this
with the #FUNCTION command, although you will normally use
the #FUNCTION command to create zMUD functions.
Let's compare the creation of a function
with #VAR and a function with #FUNCTION. Assume @a
has the value of 100
#VAR test {@a %1 %2}
Since #VAR expands its variables,
this results in #VAR test {100 %1 %2}. So, test(1,2)
results in 100 1 2. If we change @a to 50,
then test(1,2) will still evaluate to 100 1 2
because the @a was expanded when the function was defined.
However, if we use #FUNCTION
#FUNC test @a %1 %2
and @a is 100, then test(1,2)
will still return 100 1 2. However, if @a now
changes to 50, test(1,2) will return 50 1 2.
Using the #FUNC command delays variable expansion until the
function is used, rather than when it was defined. Both of these
types of functions will be useful in programming zMUD.
For user-defined functions, each parameter
is expanded before sending it to the function. Thus, if @temp
has the value of 50, then test(@temp,2) would
return 100 50 2. For built-in functions, expansion or
evaluation of the parameter depends upon the type of the
parameter. In the Function Wizard, the type of each parameter is
shown. Parameters of type String, or Color are
fully expanded. Parameters of type Name, FileName, WindowName,
TriggerClass are expanded only one level (non-recursive
expansion). Parameters of type Expression, FileNumber,
and Range are evaluated.
Some functions, such as %min and %max
also display a line at the bottom of the Function Wizard
indicating that the parameter list is Pre Expanded. In
these cases, zMUD first expands the entire parameter list, before
breaking it into individual parameters on the commas. This allows
the following
#VAR a 1,2,3
#VAR b 4,5,6
%min(@a,@b)
will return 1, and
%max(@a,@b)
will return 6. This is because, the
parameter list (@a,@b) is first exanded, resulting in (1,2,3,4,5,6),
and then the %min or %max function is called with
this new parameter list. Using extra parentheses prevents this
operation:
%min((@a),(@b))
expands to
%min((1,2,3),(4,5,6))
which gives a result of 1,2,3.
Aliases
If you look at the #ALIAS command in
the Command Wizard, you will see that the first parameter is the
name of the alias, and is of type name (which means it is
expanded), while the second parameter is the list of commands is
is of type literal instead of command. This means that the
second parameter of the #ALIAS command is not expanded.
So,
#ALIAS dr {drink @container}
assigns drink @container to the
alias dr. When you then use the dr alias later, the
value of @container is expanded when the alias is used.
Again, you can force expansion using the force operation
#ALIAS dr {drink <@container>}
which, if @container has the value
of jug, will assign drink jug to the dr
alias. Now dr will not change when @container
changes.