- Summary
The zMUD scripting language (zScript) is a Text Processing Language.
This makes it quite different from computer languages such as C or Basic that
people might be familiar with. Although the original language syntax came
from the original TinTin MUD client for Unix (for compatibility purposes),
zScript has closer ties to text manipulation languages such as perl.
Because zMUD is designed for efficient text processing, all variables in zMUD
are stored in text format. While this decreases performance for
mathematical calculations, if provides a great deal of flexibility. But
it's important to remember that even when we talk about variable
"Types", all values are stored internally as strings (with the
exception of arrays).
Although zMUD stores variables in text format, there are several
"types" of variables that can be used in scripting:
- String: "text" is an explicit string value.
- Integer: 123 is an integer. -2 is an integer.
- Floating Point: Single precision is supported. 1.23 is a floating point
value.
- String List: a string that contains multiple values. a|b|c is a string list.
- Record: a string that contains keys and values. Like a string list,
but each element of the list has a name (key).
- Arrays: formal COM-compatible array types. Indexed by an integer
starting at zero. Each element can contain a string, integer, or
floating point value.
- COM Objects: Variable contains a reference to a COM object.
- MXP Variables: Entities set by the MUD server.
In the next sections, examples of using each variable type will be given.
Strings are the core of the zMUD scripting language. To force a value
to be interpreted as a string, enclose the value in double-quotes:
"text", or in braces: {text}. The difference between these two
syntaxes is that other variables are expanded when you use the {}. For
example:
VarName = "@abc"
stores the raw text "@abc" into the variable called VarName.
Compare this to the example:
VarName = {@abc}
Without the quotes the variable named "abc" is expanded, and the
value of the "@abc" variable is stored in VarName. The above
example could also be written as:
VarName = @abc
Since there are no spaces in this expression, the {} are not actually needed.
To force a value to be interpreted as a string, you can also use the %string
function. For example, the + operator performs a numeric addition, if the
arguments are numbers, or performs a string concatenation if the arguments are
strings. So: 1+2 has a value of 3, but "1"+"2" has a
value of "12". Using the %string function, you can do:
%string(1+2)+"4" which would have a value of "34" since 1+2
becomes 3, which is then converted to the "3" string by the %string
function.
Sometimes, the trickiest part of scripting in zMUD is determining what
happens to the quotes around strings. In many cases, quotes are
stripped. For example in the above VarName="@abc" example, if
you then check the actual value of @VarName you will see that it contains @abc
without the quotes. So, the next time you use @VarName in a script, the @abc
variable reference will get expanded since it's no longer within quotes.
Usually the scripting language will do what you want by default. For
more information on zMUD parsing modes and how to better control how strings are
expanded or evaluated, see the "zMUD Programming
Language" article in the Support Library.
Integers are numbers without any decimal place, with an optional minus sign
in front. Whenever zMUD performs mathematical operations, if there are not
quotes around a value, zMUD checks to see if the value can be converted to a
number. Some operations depend upon whether the arguments are numbers or
strings. In the previous section, we examined the difference between
numeric and string + operations.
zMUD integer variables are converted from string format to 32-bit integer
format for math operations.
Division with integer variables produces an integer value. The Division
is truncated (the value after the decimal point is discarded). So, 5/2 = 2
(since 5 divided by 2 is 2.5, the .5 is discarded, giving an integer result of
just 2).
New to zMUD version 6.20 is floating point variables. Now, numbers with
decimal places can be manipulated. zMUD supports Single-Precision floating
point, which has an accuracy of approximately 7 decimal digits.
A floating point value *must* have a decimal point. For example, 2 is
an integer, but 2.0 is a floating point value. The %float function can be
used to convert a string or integer into a floating point number. It
basically just adds the ".0" to the end of an integer.
Division with floating point variables produces a floating point value.
For example, 5.0/2.0=2.5. Only one of the values needs to be floating
point. Once any floating point value is detected in a calculation, all
other values are automatically converted to floating point. So, 5.0/2 and
5/2.0 would also give a value of 2.5. However, remember that 5/2 is an
integer-only operation, with an integer value of 2. So, if you aren't sure
if a value is already floating point, use the %float function. For example
%float(@a)/%float(@b) divides the variable @a by the variable @b, but ensures
that the result is a floating point value. So, even if @a=5 and @b=2 are
both integers, the result will still be the floating point 2.5 value.
Because of the way floating point values are stored within computers, values
that should be equal sometimes are not. For example, in format
mathematics, 1.0/3.0 is the same as (4.0/3.0-1.0). However, in zMUD you
will find that 1.0/3.0 is 0.333333343267441 and (4.0/3.0-1.0) is 0.333333373069763.
Notice that these values start out looking the same, but then differ. This
isn't the fault of zMUD, but is simply a result of how floating point values are
stored on binary computers.
So, given the above problem, if you try to do something like #IF (1.0/3.0 =
(4.0/3.0-1.0)) {...}, you will never get a True result from this, since the
values are actually not equal. To take care of this, zMUD provides the
%norm function to normalize floating point values. In zMUD, %norm(1.0/3.0)
has a value of 0.333332985639572 and %norm(4.0/3.0-1.0) has a value of 0.333332985639572
also. Notice that these values are now the same. In fact, zMUD
automatically calls %norm whenever you use floating point values in an #IF
statement. So, in zMUD, #IF (1.0/3.0 = (4.0/3.0-1.0)) {...} is True as
expected. But if you perform your own operations, it's useful to know
about the %norm function.
String Lists have been used in zMUD for a long time. They provide a
simple mechanism to store multiple values in a single variable.
Originally, a string list was just a list of strings separated by the |
character. In fact, in older versions of zMUD, it was really that trivial.
In zMUD v6.26 and higher, string lists were improved to support nested lists.
For example, in old versions of zMUD, the line:
#ADDITEM List a|b
actually added *two* items to the string list. In zMUD 6.26 and later,
the above statement only adds a single item to the list. This allows zMUD
to support nested lists and other operations. It also fixes problems
previous versions had with list items that already had quotes around them.
In zMUD 6.26, if you really want to merge two lists as you could in the past,
simply contatenate the lists together with the | symbol. For example:
#MATH List @List+"|"+"a|b"
would concat the "a|b" list to the end of the existing list.
Depending upon what operations are used, string lists in zMUD may contain
duplicate entries, or may not. Using the #ADDITEM and #DELITEM commands,
duplicate items in the list are removed. Using the %additem and %delitem
functions, duplicate items in the list are NOT removed. It's important to
remember this distinction when choosing whether to use a command or
function. To manually remove duplicate items in a list, use the %dup
function.
New to zMUD 6.20 and later is the ability to refer to string list elements as
an array. For example, if @List had the value a|b|c,
then @List.1 is "a", @List.2 is "b" and so on. NOTE:
You can only *read* list values using array syntax. If you attempt an
assignment using the syntax "List.1=a" you will actually be creating
an array as described later.
There are *many* zMUD functions that work with lists. Some examples
are:
- %numitems(@List)
- returns the number of items in a list;
- %push(@List,"item")
- pushes a new item onto the beginning of the list (compared to %additem
which adds the item to the end of the list).
- %pop(List)
- returns the first item from the list and removes it from the list.
Notice only the Name of the list variable is given, rather than it's value
(no @ is used).
- %sort(@List)
- returns a sorted list
Starting with version 6.26 you can also nest one list inside of
another. For example:
List1="a|b|c"
List2=""
#ADDITEM List2 @List1
Puts @List1 into the first element of @List2. Using the nested index
syntax, you could query @List2.1.1 to get "a", @List2.1.2 to get
"b", and so on. Nested lists are delimited using
parenthesis. So, the list:
a|(b|c)|d
actually has 3 items. The first item is "a", the second item
is the nested list "b|c" and the third item is "d".
Records are similar to string lists, except that each element in the list
also has a name, called the Key. Although records are stored internally by
zMUD as special string lists, you should not attempt to construct records
directly. You should always use the #ADDKEY command or %addkey function to
add a new key and value item to the record.
Direct key reference can also be used in zMUD, for both retrieving data,
*and* for assigning data. For example:
VarName.Key = Value
is the same as:
#ADDKEY VarName Key Value
and @VarName.Key is the same as %db(@VarName,Key). This direct key
access syntax can make scripts much easier to read.
In zMUD v6.20 and later, record variables were improved, much like string
lists, to fix problems with nested values. Now you can store string lists,
or other record values into record elements. You can also nest the syntax
used to reference elements. For example, if we stored a string list into a
record variable:
Rec.List="a|b|c"
then we could use @Rec.List.1 to access "a", and @Rec.List.2 to
access "b", etc. Just how you'd expect it to work!
In v6.1x, basic support for arrays was added to provide COM programming
compatibility. However, arrays were still limited in their general
usefulness for zMUD scripting. Starting with version 6.20, arrays were
expanded and became powerful enough to use in everyday scripting.
In version 6.20 and later, direct indexing syntax is supported for both
retrieving data, *and* for assigning data. Also, arrays are created as
needed without the need for an explicit %array function call. For example,
the simple statement: Arr.1="abc" creates an array, assigns "abc"
to the first element, and stores the array in the @Arr variable. To
retrieve the element, just use the @Arr.1 syntax, just like with string lists.
Anytime you assign an element to the array, the array will automatically grow
to the size needed to store the item. Be careful with this. For
example, Arr.10000="abc" suddenly creates an array with 10,000
elements in it! Element 10000 has the value "abc", and all of
the other elements from 0 to 9999 would be empty. But the memory needed
for all 10,000 elements is allocated from Windows. To deallocate this
memory, just assign something else to the variable. For example, doing Arr=""
would clear the variable, freeing up all of the memory used for the array.
In v6.20 and higher, array elements can store either strings, integers, or
floating-point values. In the case of arrays, zMUD stores the data in the
native format. Strings are OLE-compatible strings, Integers are 32-bit
values, and floating-point are Single precision values. This maintains the
COM compatibility with zMUD arrays. Note that zMUD does *not* support
nested arrays. In other words, you cannot assign an array to another array
element. You also cannot store COM objects directly into arrays.
Starting in zMUD v6.20, array variables can be stored in the character
settings file, and exported/imported, just like regular variables. In
addition, the Settings Editor can be used to edit arrays just like editing
string lists.
References to COM Objects can be stored in a zMUD variable using the %comcreate
or %comactive function calls. For more information, see the article on COM
Programming in zMUD in the Support Library.
By default, the @ character is used to retrieve the value of a user-defined
variable. For example, @ABC retrieves the value of the variable called
ABC. The % character is used to retrieve the value from internal zMUD
system variables. See the topic "Predefined Variables" in the
zMUD help file for a full list of available system variables. In general,
system variables can be retrieved, but not set. Exceptions are noted in
the help file.
MXP allows the MUD Server to set it's own variables, called ENTITIES.
You can retrieve the value of MXP Entities using the %mud system record
variable. For example, if the MUD uses the command:
<!ENTITY Hp 100>
to create and set an entity called "Hp", you could retrieve this in
zMUD using the syntax %mud.hp. Note that you can only retrieve entity
values. You cannot change them. Also, you cannot query the value of
a "Private" entity.
An mentioned in the MXP specification, the MUD server could also set the
entity using the syntax:
<VAR Hp>100</Var>
In this case, the value 100 is displayed to the user, probably part of the
MUD prompt. This still sets the entity called "Hp" to the value
of 100 and can still be retrieved by the user using %mud.hp.
Now you have an overview of all of the types of variables support by zMUD and
how to use them.