7189 lines
No EOL
278 KiB
HTML
Vendored
7189 lines
No EOL
278 KiB
HTML
Vendored
<html><head>
|
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
|
<!-- Created by texi2html 1.56k from ProgrammersManual.texinfo on 26 August 1999 -->
|
|
|
|
<title>LambdaMOO Programmer's Manual</title>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>LambdaMOO Programmer's Manual</h1>
|
|
<h2>For LambdaMOO Version 1.8.0p6</h2>
|
|
<h2>March 1997</h2>
|
|
<address>by Pavel Curtis</address>
|
|
<address>aka Haakon</address>
|
|
<address>aka Lambda</address>
|
|
<p>
|
|
</p><p></p><hr><p>
|
|
|
|
|
|
</p><h1><a name="SEC1" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC1">Introduction</a></h1>
|
|
|
|
<p>
|
|
LambdaMOO is a network-accessible, multi-user, programmable, interactive
|
|
system well-suited to the construction of text-based adventure games,
|
|
conferencing systems, and other collaborative software. Its most common use,
|
|
however, is as a multi-participant, low-bandwidth virtual reality, and it is
|
|
with this focus in mind that I describe it here.
|
|
|
|
|
|
</p><p>
|
|
Participants (usually referred to as <em>players</em>) connect to LambdaMOO using
|
|
Telnet or some other, more specialized, <em>client</em> program. Upon
|
|
connection, they are usually presented with a <em>welcome message</em> explaining
|
|
how to either create a new <em>character</em> or connect to an existing one.
|
|
Characters are the embodiment of players in the virtual reality that is
|
|
LambdaMOO.
|
|
|
|
|
|
</p><p>
|
|
Having connected to a character, players then give one-line commands that are
|
|
parsed and interpreted by LambdaMOO as appropriate. Such commands may cause
|
|
changes in the virtual reality, such as the location of a character, or may
|
|
simply report on the current state of that reality, such as the appearance of
|
|
some object.
|
|
|
|
|
|
</p><p>
|
|
The job of interpreting those commands is shared between the two major
|
|
components in the LambdaMOO system: the <em>server</em> and the <em>database</em>.
|
|
The server is a program, written in a standard programming language, that
|
|
manages the network connections, maintains queues of commands and other tasks
|
|
to be executed, controls all access to the database, and executes other
|
|
programs written in the MOO programming language. The database contains
|
|
representations of all the objects in the virtual reality, including the MOO
|
|
programs that the server executes to give those objects their specific
|
|
behaviors.
|
|
|
|
|
|
</p><p>
|
|
Almost every command is parsed by the server into a call on a MOO procedure,
|
|
or <em>verb</em>, that actually does the work. Thus, programming in the MOO
|
|
language is a central part of making non-trivial extensions to the database
|
|
and thus, the virtual reality.
|
|
|
|
|
|
</p><p>
|
|
In the next chapter, I describe the structure and contents of a LambdaMOO
|
|
database. The following chapter gives a complete description of how the
|
|
server performs its primary duty: parsing the commands typed by players.
|
|
Next, I describe the complete syntax and semantics of the MOO programming
|
|
language. Finally, I describe all of the database conventions assumed by the
|
|
server.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<strong>Note:</strong> This manual describes only those aspects of LambdaMOO that are
|
|
entirely independent of the contents of the database. It does not describe,
|
|
for example, the commands or programming interfaces present in the LambdaCore
|
|
database.
|
|
</p></blockquote>
|
|
|
|
|
|
|
|
<h1><a name="SEC2" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC2">The LambdaMOO Database</a></h1>
|
|
|
|
<p>
|
|
In this chapter, I begin by describing in detail the various kinds of data
|
|
that can appear in a LambdaMOO database and that, therefore, MOO programs can
|
|
manipulate. In a few places, I refer to the <em>LambdaCore</em> database. This
|
|
is one particular LambdaMOO database, created every so often by extracting the
|
|
"core" of the current database for the original LambdaMOO.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<strong>Note</strong>: The original LambdaMOO resides on the host
|
|
<code>lambda.parc.xerox.com</code> (the numeric address for which is
|
|
<code>192.216.54.2</code>), on port 8888. Feel free to drop by! A copy of the most
|
|
recent release of the LambdaCore database can be obtained by anonymous FTP from
|
|
host <code>ftp.parc.xerox.com</code> in the directory <code>pub/MOO</code>.
|
|
</p></blockquote>
|
|
|
|
|
|
|
|
<h2><a name="SEC3" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC3">MOO Value Types</a></h2>
|
|
|
|
<p>
|
|
There are only a few kinds of values that MOO programs can manipulate:
|
|
|
|
|
|
|
|
</p><ul>
|
|
<li>
|
|
|
|
integers (in a specific, large range)
|
|
</li><li>
|
|
|
|
real numbers (represented with floating-point numbers)
|
|
</li><li>
|
|
|
|
strings (of characters)
|
|
</li><li>
|
|
|
|
objects (in the virtual reality)
|
|
</li><li>
|
|
|
|
errors (arising during program execution)
|
|
</li><li>
|
|
|
|
lists (of all of the above, including lists)
|
|
</li></ul>
|
|
|
|
<p>
|
|
MOO supports the integers from -2^31 (that is, negative two to the power
|
|
of 31) up to 2^31 - 1 (one less than two to the power of 31); that's
|
|
from -2147483648 to 2147483647, enough for most purposes. In MOO
|
|
programs, integers are written just as you see them here, an optional minus
|
|
sign followed by a non-empty sequence of decimal digits. In particular, you
|
|
may not put commas, periods, or spaces in the middle of large integers, as we
|
|
sometimes do in English and other natural languages (e.g., `2,147,483,647').
|
|
|
|
|
|
</p><p>
|
|
Real numbers in MOO are represented as they are in almost all other programming
|
|
languages, using so-called <em>floating-point</em> numbers. These have certain
|
|
(large) limits on size and precision that make them useful for a wide range of
|
|
applications. Floating-point numbers are written with an optional minus sign
|
|
followed by a non-empty sequence of digits punctuated at some point with a
|
|
decimal point (`.') and/or followed by a scientific-notation marker (the letter
|
|
`E' or `e' followed by an optional sign and one or more digits). Here are some
|
|
examples of floating-point numbers:
|
|
|
|
|
|
|
|
</p><pre>325.0 325. 3.25e2 0.325E3 325.E1 .0325e+4 32500e-2
|
|
</pre>
|
|
|
|
<p>
|
|
All of these examples mean the same number. The third of these, as an example
|
|
of scientific notation, should be read "3.25 times 10 to the power of 2".
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<em>Fine points:</em> The MOO represents floating-point numbers using the local
|
|
meaning of the C-language <code>double</code> type, which is almost always equivalent
|
|
to IEEE 754 double precision floating point. If so, then the smallest positive
|
|
floating-point number is no larger than <code>2.2250738585072014e-308</code> and the
|
|
largest floating-point number is <code>1.7976931348623157e+308</code>.
|
|
|
|
|
|
</p><p>
|
|
IEEE infinities and NaN values are not allowed in MOO. The error
|
|
<code>E_FLOAT</code> is raised whenever an infinity would otherwise be computed;
|
|
<code>E_INVARG</code> is raised whenever a NaN would otherwise arise. The value
|
|
<code>0.0</code> is always returned on underflow.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
Character <em>strings</em> are arbitrarily-long sequences of normal, ASCII
|
|
printing characters. When written as values in a program, strings are
|
|
enclosed in double-quotes, like this:
|
|
|
|
|
|
|
|
</p><pre>"This is a character string."
|
|
</pre>
|
|
|
|
<p>
|
|
To include a double-quote in the string, precede it with a backslash
|
|
(<samp>`\'</samp>), like this:
|
|
|
|
|
|
|
|
</p><pre>"His name was \"Leroy\", but nobody ever called him that."
|
|
</pre>
|
|
|
|
<p>
|
|
Finally, to include a backslash in a string, double it:
|
|
|
|
|
|
|
|
</p><pre>"Some people use backslash ('\\') to mean set difference."
|
|
</pre>
|
|
|
|
<p>
|
|
MOO strings may not include special ASCII characters like carriage-return,
|
|
line-feed, bell, etc. The only non-printing characters allowed are spaces and
|
|
tabs.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<em>Fine point:</em> There is a special kind of string used for representing the
|
|
arbitrary bytes used in general, binary input and output. In a <em>binary
|
|
string</em>, any byte that isn't an ASCII printing character or the space character
|
|
is represented as the three-character substring "~XX", where XX is the
|
|
hexadecimal representation of the byte; the input character `~' is represented
|
|
by the three-character substring "~7E". This special representation is used by
|
|
the functions <code>encode_binary()</code> and <code>decode_binary()</code> and by the
|
|
functions <code>notify()</code> and <code>read()</code> with network connections that are
|
|
in binary mode. See the descriptions of the <code>set_connection_option()</code>,
|
|
<code>encode_binary()</code>, and <code>decode_binary()</code> functions for more details.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
<em>Objects</em> are the backbone of the MOO database and, as such, deserve a
|
|
great deal of discussion; the entire next section is devoted to them. For now,
|
|
let it suffice to say that every object has a number, unique to that object.
|
|
In programs, we write a reference to a particular object by putting a hash mark
|
|
(<samp>`#'</samp>) followed by the number, like this:
|
|
|
|
|
|
|
|
</p><pre>#495
|
|
</pre>
|
|
|
|
<p>
|
|
Object numbers are always integers.
|
|
|
|
|
|
</p><p>
|
|
There are three special object numbers used for a variety of purposes:
|
|
<code>#-1</code>, <code>#-2</code>, and <code>#-3</code>, usually referred to in the
|
|
LambdaCore database as <code>$nothing</code>, <code>$ambiguous_match</code>, and
|
|
<code>$failed_match</code>, respectively.
|
|
|
|
|
|
</p><p>
|
|
<em>Errors</em> are, by far, the least frequently used values in MOO. In the
|
|
normal case, when a program attempts an operation that is erroneous for some
|
|
reason (for example, trying to add a number to a character string), the server
|
|
stops running the program and prints out an error message. However, it is
|
|
possible for a program to stipulate that such errors should not stop execution;
|
|
instead, the server should just let the value of the operation be an error
|
|
value. The program can then test for such a result and take some appropriate
|
|
kind of recovery action. In programs, error values are written as words
|
|
beginning with <samp>`E_'</samp>. The complete list of error values, along with their
|
|
associated messages, is as follows:
|
|
|
|
|
|
|
|
</p><pre>E_NONE No error
|
|
E_TYPE Type mismatch
|
|
E_DIV Division by zero
|
|
E_PERM Permission denied
|
|
E_PROPNF Property not found
|
|
E_VERBNF Verb not found
|
|
E_VARNF Variable not found
|
|
E_INVIND Invalid indirection
|
|
E_RECMOVE Recursive move
|
|
E_MAXREC Too many verb calls
|
|
E_RANGE Range error
|
|
E_ARGS Incorrect number of arguments
|
|
E_NACC Move refused by destination
|
|
E_INVARG Invalid argument
|
|
E_QUOTA Resource limit exceeded
|
|
E_FLOAT Floating-point arithmetic error
|
|
</pre>
|
|
|
|
<p>
|
|
The final kind of value in MOO programs is <em>lists</em>. A list is a sequence
|
|
of arbitrary MOO values, possibly including other lists. In programs,
|
|
lists are written in mathematical set notation with each of the elements
|
|
written out in order, separated by commas, the whole enclosed in curly
|
|
braces (<samp>`{'</samp> and <samp>`}'</samp>). For example, a list of the names of
|
|
the days of the week is written like this:
|
|
|
|
|
|
|
|
</p><pre>{"Sunday", "Monday", "Tuesday", "Wednesday",
|
|
"Thursday", "Friday", "Saturday"}
|
|
</pre>
|
|
|
|
<p>
|
|
Note that it doesn't matter that we put a line-break in the middle of
|
|
the list. This is true in general in MOO: anywhere that a space can go,
|
|
a line-break can go, with the same meaning. The only exception is
|
|
inside character strings, where line-breaks are not allowed.
|
|
|
|
|
|
|
|
|
|
</p><h2><a name="SEC4" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC4">Objects in the MOO Database</a></h2>
|
|
|
|
<p>
|
|
Objects are, in a sense, the whole point of the MOO programming language.
|
|
They are used to represent objects in the virtual reality, like people, rooms,
|
|
exits, and other concrete things. Because of this, MOO makes a bigger deal
|
|
out of creating objects than it does for other kinds of value, like integers.
|
|
|
|
|
|
</p><p>
|
|
Numbers always exist, in a sense; you have only to write them down in order to
|
|
operate on them. With objects, it is different. The object with number
|
|
<samp>`#958'</samp> does not exist just because you write down its number. An
|
|
explicit operation, the <samp>`create()'</samp> function described later, is required
|
|
to bring an object into existence. Symmetrically, once created, objects
|
|
continue to exist until they are explicitly destroyed by the <samp>`recycle()'</samp>
|
|
function (also described later).
|
|
|
|
|
|
</p><p>
|
|
The identifying number associated with an object is unique to that
|
|
object. It was assigned when the object was created and will never be
|
|
reused, even if the object is destroyed. Thus, if we create an object
|
|
and it is assigned the number <samp>`#1076'</samp>, the next object to be
|
|
created will be assigned <samp>`#1077'</samp>, even if <samp>`#1076'</samp> is destroyed
|
|
in the meantime.
|
|
|
|
|
|
</p><p>
|
|
Every object is made up of three kinds of pieces that together define its
|
|
behavior: <em>attributes</em>, <em>properties</em>, and <em>verbs</em>.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC5" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC5">Fundamental Object Attributes</a></h3>
|
|
|
|
<p>
|
|
There are three fundamental <em>attributes</em> to every object:
|
|
|
|
|
|
|
|
</p><ol>
|
|
<li>
|
|
|
|
A flag (either true or false) specifying whether or not the object represents
|
|
a player,
|
|
</li><li>
|
|
|
|
The object that is its <em>parent</em>, and
|
|
</li><li>
|
|
|
|
A list of the objects that are its <em>children</em>; that is, those objects for
|
|
which this object is their parent.
|
|
</li></ol>
|
|
|
|
<p>
|
|
The act of creating a character sets the player attribute of an object and
|
|
only a wizard (using the function <code>set_player_flag()</code>) can change that
|
|
setting. Only characters have the player bit set to 1.
|
|
|
|
|
|
</p><p>
|
|
The parent/child hierarchy is used for classifying objects into general classes
|
|
and then sharing behavior among all members of that class. For example, the
|
|
LambdaCore database contains an object representing a sort of "generic" room.
|
|
All other rooms are <em>descendants</em> (i.e., children or children's children,
|
|
or ...) of that one. The generic room defines those pieces of behavior
|
|
that are common to all rooms; other rooms specialize that behavior for their
|
|
own purposes. The notion of classes and specialization is the very essence of
|
|
what is meant by <em>object-oriented</em> programming. Only the functions
|
|
<code>create()</code>, <code>recycle()</code>, <code>chparent()</code>, and <code>renumber()</code> can
|
|
change the parent and children attributes.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC6" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC6">Properties on Objects</a></h3>
|
|
|
|
<p>
|
|
A <em>property</em> is a named "slot" in an object that can hold an arbitrary
|
|
MOO value. Every object has eight built-in properties whose values are
|
|
constrained to be of particular types. In addition, an object can have any
|
|
number of other properties, none of which have type constraints. The built-in
|
|
properties are as follows:
|
|
|
|
|
|
|
|
</p><pre>name a string, the usual name for this object
|
|
owner an object, the player who controls access to it
|
|
location an object, where the object is in virtual reality
|
|
contents a list of objects, the inverse of <samp>`location'</samp>
|
|
programmer a bit, does the object have programmer rights?
|
|
wizard a bit, does the object have wizard rights?
|
|
r a bit, is the object publicly readable?
|
|
w a bit, is the object publicly writable?
|
|
f a bit, is the object fertile?
|
|
</pre>
|
|
|
|
<p>
|
|
The <samp>`name'</samp> property is used to identify the object in various printed
|
|
messages. It can only be set by a wizard or by the owner of the object. For
|
|
player objects, the <samp>`name'</samp> property can only be set by a wizard; this
|
|
allows the wizards, for example, to check that no two players have the same
|
|
name.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`owner'</samp> identifies the object that has owner rights to this object,
|
|
allowing them, for example, to change the <samp>`name'</samp> property. Only a wizard
|
|
can change the value of this property.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`location'</samp> and <samp>`contents'</samp> properties describe a hierarchy of
|
|
object containment in the virtual reality. Most objects are located
|
|
"inside" some other object and that other object is the value of the
|
|
<samp>`location'</samp> property. The <samp>`contents'</samp> property is a list of those
|
|
objects for which this object is their location. In order to maintain the
|
|
consistency of these properties, only the <code>move()</code> function is able to
|
|
change them.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`wizard'</samp> and <samp>`programmer'</samp> bits are only applicable to
|
|
characters, objects representing players. They control permission to use
|
|
certain facilities in the server. They may only be set by a wizard.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`r'</samp> bit controls whether or not players other than the owner of this
|
|
object can obtain a list of the properties or verbs in the object.
|
|
Symmetrically, the <samp>`w'</samp> bit controls whether or not non-owners can add or
|
|
delete properties and/or verbs on this object. The <samp>`r'</samp> and <samp>`w'</samp> bits
|
|
can only be set by a wizard or by the owner of the object.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`f'</samp> bit specifies whether or not this object is <em>fertile</em>, whether
|
|
or not players other than the owner of this object can create new objects with
|
|
this one as the parent. It also controls whether or not non-owners can use the
|
|
<code>chparent()</code> built-in function to make this object the parent of an
|
|
existing object. The <samp>`f'</samp> bit can only be set by a wizard or by the owner
|
|
of the object.
|
|
|
|
|
|
</p><p>
|
|
All of the built-in properties on any object can, by default, be read by any
|
|
player. It is possible, however, to override this behavior from within the
|
|
database, making any of these properties readable only by wizards. See the
|
|
chapter on server assumptions about the database for details.
|
|
|
|
|
|
</p><p>
|
|
As mentioned above, it is possible, and very useful, for objects to have other
|
|
properties aside from the built-in ones. These can come from two sources.
|
|
|
|
|
|
</p><p>
|
|
First, an object has a property corresponding to every property in its parent
|
|
object. To use the jargon of object-oriented programming, this is a kind of
|
|
<em>inheritance</em>. If some object has a property named <samp>`foo'</samp>, then so
|
|
will all of its children and thus its children's children, and so on.
|
|
|
|
|
|
</p><p>
|
|
Second, an object may have a new property defined only on itself and its
|
|
descendants. For example, an object representing a rock might have properties
|
|
indicating its weight, chemical composition, and/or pointiness, depending upon
|
|
the uses to which the rock was to be put in the virtual reality.
|
|
|
|
|
|
</p><p>
|
|
Every defined property (as opposed to those that are built-in) has an owner
|
|
and a set of permissions for non-owners. The owner of the property can get
|
|
and set the property's value and can change the non-owner permissions. Only a
|
|
wizard can change the owner of a property.
|
|
|
|
|
|
</p><p>
|
|
The initial owner of a property is the player who added it; this is usually,
|
|
but not always, the player who owns the object to which the property was
|
|
added. This is because properties can only be added by the object owner or a
|
|
wizard, unless the object is publicly writable (i.e., its <samp>`w'</samp> property is
|
|
1), which is rare. Thus, the owner of an object may not necessarily be the
|
|
owner of every (or even any) property on that object.
|
|
|
|
|
|
</p><p>
|
|
The permissions on properties are drawn from this set: <samp>`r'</samp> (read),
|
|
<samp>`w'</samp> (write), and <samp>`c'</samp> (change ownership in descendants). Read
|
|
permission lets non-owners get the value of the property and, of course, write
|
|
permission lets them set that value. The <samp>`c'</samp> permission bit is a little
|
|
more complicated.
|
|
|
|
|
|
</p><p>
|
|
Recall that every object has all of the properties that its parent does and
|
|
perhaps some more. Ordinarily, when a child object inherits a property from
|
|
its parent, the owner of the child becomes the owner of that property. This
|
|
is because the <samp>`c'</samp> permission bit is "on" by default. If the <samp>`c'</samp>
|
|
bit is not on, then the inherited property has the same owner in the child as
|
|
it does in the parent.
|
|
|
|
|
|
</p><p>
|
|
As an example of where this can be useful, the LambdaCore database ensures
|
|
that every player has a <samp>`password'</samp> property containing the encrypted
|
|
version of the player's connection password. For security reasons, we don't
|
|
want other players to be able to see even the encrypted version of the
|
|
password, so we turn off the <samp>`r'</samp> permission bit. To ensure that the
|
|
password is only set in a consistent way (i.e., to the encrypted version of a
|
|
player's password), we don't want to let anyone but a wizard change the
|
|
property. Thus, in the parent object for all players, we made a wizard the
|
|
owner of the password property and set the permissions to the empty string,
|
|
<code>""</code>. That is, non-owners cannot read or write the property and, because
|
|
the <samp>`c'</samp> bit is not set, the wizard who owns the property on the parent
|
|
class also owns it on all of the descendants of that class.
|
|
|
|
|
|
</p><p>
|
|
Another, perhaps more down-to-earth example arose when a character named Ford
|
|
started building objects he called "radios" and another character, yduJ,
|
|
wanted to own one. Ford kindly made the generic radio object fertile, allowing
|
|
yduJ to create a child object of it, her own radio. Radios had a property
|
|
called <samp>`channel'</samp> that identified something corresponding to the frequency
|
|
to which the radio was tuned. Ford had written nice programs on radios (verbs,
|
|
discussed below) for turning the channel selector on the front of the radio,
|
|
which would make a corresponding change in the value of the <samp>`channel'</samp>
|
|
property. However, whenever anyone tried to turn the channel selector on
|
|
yduJ's radio, they got a permissions error. The problem concerned the
|
|
ownership of the <samp>`channel'</samp> property.
|
|
|
|
|
|
</p><p>
|
|
As I explain later, programs run with the permissions of their author. So, in
|
|
this case, Ford's nice verb for setting the channel ran with his permissions.
|
|
But, since the <samp>`channel'</samp> property in the generic radio had the <samp>`c'</samp>
|
|
permission bit set, the <samp>`channel'</samp> property on yduJ's radio was owned by
|
|
her. Ford didn't have permission to change it! The fix was simple. Ford
|
|
changed the permissions on the <samp>`channel'</samp> property of the generic radio to
|
|
be just <samp>`r'</samp>, without the <samp>`c'</samp> bit, and yduJ made a new radio. This
|
|
time, when yduJ's radio inherited the <samp>`channel'</samp> property, yduJ did not
|
|
inherit ownership of it; Ford remained the owner. Now the radio worked
|
|
properly, because Ford's verb had permission to change the channel.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC7" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC7">Verbs on Objects</a></h3>
|
|
|
|
<p>
|
|
The final kind of piece making up an object is <em>verbs</em>. A verb is a named
|
|
MOO program that is associated with a particular object. Most verbs implement
|
|
commands that a player might type; for example, in the LambdaCore database,
|
|
there is a verb on all objects representing containers that implements
|
|
commands of the form `put <var>object</var> in <var>container</var>'. It is also
|
|
possible for MOO programs to invoke the verbs defined on objects. Some verbs,
|
|
in fact, are designed to be used only from inside MOO code; they do not
|
|
correspond to any particular player command at all. Thus, verbs in MOO are
|
|
like the `procedures' or `methods' found in some other programming languages.
|
|
|
|
|
|
</p><p>
|
|
As with properties, every verb has an owner and a set of permission bits. The
|
|
owner of a verb can change its program, its permission bits, and its argument
|
|
specifiers (discussed below). Only a wizard can change the owner of a verb.
|
|
The owner of a verb also determines the permissions with which that verb runs;
|
|
that is, the program in a verb can do whatever operations the owner of that
|
|
verb is allowed to do and no others. Thus, for example, a verb owned by a
|
|
wizard must be written very carefully, since wizards are allowed to do just
|
|
about anything.
|
|
|
|
|
|
</p><p>
|
|
The permission bits on verbs are drawn from this set: <samp>`r'</samp> (read),
|
|
<samp>`w'</samp> (write), <samp>`x'</samp> (execute), and <samp>`d'</samp> (debug). Read permission
|
|
lets non-owners see the program for a verb and, symmetrically, write
|
|
permission lets them change that program. The other two bits are not,
|
|
properly speaking, permission bits at all; they have a universal effect,
|
|
covering both the owner and non-owners.
|
|
|
|
|
|
</p><p>
|
|
The execute bit determines whether or not the verb can be invoked from within
|
|
a MOO program (as opposed to from the command line, like the <samp>`put'</samp> verb
|
|
on containers). If the <samp>`x'</samp> bit is not set, the verb cannot be called
|
|
from inside a program. The <samp>`x'</samp> bit is usually set.
|
|
|
|
|
|
</p><p>
|
|
The setting of the debug bit determines what happens when the verb's program
|
|
does something erroneous, like subtracting a number from a character string.
|
|
If the <samp>`d'</samp> bit is set, then the server <em>raises</em> an error value; such
|
|
raised errors can be <em>caught</em> by certain other pieces of MOO code. If the
|
|
error is not caught, however, the server aborts execution of the command and,
|
|
by default, prints an error message on the terminal of the player whose command
|
|
is being executed. (See the chapter on server assumptions about the database
|
|
for details on how uncaught errors are handled.) If the <samp>`d'</samp> bit is not
|
|
set, then no error is raised, no message is printed, and the command is not
|
|
aborted; instead the error value is returned as the result of the erroneous
|
|
operation.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<strong>Note:</strong> the <samp>`d'</samp> bit exists only for historical reasons; it used to
|
|
be the only way for MOO code to catch and handle errors. With the introduction
|
|
of the <code>try</code>-<code>except</code> statement and the error-catching expression,
|
|
the <samp>`d'</samp> bit is no longer useful. All new verbs should have the <samp>`d'</samp>
|
|
bit set, using the newer facilities for error handling if desired. Over time,
|
|
old verbs written assuming the <samp>`d'</samp> bit would not be set should be changed
|
|
to use the new facilities instead.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
In addition to an owner and some permission bits, every verb has three
|
|
`argument specifiers', one each for the direct object, the preposition, and
|
|
the indirect object. The direct and indirect specifiers are each drawn from
|
|
this set: <samp>`this'</samp>, <samp>`any'</samp>, or <samp>`none'</samp>. The preposition specifier
|
|
is <samp>`none'</samp>, <samp>`any'</samp>, or one of the items in this list:
|
|
|
|
|
|
|
|
</p><pre>with/using
|
|
at/to
|
|
in front of
|
|
in/inside/into
|
|
on top of/on/onto/upon
|
|
out of/from inside/from
|
|
over
|
|
through
|
|
under/underneath/beneath
|
|
behind
|
|
beside
|
|
for/about
|
|
is
|
|
as
|
|
off/off of
|
|
</pre>
|
|
|
|
<p>
|
|
The argument specifiers are used in the process of parsing commands,
|
|
described in the next chapter.
|
|
|
|
|
|
|
|
|
|
</p><h1><a name="SEC8" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC8">The Built-in Command Parser</a></h1>
|
|
|
|
<p>
|
|
The MOO server is able to do a small amount of parsing on the commands
|
|
that a player enters. In particular, it can break apart commands that
|
|
follow one of the following forms:
|
|
|
|
|
|
|
|
</p><pre><var>verb</var>
|
|
<var>verb</var> <var>direct-object</var>
|
|
<var>verb</var> <var>direct-object</var> <var>preposition</var> <var>indirect-object</var>
|
|
</pre>
|
|
|
|
<p>
|
|
Real examples of these forms, meaningful in the LambdaCore database, are
|
|
as follows:
|
|
|
|
|
|
|
|
</p><pre>look
|
|
take yellow bird
|
|
put yellow bird in cuckoo clock
|
|
</pre>
|
|
|
|
<p>
|
|
Note that English articles (i.e., <samp>`the'</samp>, <samp>`a'</samp>, and <samp>`an'</samp>) are not
|
|
generally used in MOO commands; the parser does not know that they are
|
|
not important parts of objects' names.
|
|
|
|
|
|
</p><p>
|
|
To have any of this make real sense, it is important to understand
|
|
precisely how the server decides what to do when a player types a
|
|
command.
|
|
|
|
|
|
</p><p>
|
|
First, the server checks whether or not the first non-blank character in the
|
|
command is one of the following:
|
|
|
|
|
|
|
|
</p><pre>" : ;
|
|
</pre>
|
|
|
|
<p>
|
|
If so, that character is replaced by the corresponding command below, followed
|
|
by a space:
|
|
|
|
|
|
|
|
</p><pre>say emote eval
|
|
</pre>
|
|
|
|
<p>
|
|
For example, the command
|
|
|
|
|
|
|
|
</p><pre>"Hi, there.
|
|
</pre>
|
|
|
|
<p>
|
|
is treated exactly as if it were as follows:
|
|
|
|
|
|
|
|
</p><pre>say Hi, there.
|
|
</pre>
|
|
|
|
<p>
|
|
The server next breaks up the command into words. In the simplest case,
|
|
the command is broken into words at every run of space characters; for example,
|
|
the command <samp>`foo bar baz'</samp> would be broken into the words <samp>`foo'</samp>,
|
|
<samp>`bar'</samp>, and <samp>`baz'</samp>. To force the server to include spaces in a
|
|
"word", all or part of a word can be enclosed in double-quotes. For example,
|
|
the command
|
|
|
|
|
|
|
|
</p><pre>foo "bar mumble" baz" "fr"otz" bl"o"rt
|
|
</pre>
|
|
|
|
<p>
|
|
is broken into the words <samp>`foo'</samp>, <samp>`bar mumble'</samp>, <samp>`baz frotz'</samp>, and
|
|
<samp>`blort'</samp>. Finally, to include a double-quote or a backslash in a word,
|
|
they can be preceded by a backslash, just like in MOO strings.
|
|
|
|
|
|
</p><p>
|
|
Having thus broken the string into words, the server next checks to see if the
|
|
first word names any of the six "built-in" commands: <samp>`.program'</samp>,
|
|
<samp>`PREFIX'</samp>, <samp>`OUTPUTPREFIX'</samp>, <samp>`SUFFIX'</samp>, <samp>`OUTPUTSUFFIX'</samp>, or the
|
|
connection's defined <em>flush</em> command, if any (<samp>`.flush'</samp> by default).
|
|
The first one of these is only available to programmers, the next four are
|
|
intended for use by client programs, and the last can vary from database to
|
|
database or even connection to connection; all six are described in the final
|
|
chapter of this document, "Server Commands and Database Assumptions". If the
|
|
first word isn't one of the above, then we get to the usual case: a normal MOO
|
|
command.
|
|
|
|
|
|
</p><p>
|
|
The server next gives code in the database a chance to handle the command. If
|
|
the verb <code>$do_command()</code> exists, it is called with the words of the
|
|
command passed as its arguments and <code>argstr</code> set to the raw command typed
|
|
by the user. If <code>$do_command()</code> does not exist, or if that verb-call
|
|
completes normally (i.e., without suspending or aborting) and returns a false
|
|
value, then the built-in command parser is invoked to handle the command as
|
|
described below. Otherwise, it is assumed that the database code handled the
|
|
command completely and no further action is taken by the server for that
|
|
command.
|
|
|
|
|
|
</p><p>
|
|
If the built-in command parser is invoked, the server tries to parse the
|
|
command into a verb, direct object, preposition and indirect object. The first
|
|
word is taken to be the verb. The server then tries to find one of the
|
|
prepositional phrases listed at the end of the previous section, using the
|
|
match that occurs earliest in the command. For example, in the very odd
|
|
command <samp>`foo as bar to baz'</samp>, the server would take <samp>`as'</samp> as the
|
|
preposition, not <samp>`to'</samp>.
|
|
|
|
|
|
</p><p>
|
|
If the server succeeds in finding a preposition, it considers the words
|
|
between the verb and the preposition to be the direct object and those
|
|
after the preposition to be the indirect object. In both cases, the
|
|
sequence of words is turned into a string by putting one space between
|
|
each pair of words. Thus, in the odd command from the previous
|
|
paragraph, there are no words in the direct object (i.e., it is
|
|
considered to be the empty string, <code>""</code>) and the indirect object is
|
|
<code>"bar to baz"</code>.
|
|
|
|
|
|
</p><p>
|
|
If there was no preposition, then the direct object is taken to be all
|
|
of the words after the verb and the indirect object is the empty string.
|
|
|
|
|
|
</p><p>
|
|
The next step is to try to find MOO objects that are named by the direct
|
|
and indirect object strings.
|
|
|
|
|
|
</p><p>
|
|
First, if an object string is empty, then the corresponding object is the
|
|
special object <code>#-1</code> (aka <code>$nothing</code> in LambdaCore). If an object
|
|
string has the form of an object number (i.e., a hash mark (<samp>`#'</samp>) followed
|
|
by digits), and the object with that number exists, then that is the named
|
|
object. If the object string is either <code>"me"</code> or <code>"here"</code>, then the
|
|
player object itself or its location is used, respectively.
|
|
|
|
|
|
</p><p>
|
|
Otherwise, the server considers all of the objects whose location is either
|
|
the player (i.e., the objects the player is "holding", so to speak) or the
|
|
room the player is in (i.e., the objects in the same room as the player); it
|
|
will try to match the object string against the various names for these
|
|
objects.
|
|
|
|
|
|
</p><p>
|
|
The matching done by the server uses the <samp>`aliases'</samp> property of each of the
|
|
objects it considers. The value of this property should be a list of strings,
|
|
the various alternatives for naming the object. If it is not a list, or the
|
|
object does not have an <samp>`aliases'</samp> property, then the empty list is used.
|
|
In any case, the value of the <samp>`name'</samp> property is added to the list for the
|
|
purposes of matching.
|
|
|
|
|
|
</p><p>
|
|
The server checks to see if the object string in the command is either exactly
|
|
equal to or a prefix of any alias; if there are any exact matches, the prefix
|
|
matches are ignored. If exactly one of the objects being considered has a
|
|
matching alias, that object is used. If more than one has a match, then the
|
|
special object <code>#-2</code> (aka <code>$ambiguous_match</code> in LambdaCore) is used.
|
|
If there are no matches, then the special object <code>#-3</code> (aka
|
|
<code>$failed_match</code> in LambdaCore) is used.
|
|
|
|
|
|
</p><p>
|
|
So, now the server has identified a verb string, a preposition string,
|
|
and direct- and indirect-object strings and objects. It then looks at
|
|
each of the verbs defined on each of the following four objects, in
|
|
order:
|
|
|
|
|
|
|
|
</p><ol>
|
|
<li>
|
|
|
|
the player who typed the command,
|
|
</li><li>
|
|
|
|
the room the player is in,
|
|
</li><li>
|
|
|
|
the direct object, if any, and
|
|
</li><li>
|
|
|
|
the indirect object, if any.
|
|
</li></ol>
|
|
|
|
<p>
|
|
For each of these verbs in turn, it tests if all of the the following
|
|
are true:
|
|
|
|
|
|
|
|
</p><ul>
|
|
<li>
|
|
|
|
the verb string in the command matches one of the names for the
|
|
verb,
|
|
</li><li>
|
|
|
|
the direct- and indirect-object values found by matching are allowed by
|
|
the corresponding argument specifiers for the verb, and
|
|
</li><li>
|
|
|
|
the preposition string in the command is matched by the preposition
|
|
specifier for the verb.
|
|
</li></ul>
|
|
|
|
<p>
|
|
I'll explain each of these criteria in turn.
|
|
|
|
|
|
</p><p>
|
|
Every verb has one or more names; all of the names are kept in a single
|
|
string, separated by spaces. In the simplest case, a verb-name is just
|
|
a word made up of any characters other than spaces and stars (i.e., ` '
|
|
and <samp>`*'</samp>). In this case, the verb-name matches only itself; that
|
|
is, the name must be matched exactly.
|
|
|
|
|
|
</p><p>
|
|
If the name contains a single star, however, then the name matches any prefix
|
|
of itself that is at least as long as the part before the star. For example,
|
|
the verb-name <samp>`foo*bar'</samp> matches any of the strings <samp>`foo'</samp>,
|
|
<samp>`foob'</samp>, <samp>`fooba'</samp>, or <samp>`foobar'</samp>; note that the star itself is not
|
|
considered part of the name.
|
|
|
|
|
|
</p><p>
|
|
If the verb name <em>ends</em> in a star, then it matches any string that begins
|
|
with the part before the star. For example, the verb-name <samp>`foo*'</samp> matches
|
|
any of the strings <samp>`foo'</samp>, <samp>`foobar'</samp>, <samp>`food'</samp>, or <samp>`foogleman'</samp>,
|
|
among many others. As a special case, if the verb-name is <samp>`*'</samp> (i.e., a
|
|
single star all by itself), then it matches anything at all.
|
|
|
|
|
|
</p><p>
|
|
Recall that the argument specifiers for the direct and indirect objects are
|
|
drawn from the set <samp>`none'</samp>, <samp>`any'</samp>, and <samp>`this'</samp>. If the specifier
|
|
is <samp>`none'</samp>, then the corresponding object value must be <code>#-1</code> (aka
|
|
<code>$nothing</code> in LambdaCore); that is, it must not have been specified. If
|
|
the specifier is <samp>`any'</samp>, then the corresponding object value may be
|
|
anything at all. Finally, if the specifier is <samp>`this'</samp>, then the
|
|
corresponding object value must be the same as the object on which we found
|
|
this verb; for example, if we are considering verbs on the player, then the
|
|
object value must be the player object.
|
|
|
|
|
|
</p><p>
|
|
Finally, recall that the argument specifier for the preposition is
|
|
either <samp>`none'</samp>, <samp>`any'</samp>, or one of several sets of prepositional
|
|
phrases, given above. A specifier of <samp>`none'</samp> matches only if there
|
|
was no preposition found in the command. A specifier of <samp>`any'</samp>
|
|
always matches, regardless of what preposition was found, if any. If
|
|
the specifier is a set of prepositional phrases, then the one found must
|
|
be in that set for the specifier to match.
|
|
|
|
|
|
</p><p>
|
|
So, the server considers several objects in turn, checking each of their
|
|
verbs in turn, looking for the first one that meets all of the criteria
|
|
just explained. If it finds one, then that is the verb whose program
|
|
will be executed for this command. If not, then it looks for a verb
|
|
named <samp>`huh'</samp> on the room that the player is in; if one is found,
|
|
then that verb will be called. This feature is useful for implementing
|
|
room-specific command parsing or error recovery. If the server can't
|
|
even find a <samp>`huh'</samp> verb to run, it prints an error message like
|
|
<samp>`I couldn't understand that.'</samp> and the command is considered complete.
|
|
|
|
|
|
</p><p>
|
|
At long last, we have a program to run in response to the command typed by the
|
|
player. When the code for the program begins execution, the following
|
|
built-in variables will have the indicated values:
|
|
|
|
|
|
|
|
</p><pre>player an object, the player who typed the command
|
|
this an object, the object on which this verb was found
|
|
caller an object, the same as <samp>`player'</samp>
|
|
verb a string, the first word of the command
|
|
argstr a string, everything after the first word of the command
|
|
args a list of strings, the words in <samp>`argstr'</samp>
|
|
dobjstr a string, the direct object string found during parsing
|
|
dobj an object, the direct object value found during matching
|
|
prepstr a string, the prepositional phrase found during parsing
|
|
iobjstr a string, the indirect object string
|
|
iobj an object, the indirect object value
|
|
</pre>
|
|
|
|
<p>
|
|
The value returned by the program, if any, is ignored by the server.
|
|
|
|
|
|
|
|
|
|
</p><h1><a name="SEC9" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC9">The MOO Programming Language</a></h1>
|
|
|
|
<p>
|
|
MOO stands for "MUD, Object Oriented." MUD, in turn, has been said to stand
|
|
for many different things, but I tend to think of it as "Multi-User Dungeon"
|
|
in the spirit of those ancient precursors to MUDs, Adventure and Zork.
|
|
|
|
|
|
</p><p>
|
|
MOO, the programming language, is a relatively small and simple
|
|
object-oriented language designed to be easy to learn for most
|
|
non-programmers; most complex systems still require some significant
|
|
programming ability to accomplish, however.
|
|
|
|
|
|
</p><p>
|
|
Having given you enough context to allow you to understand exactly what MOO
|
|
code is doing, I now explain what MOO code looks like and what it means. I
|
|
begin with the syntax and semantics of expressions, those pieces of code that
|
|
have values. After that, I cover statements, the next level of structure up
|
|
from expressions. Next, I discuss the concept of a task, the kind of running
|
|
process initiated by players entering commands, among other causes. Finally,
|
|
I list all of the built-in functions available to MOO code and describe what
|
|
they do.
|
|
|
|
|
|
</p><p>
|
|
First, though, let me mention comments. You can include bits of text in your
|
|
MOO program that are ignored by the server. The idea is to allow you to put
|
|
in notes to yourself and others about what the code is doing. To do this,
|
|
begin the text of the comment with the two characters <samp>`/*'</samp> and end it
|
|
with the two characters <samp>`*/'</samp>; this is just like comments in the C
|
|
programming language. Note that the server will completely ignore that text;
|
|
it will <em>not</em> be saved in the database. Thus, such comments are only
|
|
useful in files of code that you maintain outside the database.
|
|
|
|
|
|
</p><p>
|
|
To include a more persistent comment in your code, try using a character
|
|
string literal as a statement. For example, the sentence about peanut butter
|
|
in the following code is essentially ignored during execution but will be
|
|
maintained in the database:
|
|
|
|
|
|
|
|
</p><pre>for x in (players())
|
|
"Grendel eats peanut butter!";
|
|
player:tell(x.name, " (", x, ")");
|
|
endfor
|
|
</pre>
|
|
|
|
|
|
|
|
<h2><a name="SEC10" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC10">MOO Language Expressions</a></h2>
|
|
|
|
<p>
|
|
Expressions are those pieces of MOO code that generate values; for
|
|
example, the MOO code
|
|
|
|
</p><pre>3 + 4
|
|
</pre>
|
|
|
|
<p>
|
|
is an expression that generates (or "has" or "returns") the value 7.
|
|
There are many kinds of expressions in MOO, all of them discussed below.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC11" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC11">Errors While Evaluating Expressions</a></h3>
|
|
|
|
<p>
|
|
Most kinds of expressions can, under some circumstances, cause an error to be
|
|
generated. For example, the expression <code>x / y</code> will generate the error
|
|
<code>E_DIV</code> if <code>y</code> is equal to zero. When an expression generates an
|
|
error, the behavior of the server is controlled by setting of the <samp>`d'</samp>
|
|
(debug) bit on the verb containing that expression. If the <samp>`d'</samp> bit is not
|
|
set, then the error is effectively squelched immediately upon generation; the
|
|
error value is simply returned as the value of the expression that generated
|
|
it.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<strong>Note:</strong> this error-squelching behavior is very error prone, since it
|
|
affects <em>all</em> errors, including ones the programmer may not have
|
|
anticipated. The <samp>`d'</samp> bit exists only for historical reasons; it was once
|
|
the only way for MOO programmers to catch and handle errors. The
|
|
error-catching expression and the <code>try</code>-<code>except</code> statement, both
|
|
described below, are far better ways of accomplishing the same thing.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
If the <samp>`d'</samp> bit is set, as it usually is, then the error is <em>raised</em>
|
|
and can be caught and handled either by code surrounding the expression in
|
|
question or by verbs higher up on the chain of calls leading to the current
|
|
verb. If the error is not caught, then the server aborts the entire task and,
|
|
by default, prints a message to the current player. See the descriptions of
|
|
the error-catching expression and the <code>try</code>-<code>except</code> statement for
|
|
the details of how errors can be caught, and the chapter on server assumptions
|
|
about the database for details on the handling of uncaught errors.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC12" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC12">Writing Values Directly in Verbs</a></h3>
|
|
|
|
<p>
|
|
The simplest kind of expression is a literal MOO value, just as
|
|
described in the section on values at the beginning of this document.
|
|
For example, the following are all expressions:
|
|
|
|
|
|
|
|
</p><pre>17
|
|
#893
|
|
"This is a character string."
|
|
E_TYPE
|
|
{"This", "is", "a", "list", "of", "words"}
|
|
</pre>
|
|
|
|
<p>
|
|
In the case of lists, like the last example above, note that the list
|
|
expression contains other expressions, several character strings in this
|
|
case. In general, those expressions can be of any kind at all, not
|
|
necessarily literal values. For example,
|
|
|
|
</p><pre>{3 + 4, 3 - 4, 3 * 4}
|
|
</pre>
|
|
|
|
<p>
|
|
is an expression whose value is the list <code>{7, -1, 12}</code>.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC13" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC13">Naming Values Within a Verb</a></h3>
|
|
|
|
<p>
|
|
As discussed earlier, it is possible to store values in properties on
|
|
objects; the properties will keep those values forever, or until another
|
|
value is explicitly put there. Quite often, though, it is useful to
|
|
have a place to put a value for just a little while. MOO provides local
|
|
variables for this purpose.
|
|
|
|
|
|
</p><p>
|
|
Variables are named places to hold values; you can get and set the value
|
|
in a given variable as many times as you like. Variables are temporary,
|
|
though; they only last while a particular verb is running; after it
|
|
finishes, all of the variables given values there cease to exist and the
|
|
values are forgotten.
|
|
|
|
|
|
</p><p>
|
|
Variables are also "local" to a particular verb; every verb has its own
|
|
set of them. Thus, the variables set in one verb are not visible to the
|
|
code of other verbs.
|
|
|
|
|
|
</p><p>
|
|
The name for a variable is made up entirely of letters, digits, and the
|
|
underscore character (<samp>`_'</samp>) and does not begin with a digit. The
|
|
following are all valid variable names:
|
|
|
|
|
|
|
|
</p><pre>foo
|
|
_foo
|
|
this2that
|
|
M68000
|
|
two_words
|
|
This_is_a_very_long_multiword_variable_name
|
|
</pre>
|
|
|
|
<p>
|
|
Note that, along with almost everything else in MOO, the case of the
|
|
letters in variable names is insignificant. For example, these are all
|
|
names for the same variable:
|
|
|
|
|
|
|
|
</p><pre>fubar
|
|
Fubar
|
|
FUBAR
|
|
fUbAr
|
|
</pre>
|
|
|
|
<p>
|
|
A variable name is itself an expression; its value is the value of the named
|
|
variable. When a verb begins, almost no variables have values yet; if you try
|
|
to use the value of a variable that doesn't have one, the error value
|
|
<code>E_VARNF</code> is raised. (MOO is unlike many other programming languages in
|
|
which one must `declare' each variable before using it; MOO has no such
|
|
declarations.) The following variables always have values:
|
|
|
|
|
|
|
|
</p><pre>INT FLOAT OBJ
|
|
STR LIST ERR
|
|
player this caller
|
|
verb args argstr
|
|
dobj dobjstr prepstr
|
|
iobj iobjstr NUM
|
|
</pre>
|
|
|
|
<p>
|
|
The values of some of these variables always start out the same:
|
|
|
|
|
|
</p><dl compact="compact">
|
|
|
|
<dt><code>INT</code>
|
|
</dt><dd>
|
|
an integer, the type code for integers (see the description of the function
|
|
<code>typeof()</code>, below)
|
|
</dd><dt><code>NUM</code>
|
|
</dt><dd>
|
|
the same as <code>INT</code> (for historical reasons)
|
|
</dd><dt><code>FLOAT</code>
|
|
</dt><dd>
|
|
an integer, the type code for floating-point numbers
|
|
</dd><dt><code>LIST</code>
|
|
</dt><dd>
|
|
an integer, the type code for lists
|
|
</dd><dt><code>STR</code>
|
|
</dt><dd>
|
|
an integer, the type code for strings
|
|
</dd><dt><code>OBJ</code>
|
|
</dt><dd>
|
|
an integer, the type code for objects
|
|
</dd><dt><code>ERR</code>
|
|
</dt><dd>
|
|
an integer, the type code for error values
|
|
</dd></dl>
|
|
|
|
<p>
|
|
For others, the general meaning of the value is consistent, though the
|
|
value itself is different for different situations:
|
|
|
|
|
|
</p><dl compact="compact">
|
|
|
|
<dt><code>player</code>
|
|
</dt><dd>
|
|
an object, the player who typed the command that started the task that
|
|
involved running this piece of code.
|
|
</dd><dt><code>this</code>
|
|
</dt><dd>
|
|
an object, the object on which the currently-running verb was found.
|
|
</dd><dt><code>caller</code>
|
|
</dt><dd>
|
|
an object, the object on which the verb that called the
|
|
currently-running verb was found. For the first verb called for a given
|
|
command, <samp>`caller'</samp> has the same value as <samp>`player'</samp>.
|
|
</dd><dt><code>verb</code>
|
|
</dt><dd>
|
|
a string, the name by which the currently-running verb was identified.
|
|
</dd><dt><code>args</code>
|
|
</dt><dd>
|
|
a list, the arguments given to this verb. For the first verb called for
|
|
a given command, this is a list of strings, the words on the command
|
|
line.
|
|
</dd></dl>
|
|
|
|
<p>
|
|
The rest of the so-called "built-in" variables are only really
|
|
meaningful for the first verb called for a given command. Their
|
|
semantics is given in the discussion of command parsing, above.
|
|
|
|
|
|
</p><p>
|
|
To change what value is stored in a variable, use an <em>assignment</em>
|
|
expression:
|
|
|
|
|
|
|
|
</p><pre><var>variable</var> = <var>expression</var>
|
|
</pre>
|
|
|
|
<p>
|
|
For example, to change the variable named <samp>`x'</samp> to have the value 17,
|
|
you would write <samp>`x = 17'</samp> as an expression. An assignment
|
|
expression does two things:
|
|
|
|
|
|
|
|
</p><ul>
|
|
<li>
|
|
|
|
it changes the value of of the named variable, and
|
|
</li><li>
|
|
|
|
it returns the new value of that variable.
|
|
</li></ul>
|
|
|
|
<p>
|
|
Thus, the expression
|
|
|
|
|
|
|
|
</p><pre>13 + (x = 17)
|
|
</pre>
|
|
|
|
<p>
|
|
changes the value of <samp>`x'</samp> to be 17 and returns 30.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC14" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC14">Arithmetic Operators</a></h3>
|
|
|
|
<p>
|
|
All of the usual simple operations on numbers are available to MOO programs:
|
|
|
|
|
|
|
|
</p><pre>+ - * / %
|
|
</pre>
|
|
|
|
<p>
|
|
These are, in order, addition, subtraction, multiplication, division, and
|
|
remainder. In the following table, the expressions on the left have the
|
|
corresponding values on the right:
|
|
|
|
|
|
|
|
</p><pre>5 + 2 => 7
|
|
5 - 2 => 3
|
|
5 * 2 => 10
|
|
5 / 2 => 2
|
|
5.0 / 2.0 => 2.5
|
|
5 % 2 => 1
|
|
5.0 % 2.0 => 1.0
|
|
5 % -2 => 1
|
|
-5 % 2 => -1
|
|
-5 % -2 => -1
|
|
-(5 + 2) => -7
|
|
</pre>
|
|
|
|
<p>
|
|
Note that integer division in MOO throws away the remainder and that the result
|
|
of the remainder operator (<samp>`%'</samp>) has the same sign as the left-hand
|
|
operand. Also, note that <samp>`-'</samp> can be used without a left-hand operand to
|
|
negate a numeric expression.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<em>Fine point:</em> Integers and floating-point numbers cannot be mixed in any
|
|
particular use of these arithmetic operators; unlike some other programming
|
|
languages, MOO does not automatically coerce integers into floating-point
|
|
numbers. You can use the <code>tofloat()</code> function to perform an explicit
|
|
conversion.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
The <samp>`+'</samp> operator can also be used to append two strings. The expression
|
|
|
|
|
|
|
|
</p><pre>"foo" + "bar"
|
|
</pre>
|
|
|
|
<p>
|
|
has the value
|
|
|
|
|
|
|
|
</p><pre>"foobar"
|
|
</pre>
|
|
|
|
<p>
|
|
Unless both operands to an arithmetic operator are numbers of the same kind
|
|
(or, for <samp>`+'</samp>, both strings), the error value <code>E_TYPE</code> is raised. If
|
|
the right-hand operand for the division or remainder operators (<samp>`/'</samp> or
|
|
<samp>`%'</samp>) is zero, the error value <code>E_DIV</code> is raised.
|
|
|
|
|
|
</p><p>
|
|
MOO also supports the exponentiation operation, also known as "raising to a
|
|
power," using the <samp>`^'</samp> operator:
|
|
|
|
|
|
|
|
</p><pre>3 ^ 4 => 81
|
|
3 ^ 4.5 error--> E_TYPE
|
|
3.5 ^ 4 => 150.0625
|
|
3.5 ^ 4.5 => 280.741230801382
|
|
</pre>
|
|
|
|
<p>
|
|
Note that if the first operand is an integer, then the second operand must also
|
|
be an integer. If the first operand is a floating-point number, then the
|
|
second operand can be either kind of number. Although it is legal to raise an
|
|
integer to a negative power, it is unlikely to be terribly useful.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC15" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC15">Comparing Values</a></h3>
|
|
|
|
<p>
|
|
Any two values can be compared for equality using <samp>`=='</samp> and
|
|
<samp>`!='</samp>. The first of these returns 1 if the two values are equal and
|
|
0 otherwise; the second does the reverse:
|
|
|
|
|
|
|
|
</p><pre>3 == 4 => 0
|
|
3 != 4 => 1
|
|
3 == 3.0 => 0
|
|
"foo" == "Foo" => 1
|
|
#34 != #34 => 0
|
|
{1, #34, "foo"} == {1, #34, "FoO"} => 1
|
|
E_DIV == E_TYPE => 0
|
|
3 != "foo" => 1
|
|
</pre>
|
|
|
|
<p>
|
|
Note that integers and floating-point numbers are never equal to one another,
|
|
even in the `obvious' cases. Also note that comparison of strings (and list
|
|
values containing strings) is case-insensitive; that is, it does not
|
|
distinguish between the upper- and lower-case version of letters. To test two
|
|
values for case-sensitive equality, use the <samp>`equal'</samp> function described
|
|
later.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<strong>Warning</strong>: It is easy (and very annoying) to confuse the
|
|
equality-testing operator (<samp>`=='</samp>) with the assignment operator (<samp>`='</samp>),
|
|
leading to nasty, hard-to-find bugs. Don't do this.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
Numbers, object numbers, strings, and error values can also be compared
|
|
for ordering purposes using the following operators:
|
|
|
|
|
|
|
|
</p><pre>< <= >= >
|
|
</pre>
|
|
|
|
<p>
|
|
meaning "less than," "less than or equal," "greater than or
|
|
equal," and "greater than," respectively. As with the equality
|
|
operators, these return 1 when their operands are in the appropriate
|
|
relation and 0 otherwise:
|
|
|
|
|
|
|
|
</p><pre>3 < 4 => 1
|
|
3 < 4.0 error--> E_TYPE
|
|
#34 >= #32 => 1
|
|
"foo" <= "Boo" => 0
|
|
E_DIV > E_TYPE => 1
|
|
</pre>
|
|
|
|
<p>
|
|
Note that, as with the equality operators, strings are compared
|
|
case-insensitively. To perform a case-sensitive string comparison, use the
|
|
<samp>`strcmp'</samp> function described later. Also note that the error values are
|
|
ordered as given in the table in the section on values. If the operands to
|
|
these four comparison operators are of different types (even integers and
|
|
floating-point numbers are considered different types), or if they are lists,
|
|
then <code>E_TYPE</code> is raised.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC16" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC16">Values as True and False</a></h3>
|
|
|
|
<p>
|
|
There is a notion in MOO of <em>true</em> and <em>false</em> values; every value
|
|
is one or the other. The true values are as follows:
|
|
|
|
|
|
|
|
</p><ul>
|
|
<li>
|
|
|
|
all integers other than zero,
|
|
</li><li>
|
|
|
|
all floating-point numbers not equal to <code>0.0</code>,
|
|
</li><li>
|
|
|
|
all non-empty strings (i.e., other than <samp>`""'</samp>), and
|
|
</li><li>
|
|
|
|
all non-empty lists (i.e., other than <samp>`{}'</samp>).
|
|
</li></ul>
|
|
|
|
<p>
|
|
All other values are false:
|
|
|
|
|
|
|
|
</p><ul>
|
|
<li>
|
|
|
|
the integer zero,
|
|
</li><li>
|
|
|
|
the floating-point numbers <code>0.0</code> and <code>-0.0</code>,
|
|
</li><li>
|
|
|
|
the empty string (<samp>`""'</samp>),
|
|
</li><li>
|
|
|
|
the empty list (<samp>`{}'</samp>),
|
|
</li><li>
|
|
|
|
all object numbers, and
|
|
</li><li>
|
|
|
|
all error values.
|
|
</li></ul>
|
|
|
|
<p>
|
|
There are four kinds of expressions and two kinds of statements that depend
|
|
upon this classification of MOO values. In describing them, I sometimes refer
|
|
to the <em>truth value</em> of a MOO value; this is just <em>true</em> or
|
|
<em>false</em>, the category into which that MOO value is classified.
|
|
|
|
|
|
</p><p>
|
|
The conditional expression in MOO has the following form:
|
|
|
|
|
|
|
|
</p><pre><var>expression-1</var> ? <var>expression-2</var> | <var>expression-3</var>
|
|
</pre>
|
|
|
|
<p>
|
|
First, <var>expression-1</var> is evaluated. If it returns a true value, then
|
|
<var>expression-2</var> is evaluated and whatever it returns is returned as the
|
|
value of the conditional expression as a whole. If <var>expression-1</var> returns
|
|
a false value, then <var>expression-3</var> is evaluated instead and its value is
|
|
used as that of the conditional expression.
|
|
|
|
|
|
|
|
</p><pre>1 ? 2 | 3 => 2
|
|
0 ? 2 | 3 => 3
|
|
"foo" ? 17 | {#34} => 17
|
|
</pre>
|
|
|
|
<p>
|
|
Note that only one of <var>expression-2</var> and <var>expression-3</var> is evaluated,
|
|
never both.
|
|
|
|
|
|
</p><p>
|
|
To negate the truth value of a MOO value, use the <samp>`!'</samp> operator:
|
|
|
|
|
|
|
|
</p><pre>! <var>expression</var>
|
|
</pre>
|
|
|
|
<p>
|
|
If the value of <var>expression</var> is true, <samp>`!'</samp> returns 0; otherwise, it
|
|
returns 1:
|
|
|
|
|
|
|
|
</p><pre>! "foo" => 0
|
|
! (3 >= 4) => 1
|
|
</pre>
|
|
|
|
<p>
|
|
The negation operator is usually read as "not."
|
|
|
|
|
|
</p><p>
|
|
It is frequently useful to test more than one condition to see if some or all
|
|
of them are true. MOO provides two operators for this:
|
|
|
|
|
|
|
|
</p><pre><var>expression-1</var> && <var>expression-2</var>
|
|
<var>expression-1</var> || <var>expression-2</var>
|
|
</pre>
|
|
|
|
<p>
|
|
These operators are usually read as "and" and "or," respectively.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`&&'</samp> operator first evaluates <var>expression-1</var>. If it returns a
|
|
true value, then <var>expression-2</var> is evaluated and its value becomes the
|
|
value of the <samp>`&&'</samp> expression as a whole; otherwise, the value of
|
|
<var>expression-1</var> is used as the value of the <samp>`&&'</samp> expression. Note
|
|
that <var>expression-2</var> is only evaluated if <var>expression-1</var> returns a true
|
|
value. The <samp>`&&'</samp> expression is equivalent to the conditional expression
|
|
|
|
|
|
|
|
</p><pre><var>expression-1</var> ? <var>expression-2</var> | <var>expression-1</var>
|
|
</pre>
|
|
|
|
<p>
|
|
except that <var>expression-1</var> is only evaluated once.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`||'</samp> operator works similarly, except that <var>expression-2</var> is
|
|
evaluated only if <var>expression-1</var> returns a false value. It is equivalent
|
|
to the conditional expression
|
|
|
|
|
|
|
|
</p><pre><var>expression-1</var> ? <var>expression-1</var> | <var>expression-2</var>
|
|
</pre>
|
|
|
|
<p>
|
|
except that, as with <samp>`&&'</samp>, <var>expression-1</var> is only evaluated once.
|
|
|
|
|
|
</p><p>
|
|
These two operators behave very much like "and" and "or" in English:
|
|
|
|
|
|
|
|
</p><pre>1 && 1 => 1
|
|
0 && 1 => 0
|
|
0 && 0 => 0
|
|
1 || 1 => 1
|
|
0 || 1 => 1
|
|
0 || 0 => 0
|
|
17 <= 23 && 23 <= 27 => 1
|
|
</pre>
|
|
|
|
|
|
|
|
<h3><a name="SEC17" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC17">Indexing into Lists and Strings</a></h3>
|
|
|
|
<p>
|
|
Both strings and lists can be seen as ordered sequences of MOO values. In the
|
|
case of strings, each is a sequence of single-character strings; that is, one
|
|
can view the string <code>"bar"</code> as a sequence of the strings <code>"b"</code>,
|
|
<code>"a"</code>, and <code>"r"</code>. MOO allows you to refer to the elements of lists
|
|
and strings by number, by the <em>index</em> of that element in the list or
|
|
string. The first element in a list or string has index 1, the second has
|
|
index 2, and so on.
|
|
|
|
|
|
|
|
|
|
</p><h4><a name="SEC18" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC18">Extracting an Element from a List or String</a></h4>
|
|
|
|
<p>
|
|
The indexing expression in MOO extracts a specified element from a list or
|
|
string:
|
|
|
|
|
|
|
|
</p><pre><var>expression-1</var>[<var>expression-2</var>]
|
|
</pre>
|
|
|
|
<p>
|
|
First, <var>expression-1</var> is evaluated; it must return a list or a string (the
|
|
<em>sequence</em>). Then, <var>expression-2</var> is evaluated and must return an
|
|
integer (the <em>index</em>). If either of the expressions returns some other type
|
|
of value, <code>E_TYPE</code> is returned. The index must be between 1 and the
|
|
length of the sequence, inclusive; if it is not, then <code>E_RANGE</code> is raised.
|
|
The value of the indexing expression is the index'th element in the sequence.
|
|
Anywhere within <var>expression-2</var>, you can use the symbol <code>$</code> as an
|
|
expression returning the length of the value of <var>expression-1</var>.
|
|
|
|
|
|
|
|
</p><pre>"fob"[2] => "o"
|
|
"fob"[1] => "f"
|
|
{#12, #23, #34}[$ - 1] => #23
|
|
</pre>
|
|
|
|
<p>
|
|
Note that there are no legal indices for the empty string or list, since
|
|
there are no integers between 1 and 0 (the length of the empty string or
|
|
list).
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<em>Fine point:</em> The <code>$</code> expression actually returns the length of the
|
|
value of the expression just before the nearest enclosing <code>[...]</code>
|
|
indexing or subranging brackets. For example:
|
|
|
|
</p><pre>"frob"[{3, 2, 4}[$]] => "b"
|
|
</pre>
|
|
|
|
</blockquote>
|
|
|
|
|
|
|
|
<h4><a name="SEC19" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC19">Replacing an Element of a List or String</a></h4>
|
|
|
|
<p>
|
|
It often happens that one wants to change just one particular slot of a list or
|
|
string, which is stored in a variable or a property. This can be done
|
|
conveniently using an <em>indexed assignment</em> having one of the following
|
|
forms:
|
|
|
|
|
|
|
|
</p><pre><var>variable</var>[<var>index-expr</var>] = <var>result-expr</var>
|
|
<var>object-expr</var>.<var>name</var>[<var>index-expr</var>] = <var>result-expr</var>
|
|
<var>object-expr</var>.(<var>name-expr</var>)[<var>index-expr</var>] = <var>result-expr</var>
|
|
$<var>name</var>[<var>index-expr</var>] = <var>result-expr</var>
|
|
</pre>
|
|
|
|
<p>
|
|
The first form writes into a variable, and the last three forms write into a
|
|
property. The usual errors (<code>E_TYPE</code>, <code>E_INVIND</code>, <code>E_PROPNF</code>
|
|
and <code>E_PERM</code> for lack of read/write permission on the property) may be
|
|
raised, just as in reading and writing any object property; see the
|
|
discussion of object property expressions below for details. Correspondingly,
|
|
if <var>variable</var> does not yet have a value (i.e., it has never been assigned
|
|
to), <code>E_VARNF</code> will be raised.
|
|
|
|
|
|
</p><p>
|
|
If <var>index-expr</var> is not an integer, or if the value of <var>variable</var> or the
|
|
property is not a list or string, <code>E_TYPE</code> is raised. If
|
|
<var>result-expr</var> is a string, but not of length 1, <code>E_INVARG</code> is
|
|
raised. Now suppose <var>index-expr</var> evaluates to an integer <var>k</var>. If
|
|
<var>k</var> is outside the range of the list or string (i.e. smaller than 1 or
|
|
greater than the length of the list or string), <code>E_RANGE</code> is raised.
|
|
Otherwise, the actual assignment takes place. For lists, the variable or the
|
|
property is assigned a new list that is identical to the original one except at
|
|
the <var>k</var>-th position, where the new list contains the result of
|
|
<var>result-expr</var> instead. For strings, the variable or the property is
|
|
assigned a new string that is identical to the original one, except the
|
|
<var>k</var>-th character is changed to be <var>result-expr</var>.
|
|
|
|
|
|
</p><p>
|
|
The assignment expression itself returns the value of <var>result-expr</var>. For
|
|
the following examples, assume that <code>l</code> initially contains the list
|
|
<code>{1, 2, 3}</code> and that <code>s</code> initially contains the string "foobar":
|
|
|
|
|
|
|
|
</p><pre>l[5] = 3 error--> E_RANGE
|
|
l["first"] = 4 error--> E_TYPE
|
|
s[3] = "baz" error--> E_INVARG
|
|
l[2] = l[2] + 3 => 5
|
|
l => {1, 5, 3}
|
|
l[2] = "foo" => "foo"
|
|
l => {1, "foo", 3}
|
|
s[2] = "u" => "u"
|
|
s => "fuobar"
|
|
s[$] = "z" => "z"
|
|
s => "fuobaz"
|
|
</pre>
|
|
|
|
<p>
|
|
Note that the <code>$</code> expression may also be used in indexed assignments with
|
|
the same meaning as before.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<em>Fine point:</em> After an indexed assignment, the variable or property
|
|
contains a <em>new</em> list or string, a copy of the original list in all but
|
|
the <var>k</var>-th place, where it contains a new value. In programming-language
|
|
jargon, the original list is not mutated, and there is no aliasing. (Indeed,
|
|
no MOO value is mutable and no aliasing ever occurs.)
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
In the list case, indexed assignment can be nested to many levels, to work on
|
|
nested lists. Assume that <code>l</code> initially contains the list
|
|
|
|
|
|
|
|
</p><pre>{{1, 2, 3}, {4, 5, 6}, "foo"}
|
|
</pre>
|
|
|
|
<p>
|
|
in the following examples:
|
|
|
|
|
|
|
|
</p><pre>l[7] = 4 error--> E_RANGE
|
|
l[1][8] = 35 error--> E_RANGE
|
|
l[3][2] = 7 error--> E_TYPE
|
|
l[1][1][1] = 3 error--> E_TYPE
|
|
l[2][2] = -l[2][2] => -5
|
|
l => {{1, 2, 3}, {4, -5, 6}, "foo"}
|
|
l[2] = "bar" => "bar"
|
|
l => {{1, 2, 3}, "bar", "foo"}
|
|
l[2][$] = "z" => "z"
|
|
l => {{1, 2, 3}, "baz", "foo"}
|
|
</pre>
|
|
|
|
<p>
|
|
The first two examples raise <code>E_RANGE</code> because 7 is out of the range of
|
|
<code>l</code> and 8 is out of the range of <code>l[1]</code>. The next two examples
|
|
raise <code>E_TYPE</code> because <code>l[3]</code> and <code>l[1][1]</code> are not lists.
|
|
|
|
|
|
|
|
|
|
</p><h4><a name="SEC20" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC20">Extracting a Subsequence of a List or String</a></h4>
|
|
|
|
<p>
|
|
The range expression extracts a specified subsequence from a list or string:
|
|
|
|
|
|
|
|
</p><pre><var>expression-1</var>[<var>expression-2</var>..<var>expression-3</var>]
|
|
</pre>
|
|
|
|
<p>
|
|
The three expressions are evaluated in order. <var>Expression-1</var> must return a
|
|
list or string (the <em>sequence</em>) and the other two expressions must return
|
|
integers (the <em>low</em> and <em>high</em> indices, respectively); otherwise,
|
|
<code>E_TYPE</code> is raised. The <code>$</code> expression can be used in either or both
|
|
of <var>expression-2</var> and <var>expression-3</var> just as before, meaning the length
|
|
of the value of <var>expression-1</var>.
|
|
|
|
|
|
</p><p>
|
|
If the low index is greater than the high index, then the empty string or list
|
|
is returned, depending on whether the sequence is a string or a list.
|
|
Otherwise, both indices must be between 1 and the length of the sequence;
|
|
<code>E_RANGE</code> is raised if they are not. A new list or string is returned
|
|
that contains just the elements of the sequence with indices between the low
|
|
and high bounds.
|
|
|
|
|
|
|
|
</p><pre>"foobar"[2..$] => "oobar"
|
|
"foobar"[3..3] => "o"
|
|
"foobar"[17..12] => ""
|
|
{"one", "two", "three"}[$ - 1..$] => {"two", "three"}
|
|
{"one", "two", "three"}[3..3] => {"three"}
|
|
{"one", "two", "three"}[17..12] => {}
|
|
</pre>
|
|
|
|
|
|
|
|
<h4><a name="SEC21" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC21">Replacing a Subsequence of a List or String</a></h4>
|
|
|
|
<p>
|
|
The subrange assigment replaces a specified subsequence of a list or string
|
|
with a supplied subsequence. The allowed forms are:
|
|
|
|
|
|
|
|
</p><pre><var>variable</var>[<var>start-index-expr</var>..<var>end-index-expr</var>] = <var>result-expr</var>
|
|
<var>object-expr</var>.<var>name</var>[<var>start-index-expr</var>..<var>end-index-expr</var>] = <var>result-expr</var>
|
|
<var>object-expr</var>.(<var>name-expr</var>)[<var>start-index-expr</var>..<var>end-index-expr</var>] = <var>result-expr</var>
|
|
$<var>name</var>[<var>start-index-expr</var>..<var>end-index-expr</var>] = <var>result-expr</var>
|
|
</pre>
|
|
|
|
<p>
|
|
As with indexed assigments, the first form writes into a variable, and the last
|
|
three forms write into a property. The same errors (<code>E_TYPE</code>,
|
|
<code>E_INVIND</code>, <code>E_PROPNF</code> and <code>E_PERM</code> for lack of read/write
|
|
permission on the property) may be raised. If <var>variable</var> does not yet have
|
|
a value (i.e., it has never been assigned to), <code>E_VARNF</code> will be raised.
|
|
As before, the <code>$</code> expression can be used in either <var>start-index-expr</var>
|
|
or <var>end-index-expr</var>, meaning the length of the original value of the
|
|
expression just before the <code>[...]</code> part.
|
|
|
|
|
|
</p><p>
|
|
If <var>start-index-expr</var> or <var>end-index-expr</var> is not an integer, if the value
|
|
of <var>variable</var> or the property is not a list or string, or <var>result-expr</var>
|
|
is not the same type as <var>variable</var> or the property, <code>E_TYPE</code> is
|
|
raised. <code>E_RANGE</code> is raised if <var>end-index-expr</var> is less than zero
|
|
or if <var>start-index-expr</var> is greater than the length of the list or string
|
|
plus one. Note: the length of <var>result-expr</var> does not need to be the same
|
|
as the length of the specified range.
|
|
|
|
|
|
</p><p>
|
|
In precise terms, the subrange assigment
|
|
|
|
</p><pre><var>v</var>[<var>start</var>..<var>end</var>] = <var>value</var>
|
|
</pre>
|
|
|
|
<p>
|
|
is equivalent to
|
|
|
|
</p><pre><var>v</var> = {@<var>v</var>[1..<var>start</var> - 1], @<var>value</var>, @<var>v</var>[<var>end</var> + 1..$]}
|
|
</pre>
|
|
|
|
<p>
|
|
if <var>v</var> is a list and to
|
|
|
|
</p><pre><var>v</var> = <var>v</var>[1..<var>start</var> - 1] + <var>value</var> + <var>v</var>[<var>end</var> + 1..$]
|
|
</pre>
|
|
|
|
<p>
|
|
if <var>v</var> is a string.
|
|
|
|
|
|
</p><p>
|
|
The assigment expression itself returns the value of <var>result-expr</var>. For
|
|
the following examples, assume that <code>l</code> initially contains the list
|
|
<code>{1, 2, 3}</code> and that <code>s</code> initially contains the string "foobar":
|
|
|
|
|
|
|
|
</p><pre>l[5..6] = {7, 8} error--> E_RANGE
|
|
l[2..3] = 4 error--> E_TYPE
|
|
l[#2..3] = {7} error--> E_TYPE
|
|
s[2..3] = {6} error--> E_TYPE
|
|
l[2..3] = {6, 7, 8, 9} => {6, 7, 8, 9}
|
|
l => {1, 6, 7, 8, 9}
|
|
l[2..1] = {10, "foo"} => {10, "foo"}
|
|
l => {1, 10, "foo", 6, 7, 8, 9}
|
|
l[3][2..$] = "u" => "u"
|
|
l => {1, 10, "fu", 6, 7, 8, 9}
|
|
s[7..12] = "baz" => "baz"
|
|
s => "foobarbaz"
|
|
s[1..3] = "fu" => "fu"
|
|
s => "fubarbaz"
|
|
s[1..0] = "test" => "test"
|
|
s => "testfubarbaz"
|
|
</pre>
|
|
|
|
|
|
|
|
<h3><a name="SEC22" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC22">Other Operations on Lists</a></h3>
|
|
|
|
<p>
|
|
As was mentioned earlier, lists can be constructed by writing a
|
|
comma-separated sequence of expressions inside curly braces:
|
|
|
|
|
|
|
|
</p><pre>{<var>expression-1</var>, <var>expression-2</var>, ..., <var>expression-N</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
The resulting list has the value of <var>expression-1</var> as its first element,
|
|
that of <var>expression-2</var> as the second, etc.
|
|
|
|
|
|
|
|
</p><pre>{3 < 4, 3 <= 4, 3 >= 4, 3 > 4} => {1, 1, 0, 0}
|
|
</pre>
|
|
|
|
<p>
|
|
Additionally, one may precede any of these expressions by the splicing
|
|
operator, <samp>`@'</samp>. Such an expression must return a list; rather than the
|
|
old list itself becoming an element of the new list, all of the elements of
|
|
the old list are included in the new list. This concept is easy to
|
|
understand, but hard to explain in words, so here are some examples. For
|
|
these examples, assume that the variable <code>a</code> has the value <code>{2, 3,
|
|
4}</code> and that <code>b</code> has the value <code>{"Foo", "Bar"}</code>:
|
|
|
|
|
|
|
|
</p><pre>{1, a, 5} => {1, {2, 3, 4}, 5}
|
|
{1, @a, 5} => {1, 2, 3, 4, 5}
|
|
{a, @a} => {{2, 3, 4}, 2, 3, 4}
|
|
{@a, @b} => {2, 3, 4, "Foo", "Bar"}
|
|
</pre>
|
|
|
|
<p>
|
|
If the splicing operator (<samp>`@'</samp>) precedes an expression whose value
|
|
is not a list, then <code>E_TYPE</code> is raised as the value of the list
|
|
construction as a whole.
|
|
|
|
|
|
</p><p>
|
|
The list membership expression tests whether or not a given MOO value is an
|
|
element of a given list and, if so, with what index:
|
|
|
|
|
|
|
|
</p><pre><var>expression-1</var> in <var>expression-2</var>
|
|
</pre>
|
|
|
|
<p>
|
|
<var>Expression-2</var> must return a list; otherwise, <code>E_TYPE</code> is raised.
|
|
If the value of <var>expression-1</var> is in that list, then the index of its first
|
|
occurrence in the list is returned; otherwise, the <samp>`in'</samp> expression returns
|
|
0.
|
|
|
|
|
|
|
|
</p><pre>2 in {5, 8, 2, 3} => 3
|
|
7 in {5, 8, 2, 3} => 0
|
|
"bar" in {"Foo", "Bar", "Baz"} => 2
|
|
</pre>
|
|
|
|
<p>
|
|
Note that the list membership operator is case-insensitive in comparing
|
|
strings, just like the comparison operators. To perform a case-sensitive list
|
|
membership test, use the <samp>`is_member'</samp> function described later. Note also
|
|
that since it returns zero only if the given value is not in the given list,
|
|
the <samp>`in'</samp> expression can be used either as a membership test or as an
|
|
element locator.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC23" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC23">Spreading List Elements Among Variables</a></h3>
|
|
|
|
<p>
|
|
It is often the case in MOO programming that you will want to access the
|
|
elements of a list individually, with each element stored in a separate
|
|
variables. This desire arises, for example, at the beginning of almost every
|
|
MOO verb, since the arguments to all verbs are delivered all bunched together
|
|
in a single list. In such circumstances, you <em>could</em> write statements
|
|
like these:
|
|
|
|
|
|
|
|
</p><pre>first = args[1];
|
|
second = args[2];
|
|
if (length(args) > 2)
|
|
third = args[3];
|
|
else
|
|
third = 0;
|
|
endif
|
|
</pre>
|
|
|
|
<p>
|
|
This approach gets pretty tedious, both to read and to write, and it's prone to
|
|
errors if you mistype one of the indices. Also, you often want to check
|
|
whether or not any <em>extra</em> list elements were present, adding to the
|
|
tedium.
|
|
|
|
|
|
</p><p>
|
|
MOO provides a special kind of assignment expression, called <em>scattering
|
|
assignment</em> made just for cases such as these. A scattering assignment
|
|
expression looks like this:
|
|
|
|
|
|
|
|
</p><pre>{<var>target</var>, ...} = <var>expr</var>
|
|
</pre>
|
|
|
|
<p>
|
|
where each <var>target</var> describes a place to store elements of the list that
|
|
results from evaluating <var>expr</var>. A <var>target</var> has one of the following
|
|
forms:
|
|
|
|
|
|
</p><dl compact="compact">
|
|
|
|
<dt><code><var>variable</var></code>
|
|
</dt><dd>
|
|
This is the simplest target, just a simple variable; the list element in the
|
|
corresponding position is assigned to the variable. This is called a
|
|
<em>required</em> target, since the assignment is required to put one of the list
|
|
elements into the variable.
|
|
|
|
</dd><dt><code>?<var>variable</var></code>
|
|
</dt><dd>
|
|
This is called an <em>optional</em> target, since it doesn't always get assigned
|
|
an element. If there are any list elements left over after all of the required
|
|
targets have been accounted for (along with all of the other optionals to the
|
|
left of this one), then this variable is treated like a required one and the
|
|
list element in the corresponding position is assigned to the variable. If
|
|
there aren't enough elements to assign one to this target, then no assignment
|
|
is made to this variable, leaving it with whatever its previous value was.
|
|
|
|
</dd><dt><code>?<var>variable</var> = <var>default-expr</var></code>
|
|
</dt><dd>
|
|
This is also an optional target, but if there aren't enough list elements
|
|
available to assign one to this target, the result of evaluating
|
|
<var>default-expr</var> is assigned to it instead. Thus, <var>default-expr</var>
|
|
provides a <em>default value</em> for the variable. The default value expressions
|
|
are evaluated and assigned working from left to right <em>after</em> all of the
|
|
other assignments have been performed.
|
|
|
|
</dd><dt><code>@<var>variable</var></code>
|
|
</dt><dd>
|
|
By analogy with the <code>@</code> syntax in list construction, this variable is
|
|
assigned a list of all of the `leftover' list elements in this part of the list
|
|
after all of the other targets have been filled in. It is assigned the empty
|
|
list if there aren't any elements left over. This is called a <em>rest</em>
|
|
target, since it gets the rest of the elements. There may be at most one rest
|
|
target in each scattering assignment expression.
|
|
</dd></dl>
|
|
|
|
<p>
|
|
If there aren't enough list elements to fill all of the required targets, or if
|
|
there are more than enough to fill all of the required and optional targets but
|
|
there isn't a rest target to take the leftover ones, then <code>E_ARGS</code> is
|
|
raised.
|
|
|
|
|
|
</p><p>
|
|
Here are some examples of how this works. Assume first that the verb
|
|
<code>me:foo()</code> contains the following code:
|
|
|
|
|
|
|
|
</p><pre>b = c = e = 17;
|
|
{a, ?b, ?c = 8, @d, ?e = 9, f} = args;
|
|
return {a, b, c, d, e, f};
|
|
</pre>
|
|
|
|
<p>
|
|
Then the following calls return the given values:
|
|
|
|
|
|
|
|
</p><pre>me:foo(1) error--> E_ARGS
|
|
me:foo(1, 2) => {1, 17, 8, {}, 9, 2}
|
|
me:foo(1, 2, 3) => {1, 2, 8, {}, 9, 3}
|
|
me:foo(1, 2, 3, 4) => {1, 2, 3, {}, 9, 4}
|
|
me:foo(1, 2, 3, 4, 5) => {1, 2, 3, {}, 4, 5}
|
|
me:foo(1, 2, 3, 4, 5, 6) => {1, 2, 3, {4}, 5, 6}
|
|
me:foo(1, 2, 3, 4, 5, 6, 7) => {1, 2, 3, {4, 5}, 6, 7}
|
|
me:foo(1, 2, 3, 4, 5, 6, 7, 8) => {1, 2, 3, {4, 5, 6}, 7, 8}
|
|
</pre>
|
|
|
|
<p>
|
|
Using scattering assignment, the example at the begining of this section could
|
|
be rewritten more simply, reliably, and readably:
|
|
|
|
|
|
|
|
</p><pre>{first, second, ?third = 0} = args;
|
|
</pre>
|
|
|
|
<p>
|
|
It is good MOO programming style to use a scattering assignment at the top of
|
|
nearly every verb, since it shows so clearly just what kinds of arguments the
|
|
verb expects.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC24" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC24">Getting and Setting the Values of Properties</a></h3>
|
|
|
|
<p>
|
|
Usually, one can read the value of a property on an object with a simple
|
|
expression:
|
|
|
|
|
|
|
|
</p><pre><var>expression</var>.<var>name</var>
|
|
</pre>
|
|
|
|
<p>
|
|
<var>Expression</var> must return an object number; if not, <code>E_TYPE</code> is
|
|
raised. If the object with that number does not exist, <code>E_INVIND</code> is
|
|
raised. Otherwise, if the object does not have a property with that name,
|
|
then <code>E_PROPNF</code> is raised. Otherwise, if the named property is not
|
|
readable by the owner of the current verb, then <code>E_PERM</code> is raised.
|
|
Finally, assuming that none of these terrible things happens, the value of the
|
|
named property on the given object is returned.
|
|
|
|
|
|
</p><p>
|
|
I said "usually" in the paragraph above because that simple expression only
|
|
works if the name of the property obeys the same rules as for the names of
|
|
variables (i.e., consists entirely of letters, digits, and underscores, and
|
|
doesn't begin with a digit). Property names are not restricted to this set,
|
|
though. Also, it is sometimes useful to be able to figure out what property
|
|
to read by some computation. For these more general uses, the following
|
|
syntax is also allowed:
|
|
|
|
|
|
|
|
</p><pre><var>expression-1</var>.(<var>expression-2</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
As before, <var>expression-1</var> must return an object number. <var>Expression-2</var>
|
|
must return a string, the name of the property to be read; <code>E_TYPE</code>
|
|
is raised otherwise. Using this syntax, any property can be read,
|
|
regardless of its name.
|
|
|
|
|
|
</p><p>
|
|
Note that, as with almost everything in MOO, case is not significant in the
|
|
names of properties. Thus, the following expressions are all equivalent:
|
|
|
|
|
|
|
|
</p><pre>foo.bar
|
|
foo.Bar
|
|
foo.("bAr")
|
|
</pre>
|
|
|
|
<p>
|
|
The LambdaCore database uses several properties on <code>#0</code>, the <em>system
|
|
object</em>, for various special purposes. For example, the value of
|
|
<code>#0.room</code> is the "generic room" object, <code>#0.exit</code> is the "generic
|
|
exit" object, etc. This allows MOO programs to refer to these useful objects
|
|
more easily (and more readably) than using their object numbers directly. To
|
|
make this usage even easier and more readable, the expression
|
|
|
|
|
|
|
|
</p><pre>$<var>name</var>
|
|
</pre>
|
|
|
|
<p>
|
|
(where <var>name</var> obeys the rules for variable names) is an abbreviation for
|
|
|
|
|
|
|
|
</p><pre>#0.<var>name</var>
|
|
</pre>
|
|
|
|
<p>
|
|
Thus, for example, the value <code>$nothing</code> mentioned earlier is really
|
|
<code>#-1</code>, the value of <code>#0.nothing</code>.
|
|
|
|
|
|
</p><p>
|
|
As with variables, one uses the assignment operator (<samp>`='</samp>) to change the
|
|
value of a property. For example, the expression
|
|
|
|
|
|
|
|
</p><pre>14 + (#27.foo = 17)
|
|
</pre>
|
|
|
|
<p>
|
|
changes the value of the <samp>`foo'</samp> property of the object numbered 27 to be
|
|
17 and then returns 31. Assignments to properties check that the owner of the
|
|
current verb has write permission on the given property, raising
|
|
<code>E_PERM</code> otherwise. Read permission is not required.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC25" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC25">Calling Built-in Functions and Other Verbs</a></h3>
|
|
|
|
<p>
|
|
MOO provides a large number of useful functions for performing a wide
|
|
variety of operations; a complete list, giving their names, arguments,
|
|
and semantics, appears in a separate section later. As an example to
|
|
give you the idea, there is a function named <samp>`length'</samp> that returns
|
|
the length of a given string or list.
|
|
|
|
|
|
</p><p>
|
|
The syntax of a call to a function is as follows:
|
|
|
|
|
|
|
|
</p><pre><var>name</var>(<var>expr-1</var>, <var>expr-2</var>, ..., <var>expr-N</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>name</var> is the name of one of the built-in functions. The
|
|
expressions between the parentheses, called <em>arguments</em>, are each
|
|
evaluated in turn and then given to the named function to use in its
|
|
appropriate way. Most functions require that a specific number of arguments
|
|
be given; otherwise, <code>E_ARGS</code> is raised. Most also require that
|
|
certain of the arguments have certain specified types (e.g., the
|
|
<code>length()</code> function requires a list or a string as its argument);
|
|
<code>E_TYPE</code> is raised if any argument has the wrong type.
|
|
|
|
|
|
</p><p>
|
|
As with list construction, the splicing operator <samp>`@'</samp> can precede
|
|
any argument expression. The value of such an expression must be a
|
|
list; <code>E_TYPE</code> is raised otherwise. The elements of this list
|
|
are passed as individual arguments, in place of the list as a whole.
|
|
|
|
|
|
</p><p>
|
|
Verbs can also call other verbs, usually using this syntax:
|
|
|
|
|
|
|
|
</p><pre><var>expr-0</var>:<var>name</var>(<var>expr-1</var>, <var>expr-2</var>, ..., <var>expr-N</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
<var>Expr-0</var> must return an object number; <code>E_TYPE</code> is raised otherwise.
|
|
If the object with that number does not exist, <code>E_INVIND</code> is raised. If
|
|
this task is too deeply nested in verbs calling verbs calling verbs, then
|
|
<code>E_MAXREC</code> is raised; the default limit is 50 levels, but this can be
|
|
changed from within the database; see the chapter on server assumptions about
|
|
the database for details. If neither the object nor any of its ancestors
|
|
defines a verb matching the given name, <code>E_VERBNF</code> is raised.
|
|
Otherwise, if none of these nasty things happens, the named verb on the given
|
|
object is called; the various built-in variables have the following initial
|
|
values in the called verb:
|
|
|
|
|
|
</p><dl compact="compact">
|
|
|
|
<dt><code>this</code>
|
|
</dt><dd>
|
|
an object, the value of <var>expr-0</var>
|
|
</dd><dt><code>verb</code>
|
|
</dt><dd>
|
|
a string, the <var>name</var> used in calling this verb
|
|
</dd><dt><code>args</code>
|
|
</dt><dd>
|
|
a list, the values of <var>expr-1</var>, <var>expr-2</var>, etc.
|
|
</dd><dt><code>caller</code>
|
|
</dt><dd>
|
|
an object, the value of <code>this</code> in the calling verb
|
|
</dd><dt><code>player</code>
|
|
</dt><dd>
|
|
an object, the same value as it had initially in the calling verb or, if the
|
|
calling verb is running with wizard permissions, the same as the current value
|
|
in the calling verb.
|
|
</dd></dl>
|
|
|
|
<p>
|
|
All other built-in variables (<code>argstr</code>, <code>dobj</code>, etc.) are initialized
|
|
with the same values they have in the calling verb.
|
|
|
|
|
|
</p><p>
|
|
As with the discussion of property references above, I said "usually" at the
|
|
beginning of the previous paragraph because that syntax is only allowed when
|
|
the <var>name</var> follows the rules for allowed variable names. Also as with
|
|
property reference, there is a syntax allowing you to compute the name of the
|
|
verb:
|
|
|
|
|
|
|
|
</p><pre><var>expr-0</var>:(<var>expr-00</var>)(<var>expr-1</var>, <var>expr-2</var>, ..., <var>expr-N</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
The expression <var>expr-00</var> must return a string; <code>E_TYPE</code> is raised
|
|
otherwise.
|
|
|
|
|
|
</p><p>
|
|
The splicing operator (<samp>`@'</samp>) can be used with verb-call arguments,
|
|
too, just as with the arguments to built-in functions.
|
|
|
|
|
|
</p><p>
|
|
In many databases, a number of important verbs are defined on <code>#0</code>, the
|
|
<em>system object</em>. As with the <samp>`$foo'</samp> notation for properties on
|
|
<code>#0</code>, the server defines a special syntax for calling verbs on <code>#0</code>:
|
|
|
|
|
|
|
|
</p><pre>$<var>name</var>(<var>expr-1</var>, <var>expr-2</var>, ..., <var>expr-N</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
(where <var>name</var> obeys the rules for variable names) is an abbreviation for
|
|
|
|
|
|
|
|
</p><pre>#0:<var>name</var>(<var>expr-1</var>, <var>expr-2</var>, ..., <var>expr-N</var>)
|
|
</pre>
|
|
|
|
|
|
|
|
<h3><a name="SEC26" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC26">Catching Errors in Expressions</a></h3>
|
|
|
|
<p>
|
|
It is often useful to be able to <em>catch</em> an error that an expression
|
|
raises, to keep the error from aborting the whole task, and to keep on running
|
|
as if the expression had returned some other value normally. The following
|
|
expression accomplishes this:
|
|
|
|
|
|
|
|
</p><pre>` <var>expr-1</var> ! <var>codes</var> => <var>expr-2</var> '
|
|
</pre>
|
|
|
|
<p>
|
|
<strong>Note:</strong> the open- and close-quotation marks in the previous line are
|
|
really part of the syntax; you must actually type them as part of your MOO
|
|
program for this kind of expression.
|
|
|
|
|
|
</p><p>
|
|
The <var>codes</var> part is either the keyword <code>ANY</code> or else a
|
|
comma-separated list of expressions, just like an argument list. As in an
|
|
argument list, the splicing operator (<samp>`@'</samp>) can be used here. The
|
|
<code>=> <var>expr-2</var></code> part of the error-catching expression is optional.
|
|
|
|
|
|
</p><p>
|
|
First, the <var>codes</var> part is evaluated, yielding a list of error codes that
|
|
should be caught if they're raised; if <var>codes</var> is <code>ANY</code>, then it is
|
|
equivalent to the list of all possible MOO values.
|
|
|
|
|
|
</p><p>
|
|
Next, <var>expr-1</var> is evaluated. If it evaluates normally, without raising an
|
|
error, then its value becomes the value of the entire error-catching
|
|
expression. If evaluating <var>expr-1</var> results in an error being raised, then
|
|
call that error <var>E</var>. If <var>E</var> is in the list resulting from evaluating
|
|
<var>codes</var>, then <var>E</var> is considered <em>caught</em> by this error-catching
|
|
expression. In such a case, if <var>expr-2</var> was given, it is evaluated to get
|
|
the outcome of the entire error-catching expression; if <var>expr-2</var> was
|
|
omitted, then <var>E</var> becomes the value of the entire expression. If <var>E</var>
|
|
is <em>not</em> in the list resulting from <var>codes</var>, then this expression does
|
|
not catch the error at all and it continues to be raised, possibly to be caught
|
|
by some piece of code either surrounding this expression or higher up on the
|
|
verb-call stack.
|
|
|
|
|
|
</p><p>
|
|
Here are some examples of the use of this kind of expression:
|
|
|
|
|
|
|
|
</p><pre>`x + 1 ! E_TYPE => 0'
|
|
</pre>
|
|
|
|
<p>
|
|
Returns <code>x + 1</code> if <code>x</code> is an integer, returns <code>0</code> if <code>x</code> is
|
|
not an integer, and raises <code>E_VARNF</code> if <code>x</code> doesn't have a value.
|
|
|
|
|
|
|
|
</p><pre>`x.y ! E_PROPNF, E_PERM => 17'
|
|
</pre>
|
|
|
|
<p>
|
|
Returns <code>x.y</code> if that doesn't cause an error, <code>17</code> if <code>x</code>
|
|
doesn't have a <code>y</code> property or that property isn't readable, and raises
|
|
some other kind of error (like <code>E_INVIND</code>) if <code>x.y</code> does.
|
|
|
|
|
|
|
|
</p><pre>`1 / 0 ! ANY'
|
|
</pre>
|
|
|
|
<p>
|
|
Returns <code>E_DIV</code>.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC27" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC27">Parentheses and Operator Precedence</a></h3>
|
|
|
|
<p>
|
|
As shown in a few examples above, MOO allows you to use parentheses to make it
|
|
clear how you intend for complex expressions to be grouped. For example, the
|
|
expression
|
|
|
|
|
|
|
|
</p><pre>3 * (4 + 5)
|
|
</pre>
|
|
|
|
<p>
|
|
performs the addition of 4 and 5 before multiplying the result by 3.
|
|
|
|
|
|
</p><p>
|
|
If you leave out the parentheses, MOO will figure out how to group the
|
|
expression according to certain rules. The first of these is that some
|
|
operators have higher <em>precedence</em> than others; operators with higher
|
|
precedence will more tightly bind to their operands than those with lower
|
|
precedence. For example, multiplication has higher precedence than addition;
|
|
thus, if the parentheses had been left out of the expression in the previous
|
|
paragraph, MOO would have grouped it as follows:
|
|
|
|
|
|
|
|
</p><pre>(3 * 4) + 5
|
|
</pre>
|
|
|
|
<p>
|
|
The table below gives the relative precedence of all of the MOO
|
|
operators; operators on higher lines in the table have higher precedence
|
|
and those on the same line have identical precedence:
|
|
|
|
|
|
|
|
</p><pre>! - (without a left operand)
|
|
^
|
|
* / %
|
|
+ -
|
|
== != < <= > >= in
|
|
&& ||
|
|
... ? ... | ... (the conditional expression)
|
|
=
|
|
</pre>
|
|
|
|
<p>
|
|
Thus, the horrendous expression
|
|
|
|
|
|
|
|
</p><pre>x = a < b && c > d + e * f ? w in y | - q - r
|
|
</pre>
|
|
|
|
<p>
|
|
would be grouped as follows:
|
|
|
|
|
|
|
|
</p><pre>x = (((a < b) && (c > (d + (e * f)))) ? (w in y) | ((- q) - r))
|
|
</pre>
|
|
|
|
<p>
|
|
It is best to keep expressions simpler than this and to use parentheses
|
|
liberally to make your meaning clear to other humans.
|
|
|
|
|
|
|
|
|
|
</p><h2><a name="SEC28" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC28">MOO Language Statements</a></h2>
|
|
|
|
<p>
|
|
Statements are MOO constructs that, in contrast to expressions, perform some
|
|
useful, non-value-producing operation. For example, there are several kinds of
|
|
statements, called `looping constructs', that repeatedly perform some set of
|
|
operations. Fortunately, there are many fewer kinds of statements in MOO than
|
|
there are kinds of expressions.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC29" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC29">Errors While Executing Statements</a></h3>
|
|
|
|
<p>
|
|
Statements do not return values, but some kinds of statements can, under
|
|
certain circumstances described below, generate errors. If such an error is
|
|
generated in a verb whose <samp>`d'</samp> (debug) bit is not set, then the error is
|
|
ignored and the statement that generated it is simply skipped; execution
|
|
proceeds with the next statement.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<strong>Note:</strong> this error-ignoring behavior is very error prone, since it
|
|
affects <em>all</em> errors, including ones the programmer may not have
|
|
anticipated. The <samp>`d'</samp> bit exists only for historical reasons; it was once
|
|
the only way for MOO programmers to catch and handle errors. The
|
|
error-catching expression and the <code>try</code>-<code>except</code> statement are far
|
|
better ways of accomplishing the same thing.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
If the <samp>`d'</samp> bit is set, as it usually is, then the error is <em>raised</em>
|
|
and can be caught and handled either by code surrounding the expression in
|
|
question or by verbs higher up on the chain of calls leading to the current
|
|
verb. If the error is not caught, then the server aborts the entire task and,
|
|
by default, prints a message to the current player. See the descriptions of
|
|
the error-catching expression and the <code>try</code>-<code>except</code> statement for
|
|
the details of how errors can be caught, and the chapter on server assumptions
|
|
about the database for details on the handling of uncaught errors.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC30" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC30">Simple Statements</a></h3>
|
|
|
|
<p>
|
|
The simplest kind of statement is the <em>null</em> statement, consisting of just
|
|
a semicolon:
|
|
|
|
|
|
|
|
</p><pre>;
|
|
</pre>
|
|
|
|
<p>
|
|
It doesn't do anything at all, but it does it very quickly.
|
|
|
|
|
|
</p><p>
|
|
The next simplest statement is also one of the most common, the expression
|
|
statement, consisting of any expression followed by a semicolon:
|
|
|
|
|
|
|
|
</p><pre><var>expression</var>;
|
|
</pre>
|
|
|
|
<p>
|
|
The given expression is evaluated and the resulting value is ignored.
|
|
Commonly-used kinds of expressions for such statements include
|
|
assignments and verb calls. Of course, there's no use for such a
|
|
statement unless the evaluation of <var>expression</var> has some side-effect,
|
|
such as changing the value of some variable or property, printing some
|
|
text on someone's screen, etc.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC31" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC31">Statements for Testing Conditions</a></h3>
|
|
|
|
<p>
|
|
The <samp>`if'</samp> statement allows you to decide whether or not to perform some
|
|
statements based on the value of an arbitrary expression:
|
|
|
|
|
|
|
|
</p><pre>if (<var>expression</var>)
|
|
<var>statements</var>
|
|
endif
|
|
</pre>
|
|
|
|
<p>
|
|
<var>Expression</var> is evaluated and, if it returns a true value, the statements
|
|
are executed in order; otherwise, nothing more is done.
|
|
|
|
|
|
</p><p>
|
|
One frequently wants to perform one set of statements if some condition is
|
|
true and some other set of statements otherwise. The optional <samp>`else'</samp>
|
|
phrase in an <samp>`if'</samp> statement allows you to do this:
|
|
|
|
|
|
|
|
</p><pre>if (<var>expression</var>)
|
|
<var>statements-1</var>
|
|
else
|
|
<var>statements-2</var>
|
|
endif
|
|
</pre>
|
|
|
|
<p>
|
|
This statement is executed just like the previous one, except that
|
|
<var>statements-1</var> are executed if <var>expression</var> returns a true value and
|
|
<var>statements-2</var> are executed otherwise.
|
|
|
|
|
|
</p><p>
|
|
Sometimes, one needs to test several conditions in a kind of nested
|
|
fashion:
|
|
|
|
|
|
|
|
</p><pre>if (<var>expression-1</var>)
|
|
<var>statements-1</var>
|
|
else
|
|
if (<var>expression-2</var>)
|
|
<var>statements-2</var>
|
|
else
|
|
if (<var>expression-3</var>)
|
|
<var>statements-3</var>
|
|
else
|
|
<var>statements-4</var>
|
|
endif
|
|
endif
|
|
endif
|
|
</pre>
|
|
|
|
<p>
|
|
Such code can easily become tedious to write and difficult to read. MOO
|
|
provides a somewhat simpler notation for such cases:
|
|
|
|
|
|
|
|
</p><pre>if (<var>expression-1</var>)
|
|
<var>statements-1</var>
|
|
elseif (<var>expression-2</var>)
|
|
<var>statements-2</var>
|
|
elseif (<var>expression-3</var>)
|
|
<var>statements-3</var>
|
|
else
|
|
<var>statements-4</var>
|
|
endif
|
|
</pre>
|
|
|
|
<p>
|
|
Note that <samp>`elseif'</samp> is written as a single word, without any spaces. This
|
|
simpler version has the very same meaning as the original: evaluate
|
|
<var>expression-i</var> for <var>i</var> equal to 1, 2, and 3, in turn, until one of
|
|
them returns a true value; then execute the <var>statements-i</var> associated with
|
|
that expression. If none of the <var>expression-i</var> return a true value, then
|
|
execute <var>statements-4</var>.
|
|
|
|
|
|
</p><p>
|
|
Any number of <samp>`elseif'</samp> phrases can appear, each having this form:
|
|
|
|
|
|
|
|
</p><pre>elseif (<var>expression</var>) <var>statements</var>
|
|
</pre>
|
|
|
|
<p>
|
|
The complete syntax of the <samp>`if'</samp> statement, therefore, is as follows:
|
|
|
|
|
|
|
|
</p><pre>if (<var>expression</var>)
|
|
<var>statements</var>
|
|
<var>zero-or-more-elseif-phrases</var>
|
|
<var>an-optional-else-phrase</var>
|
|
endif
|
|
</pre>
|
|
|
|
|
|
|
|
<h3><a name="SEC32" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC32">Statements for Looping</a></h3>
|
|
|
|
<p>
|
|
MOO provides three different kinds of looping statements, allowing you to have
|
|
a set of statements executed (1) once for each element of a given list, (2)
|
|
once for each integer or object number in a given range, and (3) over and over
|
|
until a given condition stops being true.
|
|
|
|
|
|
</p><p>
|
|
To perform some statements once for each element of a given list, use this
|
|
syntax:
|
|
|
|
|
|
|
|
</p><pre>for <var>variable</var> in (<var>expression</var>)
|
|
<var>statements</var>
|
|
endfor
|
|
</pre>
|
|
|
|
<p>
|
|
The expression is evaluated and should return a list; if it does not,
|
|
<code>E_TYPE</code> is raised. The <var>statements</var> are then executed once for
|
|
each element of that list in turn; each time, the given <var>variable</var> is
|
|
assigned the value of the element in question. For example, consider
|
|
the following statements:
|
|
|
|
|
|
|
|
</p><pre>odds = {1, 3, 5, 7, 9};
|
|
evens = {};
|
|
for n in (odds)
|
|
evens = {@evens, n + 1};
|
|
endfor
|
|
</pre>
|
|
|
|
<p>
|
|
The value of the variable <samp>`evens'</samp> after executing these statements
|
|
is the list
|
|
|
|
|
|
|
|
</p><pre>{2, 4, 6, 8, 10}
|
|
</pre>
|
|
|
|
<p>
|
|
To perform a set of statements once for each integer or object number in a given
|
|
range, use this syntax:
|
|
|
|
|
|
|
|
</p><pre>for <var>variable</var> in [<var>expression-1</var>..<var>expression-2</var>]
|
|
<var>statements</var>
|
|
endfor
|
|
</pre>
|
|
|
|
<p>
|
|
The two expressions are evaluated in turn and should either both return integers
|
|
or both return object numbers; <code>E_TYPE</code> is raised otherwise. The
|
|
<var>statements</var> are then executed once for each integer (or object number, as
|
|
appropriate) greater than or equal to the value of <var>expression-1</var> and less
|
|
than or equal to the result of <var>expression-2</var>, in increasing order. Each
|
|
time, the given variable is assigned the integer or object number in question.
|
|
For example, consider the following statements:
|
|
|
|
|
|
|
|
</p><pre>evens = {};
|
|
for n in [1..5]
|
|
evens = {@evens, 2 * n};
|
|
endfor
|
|
</pre>
|
|
|
|
<p>
|
|
The value of the variable <samp>`evens'</samp> after executing these statements
|
|
is just as in the previous example: the list
|
|
|
|
|
|
|
|
</p><pre>{2, 4, 6, 8, 10}
|
|
</pre>
|
|
|
|
<p>
|
|
The following loop over object numbers prints out the number and name of every
|
|
valid object in the database:
|
|
|
|
|
|
|
|
</p><pre>for o in [#0..max_object()]
|
|
if (valid(o))
|
|
notify(player, tostr(o, ": ", o.name));
|
|
endif
|
|
endfor
|
|
</pre>
|
|
|
|
<p>
|
|
The final kind of loop in MOO executes a set of statements repeatedly as long
|
|
as a given condition remains true:
|
|
|
|
|
|
|
|
</p><pre>while (<var>expression</var>)
|
|
<var>statements</var>
|
|
endwhile
|
|
</pre>
|
|
|
|
<p>
|
|
The expression is evaluated and, if it returns a true value, the
|
|
<var>statements</var> are executed; then, execution of the <samp>`while'</samp> statement
|
|
begins all over again with the evaluation of the expression. That is,
|
|
execution alternates between evaluating the expression and executing the
|
|
statements until the expression returns a false value. The following
|
|
example code has precisely the same effect as the loop just shown above:
|
|
|
|
|
|
|
|
</p><pre>evens = {};
|
|
n = 1;
|
|
while (n <= 5)
|
|
evens = {@evens, 2 * n};
|
|
n = n + 1;
|
|
endwhile
|
|
</pre>
|
|
|
|
|
|
<blockquote>
|
|
<p>
|
|
<em>Fine point:</em> It is also possible to give a `name' to a <samp>`while'</samp>
|
|
loop, using this syntax:
|
|
|
|
|
|
</p><pre>while <var>name</var> (<var>expression</var>)
|
|
<var>statements</var>
|
|
endwhile
|
|
</pre>
|
|
|
|
<p>
|
|
which has precisely the same effect as
|
|
|
|
|
|
|
|
</p><pre>while (<var>name</var> = <var>expression</var>)
|
|
<var>statements</var>
|
|
endwhile
|
|
</pre>
|
|
|
|
<p>
|
|
This naming facility is only really useful in conjunction with the <samp>`break'</samp>
|
|
and <samp>`continue'</samp> statements, described in the next section.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
With each kind of loop, it is possible that the statements in the body of the
|
|
loop will never be executed at all. For iteration over lists, this happens
|
|
when the list returned by the expression is empty. For iteration on integers,
|
|
it happens when <var>expression-1</var> returns a larger integer than
|
|
<var>expression-2</var>. Finally, for the <samp>`while'</samp> loop, it happens if the
|
|
expression returns a false value the very first time it is evaluated.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC33" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC33">Terminating One or All Iterations of a Loop</a></h3>
|
|
|
|
<p>
|
|
Sometimes, it is useful to exit a loop before it finishes all of its
|
|
iterations. For example, if the loop is used to search for a particular kind
|
|
of element of a list, then it might make sense to stop looping as soon as the
|
|
right kind of element is found, even if there are more elements yet to see.
|
|
The <samp>`break'</samp> statement is used for this purpose; it has the form
|
|
|
|
|
|
|
|
</p><pre>break;
|
|
</pre>
|
|
|
|
<p>
|
|
or
|
|
|
|
|
|
|
|
</p><pre>break <var>name</var>;
|
|
</pre>
|
|
|
|
<p>
|
|
Each <samp>`break'</samp> statement indicates a specific surrounding loop; if
|
|
<var>name</var> is not given, the statement refers to the innermost one. If it is
|
|
given, <var>name</var> must be the name appearing right after the <samp>`for'</samp> or
|
|
<samp>`while'</samp> keyword of the desired enclosing loop. When the <samp>`break'</samp>
|
|
statement is executed, the indicated loop is immediately terminated and
|
|
executing continues just as if the loop had completed its iterations normally.
|
|
|
|
|
|
</p><p>
|
|
MOO also allows you to terminate just the current iteration of a loop, making
|
|
it immediately go on to the next one, if any. The <samp>`continue'</samp> statement
|
|
does this; it has precisely the same forms as the <samp>`break'</samp> statement:
|
|
|
|
|
|
|
|
</p><pre>continue;
|
|
</pre>
|
|
|
|
<p>
|
|
or
|
|
|
|
|
|
|
|
</p><pre>continue <var>name</var>;
|
|
</pre>
|
|
|
|
|
|
|
|
<h3><a name="SEC34" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC34">Returning a Value from a Verb</a></h3>
|
|
|
|
<p>
|
|
The MOO program in a verb is just a sequence of statements. Normally, when
|
|
the verb is called, those statements are simply executed in order and then the
|
|
integer 0 is returned as the value of the verb-call expression. Using the
|
|
<samp>`return'</samp> statement, one can change this behavior. The <samp>`return'</samp>
|
|
statement has one of the following two forms:
|
|
|
|
|
|
|
|
</p><pre>return;
|
|
</pre>
|
|
|
|
<p>
|
|
or
|
|
|
|
|
|
|
|
</p><pre>return <var>expression</var>;
|
|
</pre>
|
|
|
|
<p>
|
|
When it is executed, execution of the current verb is terminated immediately
|
|
after evaluating the given <var>expression</var>, if any. The verb-call expression
|
|
that started the execution of this verb then returns either the value of
|
|
<var>expression</var> or the integer 0, if no <var>expression</var> was provided.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC35" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC35">Handling Errors in Statements</a></h3>
|
|
|
|
<p>
|
|
Normally, whenever a piece of MOO code raises an error, the entire task is
|
|
aborted and a message printed to the user. Often, such errors can be
|
|
anticipated in advance by the programmer and code written to deal with them in
|
|
a more graceful manner. The <code>try</code>-<code>except</code> statement allows you to
|
|
do this; the syntax is as follows:
|
|
|
|
|
|
|
|
</p><pre>try
|
|
<var>statements-0</var>
|
|
except <var>variable-1</var> (<var>codes-1</var>)
|
|
<var>statements-1</var>
|
|
except <var>variable-2</var> (<var>codes-2</var>)
|
|
<var>statements-2</var>
|
|
...
|
|
endtry
|
|
</pre>
|
|
|
|
<p>
|
|
where the <var>variable</var>s may be omitted and each <var>codes</var> part is either
|
|
the keyword <code>ANY</code> or else a comma-separated list of expressions, just like
|
|
an argument list. As in an argument list, the splicing operator (<samp>`@'</samp>)
|
|
can be used here. There can be anywhere from 1 to 255 <code>except</code> clauses.
|
|
|
|
|
|
</p><p>
|
|
First, each <var>codes</var> part is evaluated, yielding a list of error codes that
|
|
should be caught if they're raised; if a <var>codes</var> is <code>ANY</code>, then it is
|
|
equivalent to the list of all possible MOO values.
|
|
|
|
|
|
</p><p>
|
|
Next, <var>statements-0</var> is executed; if it doesn't raise an error, then that's
|
|
all that happens for the entire <code>try</code>-<code>except</code> statement. Otherwise,
|
|
let <var>E</var> be the error it raises. From top to bottom, <var>E</var> is searched
|
|
for in the lists resulting from the various <var>codes</var> parts; if it isn't
|
|
found in any of them, then it continues to be raised, possibly to be caught by
|
|
some piece of code either surrounding this <code>try</code>-<code>except</code> statement
|
|
or higher up on the verb-call stack.
|
|
|
|
|
|
</p><p>
|
|
If <var>E</var> is found first in <var>codes-i</var>, then <var>variable-i</var> (if provided)
|
|
is assigned a value containing information about the error being raised and
|
|
<var>statements-i</var> is executed. The value assigned to <var>variable-i</var> is a
|
|
list of four elements:
|
|
|
|
</p><pre>{<var>code</var>, <var>message</var>, <var>value</var>, <var>traceback</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>code</var> is <var>E</var>, the error being raised, <var>message</var> and
|
|
<var>value</var> are as provided by the code that raised the error, and
|
|
<var>traceback</var> is a list like that returned by the <samp>`callers()'</samp> function,
|
|
including line numbers. The <var>traceback</var> list contains entries for every
|
|
verb from the one that raised the error through the one containing this
|
|
<code>try</code>-<code>except</code> statement.
|
|
|
|
|
|
</p><p>
|
|
Unless otherwise mentioned, all of the built-in errors raised by expressions,
|
|
statements, and functions provide <code>tostr(<var>code</var>)</code> as <var>message</var> and
|
|
zero as <var>value</var>.
|
|
|
|
|
|
</p><p>
|
|
Here's an example of the use of this kind of statement:
|
|
|
|
|
|
|
|
</p><pre>try
|
|
result = object:(command)(@arguments);
|
|
player:tell("=> ", toliteral(result));
|
|
except v (ANY)
|
|
tb = v[4];
|
|
if (length(tb) == 1)
|
|
player:tell("** Illegal command: ", v[2]);
|
|
else
|
|
top = tb[1];
|
|
tb[1..1] = {};
|
|
player:tell(top[1], ":", top[2], ", line ", top[6], ":",
|
|
v[2]);
|
|
for fr in (tb)
|
|
player:tell("... called from ", fr[1], ":", fr[2],
|
|
", line ", fr[6]);
|
|
endfor
|
|
player:tell("(End of traceback)");
|
|
endif
|
|
endtry
|
|
</pre>
|
|
|
|
|
|
|
|
<h3><a name="SEC36" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC36">Cleaning Up After Errors</a></h3>
|
|
|
|
<p>
|
|
Whenever an error is raised, it is usually the case that at least some MOO code
|
|
gets skipped over and never executed. Sometimes, it's important that a piece
|
|
of code <em>always</em> be executed, whether or not an error is raised. Use the
|
|
<code>try</code>-<code>finally</code> statement for these cases; it has the following
|
|
syntax:
|
|
|
|
|
|
|
|
</p><pre>try
|
|
<var>statements-1</var>
|
|
finally
|
|
<var>statements-2</var>
|
|
endtry
|
|
</pre>
|
|
|
|
<p>
|
|
First, <var>statements-1</var> is executed; if it completes without raising an
|
|
error, returning from this verb, or terminating the current iteration of a
|
|
surrounding loop (we call these possibilities <em>transferring control</em>), then
|
|
<var>statements-2</var> is executed and that's all that happens for the entire
|
|
<code>try</code>-<code>finally</code> statement.
|
|
|
|
|
|
</p><p>
|
|
Otherwise, the process of transferring control is interrupted and
|
|
<var>statments-2</var> is executed. If <var>statements-2</var> itself completes without
|
|
transferring control, then the interrupted control transfer is resumed just
|
|
where it left off. If <var>statements-2</var> does transfer control, then the
|
|
interrupted transfer is simply forgotten in favor of the new one.
|
|
|
|
|
|
</p><p>
|
|
In short, this statement ensures that <var>statements-2</var> is executed after
|
|
control leaves <var>statements-1</var> for whatever reason; it can thus be used to
|
|
make sure that some piece of cleanup code is run even if <var>statements-1</var>
|
|
doesn't simply run normally to completion.
|
|
|
|
|
|
</p><p>
|
|
Here's an example:
|
|
|
|
|
|
|
|
</p><pre>try
|
|
start = time();
|
|
object:(command)(@arguments);
|
|
finally
|
|
end = time();
|
|
this:charge_user_for_seconds(player, end - start);
|
|
endtry
|
|
</pre>
|
|
|
|
|
|
|
|
<h3><a name="SEC37" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC37">Executing Statements at a Later Time</a></h3>
|
|
|
|
<p>
|
|
It is sometimes useful to have some sequence of statements execute at a later
|
|
time, without human intervention. For example, one might implement an object
|
|
that, when thrown into the air, eventually falls back to the ground; the
|
|
<samp>`throw'</samp> verb on that object should arrange to print a message about the
|
|
object landing on the ground, but the message shouldn't be printed until some
|
|
number of seconds have passed.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`fork'</samp> statement is intended for just such situations and has the
|
|
following syntax:
|
|
|
|
|
|
|
|
</p><pre>fork (<var>expression</var>)
|
|
<var>statements</var>
|
|
endfork
|
|
</pre>
|
|
|
|
<p>
|
|
The <samp>`fork'</samp> statement first executes the expression, which must return a
|
|
integer; call that integer <var>n</var>. It then creates a new MOO <em>task</em> that
|
|
will, after at least <var>n</var> seconds, execute the statements. When the new
|
|
task begins, all variables will have the values they had at the time the
|
|
<samp>`fork'</samp> statement was executed. The task executing the <samp>`fork'</samp>
|
|
statement immediately continues execution. The concept of tasks is discussed
|
|
in detail in the next section.
|
|
|
|
|
|
</p><p>
|
|
By default, there is no limit to the number of tasks any player may fork, but
|
|
such a limit can be imposed from within the database. See the chapter on
|
|
server assumptions about the database for details.
|
|
|
|
|
|
</p><p>
|
|
Occasionally, one would like to be able to kill a forked task before it even
|
|
starts; for example, some player might have caught the object that was thrown
|
|
into the air, so no message should be printed about it hitting the ground. If
|
|
a variable name is given after the <samp>`fork'</samp> keyword, like this:
|
|
|
|
|
|
|
|
</p><pre>fork <var>name</var> (<var>expression</var>)
|
|
<var>statements</var>
|
|
endfork
|
|
</pre>
|
|
|
|
<p>
|
|
then that variable is assigned the <em>task ID</em> of the newly-created task.
|
|
The value of this variable is visible both to the task executing the fork
|
|
statement and to the statements in the newly-created task. This ID can be
|
|
passed to the <code>kill_task()</code> function to keep the task from running and
|
|
will be the value of <code>task_id()</code> once the task begins execution.
|
|
|
|
|
|
|
|
|
|
</p><h2><a name="SEC38" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC38">MOO Tasks</a></h2>
|
|
|
|
<p>
|
|
A <em>task</em> is an execution of a MOO program. There are five kinds of tasks
|
|
in LambdaMOO:
|
|
|
|
|
|
|
|
</p><ul>
|
|
<li>
|
|
|
|
Every time a player types a command, a task is created to execute that
|
|
command; we call these <em>command tasks</em>.
|
|
</li><li>
|
|
|
|
Whenever a player connects or disconnects from the MOO, the server starts a
|
|
task to do whatever processing is necessary, such as printing out
|
|
<samp>`Munchkin has connected'</samp> to all of the players in the same room; these
|
|
are called <em>server tasks</em>.
|
|
</li><li>
|
|
|
|
The <samp>`fork'</samp> statement in the programming language creates a task whose
|
|
execution is delayed for at least some given number of seconds; these are
|
|
<em>forked tasks</em>.
|
|
</li><li>
|
|
|
|
The <code>suspend()</code> function suspends the execution of the current task. A
|
|
snapshot is taken of whole state of the execution, and the execution will be
|
|
resumed later. These are called <em>suspended tasks</em>.
|
|
</li><li>
|
|
|
|
The <code>read()</code> function also suspends the execution of the current task, in
|
|
this case waiting for the player to type a line of input. When the line is
|
|
received, the task resumes with the <code>read()</code> function returning the input
|
|
line as result. These are called <em>reading tasks</em>.
|
|
</li></ul>
|
|
|
|
<p>
|
|
The last three kinds of tasks above are collectively known as <em>queued
|
|
tasks</em> or <em>background tasks</em>, since they may not run immediately.
|
|
|
|
|
|
</p><p>
|
|
To prevent a maliciously- or incorrectly-written MOO program from running
|
|
forever and monopolizing the server, limits are placed on the running time of
|
|
every task. One limit is that no task is allowed to run longer than a certain
|
|
number of seconds; command and server tasks get five seconds each while other
|
|
tasks get only three seconds. This limit is, in practice, rarely reached. The
|
|
reason is that there is also a limit on the number of operations a task may
|
|
execute.
|
|
|
|
|
|
</p><p>
|
|
The server counts down <em>ticks</em> as any task executes. Roughly speaking, it
|
|
counts one tick for every expression evaluation (other than variables and
|
|
literals), one for every <samp>`if'</samp>, <samp>`fork'</samp> or <samp>`return'</samp> statement, and
|
|
one for every iteration of a loop. If the count gets all the way down to zero,
|
|
the task is immediately and unceremoniously aborted. By default, command and
|
|
server tasks begin with an store of 30,000 ticks; this is enough for almost all
|
|
normal uses. Forked, suspended, and reading tasks are allotted 15,000 ticks
|
|
each.
|
|
|
|
|
|
</p><p>
|
|
These limits on seconds and ticks may be changed from within the database, as
|
|
can the behavior of the server after it aborts a task for running out; see the
|
|
chapter on server assumptions about the database for details.
|
|
|
|
|
|
</p><p>
|
|
Because queued tasks may exist for long periods of time before they begin
|
|
execution, there are functions to list the ones that you own and to kill them
|
|
before they execute. These functions, among others, are discussed in the
|
|
following section.
|
|
|
|
|
|
|
|
|
|
</p><h2><a name="SEC39" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC39">Built-in Functions</a></h2>
|
|
|
|
<p>
|
|
There are a large number of built-in functions available for use by MOO
|
|
programmers. Each one is discussed in detail in this section. The
|
|
presentation is broken up into subsections by grouping together functions with
|
|
similar or related uses.
|
|
|
|
|
|
</p><p>
|
|
For most functions, the expected types of the arguments are given; if the
|
|
actual arguments are not of these types, <code>E_TYPE</code> is raised. Some
|
|
arguments can be of any type at all; in such cases, no type specification is
|
|
given for the argument. Also, for most functions, the type of the result of
|
|
the function is given. Some functions do not return a useful result; in such
|
|
cases, the specification <samp>`none'</samp> is used. A few functions can potentially
|
|
return any type of value at all; in such cases, the specification <samp>`value'</samp>
|
|
is used.
|
|
|
|
|
|
</p><p>
|
|
Most functions take a certain fixed number of required arguments and, in some
|
|
cases, one or two optional arguments. If a function is called with too many or
|
|
too few arguments, <code>E_ARGS</code> is raised.
|
|
|
|
|
|
</p><p>
|
|
Functions are always called by the program for some verb; that program is
|
|
running with the permissions of some player, usually the owner of the verb in
|
|
question (it is not always the owner, though; wizards can use
|
|
<code>set_task_perms()</code> to change the permissions `on the fly'). In the
|
|
function descriptions below, we refer to the player whose permissions are being
|
|
used as the <em>programmer</em>.
|
|
|
|
|
|
</p><p>
|
|
Many built-in functions are described below as raising <code>E_PERM</code> unless
|
|
the programmer meets certain specified criteria. It is possible to restrict
|
|
use of any function, however, so that only wizards can use it; see the chapter
|
|
on server assumptions about the database for details.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC40" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC40">Object-Oriented Programming</a></h3>
|
|
|
|
<p>
|
|
One of the most important facilities in an object-oriented programming language
|
|
is ability for a child object to make use of a parent's implementation of some
|
|
operation, even when the child provides its own definition for that operation.
|
|
The <code>pass()</code> function provides this facility in MOO.
|
|
|
|
|
|
</p><p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> value <b>pass</b> <i>(<var>arg</var>, ...)</i>
|
|
</dt><dd><a name="IDX1"></a>
|
|
Often, it is useful for a child object to define a verb that <em>augments</em>
|
|
the behavior of a verb on its parent object. For example, in the LambdaCore
|
|
database, the root object (which is an ancestor of every other object) defines
|
|
a verb called <samp>`description'</samp> that simply returns the value of
|
|
<code>this.description</code>; this verb is used by the implementation of the
|
|
<code>look</code> command. In many cases, a programmer would like the description of
|
|
some object to include some non-constant part; for example, a sentence about
|
|
whether or not the object was `awake' or `sleeping'. This sentence should be
|
|
added onto the end of the normal description. The programmer would like to
|
|
have a means of calling the normal <code>description</code> verb and then appending
|
|
the sentence onto the end of that description. The function <samp>`pass()'</samp> is
|
|
for exactly such situations.
|
|
|
|
|
|
<p>
|
|
<code>pass</code> calls the verb with the same name as the current verb but as
|
|
defined on the parent of the object that defines the current verb. The
|
|
arguments given to <code>pass</code> are the ones given to the called verb and the
|
|
returned value of the called verb is returned from the call to <code>pass</code>.
|
|
The initial value of <code>this</code> in the called verb is the same as in the
|
|
calling verb.
|
|
|
|
|
|
</p><p>
|
|
Thus, in the example above, the child-object's <code>description</code> verb might
|
|
have the following implementation:
|
|
|
|
|
|
|
|
</p><pre>return pass() + " It is " + (this.awake ? "awake." | "sleeping.");
|
|
</pre>
|
|
|
|
<p>
|
|
That is, it calls its parent's <code>description</code> verb and then appends to the
|
|
result a sentence whose content is computed based on the value of a property on
|
|
the object.
|
|
|
|
|
|
</p><p>
|
|
In almost all cases, you will want to call <samp>`pass()'</samp> with the same
|
|
arguments as were given to the current verb. This is easy to write in MOO;
|
|
just call <code>pass(@args)</code>.
|
|
</p></dd></dl>
|
|
|
|
|
|
|
|
|
|
<h3><a name="SEC41" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC41">Manipulating MOO Values</a></h3>
|
|
|
|
<p>
|
|
There are several functions for performing primitive operations on MOO values,
|
|
and they can be cleanly split into two kinds: those that do various very
|
|
general operations that apply to all types of values, and those that are
|
|
specific to one particular type. There are so many operations concerned with
|
|
objects that we do not list them in this section but rather give them their own
|
|
section following this one.
|
|
|
|
|
|
|
|
|
|
</p><h4><a name="SEC42" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC42">General Operations Applicable to all Values</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>typeof</b> <i>(<var>value</var>)</i>
|
|
</dt><dd><a name="IDX2"></a>
|
|
Takes any MOO value and returns an integer representing the type of <var>value</var>.
|
|
The result is the same as the initial value of one of these built-in variables:
|
|
<code>INT</code>, <code>FLOAT</code>, <code>STR</code>, <code>LIST</code>, <code>OBJ</code>, or <code>ERR</code>.
|
|
Thus, one usually writes code like this:
|
|
|
|
|
|
|
|
<pre>if (typeof(x) == LIST) ...
|
|
</pre>
|
|
|
|
<p>
|
|
and not like this:
|
|
|
|
|
|
|
|
</p><pre>if (typeof(x) == 3) ...
|
|
</pre>
|
|
|
|
<p>
|
|
because the former is much more readable than the latter.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>tostr</b> <i>(<var>value</var>, ...)</i>
|
|
</dt><dd><a name="IDX3"></a>
|
|
Converts all of the given MOO values into strings and returns the concatenation
|
|
of the results.
|
|
|
|
|
|
|
|
<pre>tostr(17) => "17"
|
|
tostr(1.0/3.0) => "0.333333333333333"
|
|
tostr(#17) => "#17"
|
|
tostr("foo") => "foo"
|
|
tostr({1, 2}) => "{list}"
|
|
tostr(E_PERM) => "Permission denied"
|
|
tostr("3 + 4 = ", 3 + 4) => "3 + 4 = 7"
|
|
</pre>
|
|
|
|
<p>
|
|
Note that <code>tostr()</code> does not do a good job of converting lists into
|
|
strings; all lists, including the empty list, are converted into the string
|
|
<code>"{list}"</code>. The function <code>toliteral()</code>, below, is better for this
|
|
purpose.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>toliteral</b> <i>(<var>value</var>)</i>
|
|
</dt><dd><a name="IDX4"></a>
|
|
Returns a string containing a MOO literal expression that, when evaluated,
|
|
would be equal to <var>value</var>.
|
|
|
|
|
|
|
|
<pre>toliteral(17) => "17"
|
|
toliteral(1.0/3.0) => "0.333333333333333"
|
|
toliteral(#17) => "#17"
|
|
toliteral("foo") => "\"foo\""
|
|
toliteral({1, 2}) => "{1, 2}"
|
|
toliteral(E_PERM) => "E_PERM"
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>toint</b> <i>(<var>value</var>)</i>
|
|
</dt><dd><a name="IDX5"></a>
|
|
</dd><dt><u>Function:</u> int <b>tonum</b> <i>(<var>value</var>)</i>
|
|
</dt><dd><a name="IDX6"></a>
|
|
Converts the given MOO value into an integer and returns that integer.
|
|
Floating-point numbers are rounded toward zero, truncating their fractional
|
|
parts. Object numbers are converted into the equivalent integers. Strings are
|
|
parsed as the decimal encoding of a real number which is then converted to an
|
|
integer. Errors are converted into integers obeying the same ordering (with
|
|
respect to <code><=</code> as the errors themselves. <code>Toint()</code> raises
|
|
<code>E_TYPE</code> if <var>value</var> is a list. If <var>value</var> is a string but the
|
|
string does not contain a syntactically-correct number, then <code>toint()</code>
|
|
returns 0.
|
|
|
|
|
|
|
|
<pre>toint(34.7) => 34
|
|
toint(-34.7) => -34
|
|
toint(#34) => 34
|
|
toint("34") => 34
|
|
toint("34.7") => 34
|
|
toint(" - 34 ") => -34
|
|
toint(E_TYPE) => 1
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> obj <b>toobj</b> <i>(<var>value</var>)</i>
|
|
</dt><dd><a name="IDX7"></a>
|
|
Converts the given MOO value into an object number and returns that object
|
|
number. The conversions are very similar to those for <code>toint()</code> except
|
|
that for strings, the number <em>may</em> be preceded by <samp>`#'</samp>.
|
|
|
|
|
|
|
|
<pre>toobj("34") => #34
|
|
toobj("#34") => #34
|
|
toobj("foo") => #0
|
|
toobj({1, 2}) error--> E_TYPE
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>tofloat</b> <i>(<var>value</var>)</i>
|
|
</dt><dd><a name="IDX8"></a>
|
|
Converts the given MOO value into a floating-point number and returns that
|
|
number. Integers and object numbers are converted into the corresponding
|
|
integral floating-point numbers. Strings are parsed as the decimal encoding of
|
|
a real number which is then represented as closely as possible as a
|
|
floating-point number. Errors are first converted to integers as in
|
|
<code>toint()</code> and then converted as integers are. <code>Tofloat()</code> raises
|
|
<code>E_TYPE</code> if <var>value</var> is a list. If <var>value</var> is a string but the
|
|
string does not contain a syntactically-correct number, then <code>tofloat()</code>
|
|
returns 0.
|
|
|
|
|
|
|
|
<pre>tofloat(34) => 34.0
|
|
tofloat(#34) => 34.0
|
|
tofloat("34") => 34.0
|
|
tofloat("34.7") => 34.7
|
|
tofloat(E_TYPE) => 1.0
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>equal</b> <i>(<var>value1</var>, <var>value2</var>)</i>
|
|
</dt><dd><a name="IDX9"></a>
|
|
Returns true if <var>value1</var> is completely indistinguishable from <var>value2</var>.
|
|
This is much the same operation as "<code><var>value1</var> == <var>value2</var></code>"
|
|
except that, unlike <code>==</code>, the <code>equal()</code> function does not treat
|
|
upper- and lower-case characters in strings as equal.
|
|
|
|
|
|
|
|
<pre>"Foo" == "foo" => 1
|
|
equal("Foo", "foo") => 0
|
|
equal("Foo", "Foo") => 1
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>value_bytes</b> <i>(<var>value</var>)</i>
|
|
</dt><dd><a name="IDX10"></a>
|
|
Returns the number of bytes of the server's memory required to store the given
|
|
<var>value</var>.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>value_hash</b> <i>(<var>value</var>)</i>
|
|
</dt><dd><a name="IDX11"></a>
|
|
Returns the same string as <code>string_hash(toliteral(<var>value</var>))</code>; see the
|
|
description of <code>string_hash()</code> for details.
|
|
</dd></dl>
|
|
|
|
|
|
|
|
|
|
<h4><a name="SEC43" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC43">Operations on Numbers</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>random</b> <i>([int <var>mod</var>])</i>
|
|
</dt><dd><a name="IDX12"></a>
|
|
<var>mod</var> must be a positive integer; otherwise, <code>E_INVARG</code> is raised. An
|
|
integer is chosen randomly from the range <code>[1..<var>mod</var>]</code> and returned.
|
|
If <var>mod</var> is not provided, it defaults to the largest MOO integer,
|
|
2147483647.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> num <b>min</b> <i>(num <var>x</var>, ...)</i>
|
|
</dt><dd><a name="IDX13"></a>
|
|
</dd><dt><u>Function:</u> num <b>max</b> <i>(num <var>x</var>, ...)</i>
|
|
</dt><dd><a name="IDX14"></a>
|
|
These two functions return the smallest or largest of their arguments,
|
|
respectively. All of the arguments must be numbers of the same kind (i.e.,
|
|
either integer or floating-point); otherwise <code>E_TYPE</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> num <b>abs</b> <i>(num <var>x</var>)</i>
|
|
</dt><dd><a name="IDX15"></a>
|
|
Returns the absolute value of <var>x</var>. If <var>x</var> is negative, then the result
|
|
is <code>-<var>x</var></code>; otherwise, the result is <var>x</var>. The number <var>x</var> can
|
|
be either integer or floating-point; the result is of the same kind.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>floatstr(float</b> <i><var>x</var>, int <var>precision</var> [, <var>scientific</var>])</i>
|
|
</dt><dd><a name="IDX16"></a>
|
|
Converts <var>x</var> into a string with more control than provided by either
|
|
<code>tostr()</code> or <code>toliteral()</code>. <var>Precision</var> is the number of digits
|
|
to appear to the right of the decimal point, capped at 4 more than the maximum
|
|
available precision, a total of 19 on most machines; this makes it possible to
|
|
avoid rounding errors if the resulting string is subsequently read back as a
|
|
floating-point value. If <var>scientific</var> is false or not provided, the result
|
|
is a string in the form <code>"MMMMMMM.DDDDDD"</code>, preceded by a minus sign if
|
|
and only if <var>x</var> is negative. If <var>scientific</var> is provided and true, the
|
|
result is a string in the form <code>"M.DDDDDDe+EEE"</code>, again preceded by a
|
|
minus sign if and only if <var>x</var> is negative.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>sqrt</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX17"></a>
|
|
Returns the square root of <var>x</var>. Raises <code>E_INVARG</code> if <var>x</var> is
|
|
negative.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>sin</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX18"></a>
|
|
</dd><dt><u>Function:</u> float <b>cos</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX19"></a>
|
|
</dd><dt><u>Function:</u> float <b>tan</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX20"></a>
|
|
Returns the sine, cosine, or tangent of <var>x</var>, respectively.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>asin</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX21"></a>
|
|
</dd><dt><u>Function:</u> float <b>acos</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX22"></a>
|
|
Returns the arc-sine or arc-cosine (inverse sine or cosine) of <var>x</var>, in the
|
|
range <code>[-pi/2..pi/2]</code> or <code>[0..pi]</code>, respectively. Raises
|
|
<code>E_INVARG</code> if <var>x</var> is outside the range <code>[-1.0..1.0]</code>.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>atan</b> <i>(float <var>y</var> [, float <var>x</var>])</i>
|
|
</dt><dd><a name="IDX23"></a>
|
|
Returns the arc-tangent (inverse tangent) of <var>y</var> in the range
|
|
<code>[-pi/2..pi/2]</code> if <var>x</var> is not provided, or of <code><var>y</var>/<var>x</var></code>
|
|
in the range <code>[-pi..pi]</code> if <var>x</var> is provided.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>sinh</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX24"></a>
|
|
</dd><dt><u>Function:</u> float <b>cosh</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX25"></a>
|
|
</dd><dt><u>Function:</u> float <b>tanh</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX26"></a>
|
|
Returns the hyperbolic sine, cosine, or tangent of <var>x</var>, respectively.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>exp</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX27"></a>
|
|
Returns <var>e</var> raised to the power of <var>x</var>.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>log</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX28"></a>
|
|
</dd><dt><u>Function:</u> float <b>log10</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX29"></a>
|
|
Returns the natural or base 10 logarithm of <var>x</var>. Raises <code>E_INVARG</code> if
|
|
<var>x</var> is not positive.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>ceil</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX30"></a>
|
|
Returns the smallest integer not less than <var>x</var>, as a floating-point number.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>floor</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX31"></a>
|
|
Returns the largest integer not greater than <var>x</var>, as a floating-point
|
|
number.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> float <b>trunc</b> <i>(float <var>x</var>)</i>
|
|
</dt><dd><a name="IDX32"></a>
|
|
Returns the integer obtained by truncating <var>x</var> at the decimal point, as a
|
|
floating-point number. For negative <var>x</var>, this is equivalent to
|
|
<code>ceil()</code>; otherwise it is equivalent to <code>floor()</code>.
|
|
</dd></dl>
|
|
|
|
|
|
|
|
|
|
<h4><a name="SEC44" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC44">Operations on Strings</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>length</b> <i>(str <var>string</var>)</i>
|
|
</dt><dd><a name="IDX33"></a>
|
|
Returns the number of characters in <var>string</var>. It is also permissible to
|
|
pass a list to <code>length()</code>; see the description in the next section.
|
|
|
|
|
|
|
|
<pre>length("foo") => 3
|
|
length("") => 0
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>strsub</b> <i>(str <var>subject</var>, str <var>what</var>, str <var>with</var> [, <var>case-matters</var>])</i>
|
|
</dt><dd><a name="IDX34"></a>
|
|
Replaces all occurrences in <var>subject</var> of <var>what</var> with <var>with</var>,
|
|
performing string substitution. The occurrences are found from left to right
|
|
and all substitutions happen simultaneously. By default, occurrences of
|
|
<var>what</var> are searched for while ignoring the upper/lower case distinction.
|
|
If <var>case-matters</var> is provided and true, then case is treated as significant
|
|
in all comparisons.
|
|
|
|
|
|
|
|
<pre>strsub("%n is a fink.", "%n", "Fred") => "Fred is a fink."
|
|
strsub("foobar", "OB", "b") => "fobar"
|
|
strsub("foobar", "OB", "b", 1) => "foobar"
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>index</b> <i>(str <var>str1</var>, str <var>str2</var> [, <var>case-matters</var>])</i>
|
|
</dt><dd><a name="IDX35"></a>
|
|
</dd><dt><u>Function:</u> int <b>rindex</b> <i>(str <var>str1</var>, str <var>str2</var> [, <var>case-matters</var>])</i>
|
|
</dt><dd><a name="IDX36"></a>
|
|
The function <code>index()</code> (<code>rindex()</code>) returns the index of the first
|
|
character of the first (last) occurrence of <var>str2</var> in <var>str1</var>, or zero
|
|
if <var>str2</var> does not occur in <var>str1</var> at all. By default the search for
|
|
an occurrence of <var>str2</var> is done while ignoring the upper/lower case
|
|
distinction. If <var>case-matters</var> is provided and true, then case is treated
|
|
as significant in all comparisons.
|
|
|
|
|
|
|
|
<pre>index("foobar", "o") => 2
|
|
rindex("foobar", "o") => 3
|
|
index("foobar", "x") => 0
|
|
index("foobar", "oba") => 3
|
|
index("Foobar", "foo", 1) => 0
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>strcmp</b> <i>(str <var>str1</var>, str <var>str2</var>)</i>
|
|
</dt><dd><a name="IDX37"></a>
|
|
Performs a case-sensitive comparison of the two argument strings. If
|
|
<var>str1</var> is lexicographically less than <var>str2</var>, the
|
|
<code>strcmp()</code> returns a negative integer. If the two strings are
|
|
identical, <code>strcmp()</code> returns zero. Otherwise, <code>strcmp()</code>
|
|
returns a positive integer. The ASCII character ordering is used for the
|
|
comparison.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>decode_binary</b> <i>(str <var>bin-string</var> [, <var>fully</var>])</i>
|
|
</dt><dd><a name="IDX38"></a>
|
|
Returns a list of strings and/or integers representing the bytes in the binary
|
|
string <var>bin_string</var> in order. If <var>fully</var> is false or omitted, the list
|
|
contains an integer only for each non-printing, non-space byte; all other
|
|
characters are grouped into the longest possible contiguous substrings. If
|
|
<var>fully</var> is provided and true, the list contains only integers, one for each
|
|
byte represented in <var>bin_string</var>. Raises <code>E_INVARG</code> if
|
|
<var>bin_string</var> is not a properly-formed binary string. (See the early
|
|
section on MOO value types for a full description of binary strings.)
|
|
|
|
|
|
|
|
<pre>decode_binary("foo") => {"foo"}
|
|
decode_binary("~~foo") => {"~foo"}
|
|
decode_binary("foo~0D~0A") => {"foo", 13, 10}
|
|
decode_binary("foo~0Abar~0Abaz") => {"foo", 10, "bar", 10, "baz"}
|
|
decode_binary("foo~0D~0A", 1) => {102, 111, 111, 13, 10}
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>encode_binary</b> <i>(<var>arg</var>, ...)</i>
|
|
</dt><dd><a name="IDX39"></a>
|
|
Each argument must be an integer between 0 and 255, a string, or a list
|
|
containing only legal arguments for this function. This function translates
|
|
each integer and string in turn into its binary string equivalent, returning the
|
|
concatenation of all these substrings into a single binary string. (See the
|
|
early section on MOO value types for a full description of binary strings.)
|
|
|
|
|
|
|
|
<pre>encode_binary("~foo") => "~7Efoo"
|
|
encode_binary({"foo", 10}, {"bar", 13}) => "foo~0Abar~0D"
|
|
encode_binary("foo", 10, "bar", 13) => "foo~0Abar~0D"
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>match</b> <i>(str <var>subject</var>, str <var>pattern</var> [, <var>case-matters</var>])</i>
|
|
</dt><dd><a name="IDX40"></a>
|
|
</dd><dt><u>Function:</u> list <b>rmatch</b> <i>(str <var>subject</var>, str <var>pattern</var> [, <var>case-matters</var>])</i>
|
|
</dt><dd><a name="IDX41"></a>
|
|
The function <code>match()</code> (<code>rmatch()</code>) searches for the first (last)
|
|
occurrence of the regular expression <var>pattern</var> in the string <var>subject</var>.
|
|
If <var>pattern</var> is syntactically malformed, then <code>E_INVARG</code> is raised.
|
|
The process of matching can in some cases consume a great deal of memory in the
|
|
server; should this memory consumption become excessive, then the matching
|
|
process is aborted and <code>E_QUOTA</code> is raised.
|
|
|
|
|
|
<p>
|
|
If no match is found, the empty list is returned; otherwise, these functions
|
|
return a list containing information about the match (see below). By default,
|
|
the search ignores upper-/lower-case distinctions. If <var>case-matters</var> is
|
|
provided and true, then case is treated as significant in all comparisons.
|
|
|
|
|
|
</p><p>
|
|
The list that <code>match()</code> (<code>rmatch()</code>) returns contains the details
|
|
about the match made. The list is in the form:
|
|
|
|
|
|
|
|
</p><pre>{<var>start</var>, <var>end</var>, <var>replacements</var>, <var>subject</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>start</var> is the index in <var>subject</var> of the beginning of the match,
|
|
<var>end</var> is the index of the end of the match, <var>replacements</var> is a list
|
|
described below, and <var>subject</var> is the same string that was given as the
|
|
first argument to the <code>match()</code> or <code>rmatch()</code>.
|
|
|
|
|
|
</p><p>
|
|
The <var>replacements</var> list is always nine items long, each item itself being a
|
|
list of two integers, the start and end indices in <var>string</var> matched by some
|
|
parenthesized sub-pattern of <var>pattern</var>. The first item in
|
|
<var>replacements</var> carries the indices for the first parenthesized sub-pattern,
|
|
the second item carries those for the second sub-pattern, and so on. If there
|
|
are fewer than nine parenthesized sub-patterns in <var>pattern</var>, or if some
|
|
sub-pattern was not used in the match, then the corresponding item in
|
|
<var>replacements</var> is the list {0, -1}. See the discussion of <samp>`%)'</samp>,
|
|
below, for more information on parenthesized sub-patterns.
|
|
|
|
|
|
|
|
</p><pre>match("foo", "^f*o$") => {}
|
|
match("foo", "^fo*$") => {1, 3, {{0, -1}, ...}, "foo"}
|
|
match("foobar", "o*b") => {2, 4, {{0, -1}, ...}, "foobar"}
|
|
rmatch("foobar", "o*b") => {4, 4, {{0, -1}, ...}, "foobar"}
|
|
match("foobar", "f%(o*%)b")
|
|
=> {1, 4, {{2, 3}, {0, -1}, ...}, "foobar"}
|
|
</pre>
|
|
|
|
<p>
|
|
<em>Regular expression</em> matching allows you to test whether a string fits into
|
|
a specific syntactic shape. You can also search a string for a substring that
|
|
fits a pattern.
|
|
|
|
|
|
</p><p>
|
|
A regular expression describes a set of strings. The simplest case is one that
|
|
describes a particular string; for example, the string <samp>`foo'</samp> when regarded
|
|
as a regular expression matches <samp>`foo'</samp> and nothing else. Nontrivial
|
|
regular expressions use certain special constructs so that they can match more
|
|
than one string. For example, the regular expression <samp>`foo%|bar'</samp> matches
|
|
either the string <samp>`foo'</samp> or the string <samp>`bar'</samp>; the regular expression
|
|
<samp>`c[ad]*r'</samp> matches any of the strings <samp>`cr'</samp>, <samp>`car'</samp>, <samp>`cdr'</samp>,
|
|
<samp>`caar'</samp>, <samp>`cadddar'</samp> and all other such strings with any number of
|
|
<samp>`a'</samp>'s and <samp>`d'</samp>'s.
|
|
|
|
|
|
</p><p>
|
|
Regular expressions have a syntax in which a few characters are special
|
|
constructs and the rest are <em>ordinary</em>. An ordinary character is a simple
|
|
regular expression that matches that character and nothing else. The special
|
|
characters are <samp>`$'</samp>, <samp>`^'</samp>, <samp>`.'</samp>, <samp>`*'</samp>, <samp>`+'</samp>, <samp>`?'</samp>,
|
|
<samp>`['</samp>, <samp>`]'</samp> and <samp>`%'</samp>. Any other character appearing in a regular
|
|
expression is ordinary, unless a <samp>`%'</samp> precedes it.
|
|
|
|
|
|
</p><p>
|
|
For example, <samp>`f'</samp> is not a special character, so it is ordinary, and
|
|
therefore <samp>`f'</samp> is a regular expression that matches the string <samp>`f'</samp> and
|
|
no other string. (It does <em>not</em>, for example, match the string
|
|
<samp>`ff'</samp>.) Likewise, <samp>`o'</samp> is a regular expression that matches only
|
|
<samp>`o'</samp>.
|
|
|
|
|
|
</p><p>
|
|
Any two regular expressions <var>a</var> and <var>b</var> can be concatenated. The
|
|
result is a regular expression which matches a string if <var>a</var> matches some
|
|
amount of the beginning of that string and <var>b</var> matches the rest of the
|
|
string.
|
|
|
|
|
|
</p><p>
|
|
As a simple example, we can concatenate the regular expressions <samp>`f'</samp> and
|
|
<samp>`o'</samp> to get the regular expression <samp>`fo'</samp>, which matches only the string
|
|
<samp>`fo'</samp>. Still trivial.
|
|
|
|
|
|
</p><p>
|
|
The following are the characters and character sequences that have special
|
|
meaning within regular expressions. Any character not mentioned here is not
|
|
special; it stands for exactly itself for the purposes of searching and
|
|
matching.
|
|
|
|
|
|
</p><dl compact="compact">
|
|
|
|
<dt><samp>`.'</samp>
|
|
</dt><dd>
|
|
is a special character that matches any single character. Using concatenation,
|
|
we can make regular expressions like <samp>`a.b'</samp>, which matches any
|
|
three-character string that begins with <samp>`a'</samp> and ends with <samp>`b'</samp>.
|
|
|
|
</dd><dt><samp>`*'</samp>
|
|
</dt><dd>
|
|
is not a construct by itself; it is a suffix that means that the preceding
|
|
regular expression is to be repeated as many times as possible. In <samp>`fo*'</samp>,
|
|
the <samp>`*'</samp> applies to the <samp>`o'</samp>, so <samp>`fo*'</samp> matches <samp>`f'</samp> followed
|
|
by any number of <samp>`o'</samp>'s.
|
|
|
|
The case of zero <samp>`o'</samp>'s is allowed: <samp>`fo*'</samp> does match <samp>`f'</samp>.
|
|
|
|
<samp>`*'</samp> always applies to the <em>smallest</em> possible preceding expression.
|
|
Thus, <samp>`fo*'</samp> has a repeating <samp>`o'</samp>, not a repeating <samp>`fo'</samp>.
|
|
|
|
The matcher processes a <samp>`*'</samp> construct by matching, immediately, as many
|
|
repetitions as can be found. Then it continues with the rest of the pattern.
|
|
If that fails, it backtracks, discarding some of the matches of the <samp>`*'</samp>'d
|
|
construct in case that makes it possible to match the rest of the pattern. For
|
|
example, matching <samp>`c[ad]*ar'</samp> against the string <samp>`caddaar'</samp>, the
|
|
<samp>`[ad]*'</samp> first matches <samp>`addaa'</samp>, but this does not allow the next
|
|
<samp>`a'</samp> in the pattern to match. So the last of the matches of <samp>`[ad]'</samp> is
|
|
undone and the following <samp>`a'</samp> is tried again. Now it succeeds.
|
|
|
|
</dd><dt><samp>`+'</samp>
|
|
</dt><dd>
|
|
<samp>`+'</samp> is like <samp>`*'</samp> except that at least one match for the preceding
|
|
pattern is required for <samp>`+'</samp>. Thus, <samp>`c[ad]+r'</samp> does not match
|
|
<samp>`cr'</samp> but does match anything else that <samp>`c[ad]*r'</samp> would match.
|
|
|
|
</dd><dt><samp>`?'</samp>
|
|
</dt><dd>
|
|
<samp>`?'</samp> is like <samp>`*'</samp> except that it allows either zero or one match for
|
|
the preceding pattern. Thus, <samp>`c[ad]?r'</samp> matches <samp>`cr'</samp> or <samp>`car'</samp> or
|
|
<samp>`cdr'</samp>, and nothing else.
|
|
|
|
</dd><dt><samp>`[ ... ]'</samp>
|
|
</dt><dd>
|
|
<samp>`['</samp> begins a <em>character set</em>, which is terminated by a <samp>`]'</samp>. In
|
|
the simplest case, the characters between the two brackets form the set. Thus,
|
|
<samp>`[ad]'</samp> matches either <samp>`a'</samp> or <samp>`d'</samp>, and <samp>`[ad]*'</samp> matches any
|
|
string of <samp>`a'</samp>'s and <samp>`d'</samp>'s (including the empty string), from which it
|
|
follows that <samp>`c[ad]*r'</samp> matches <samp>`car'</samp>, etc.
|
|
|
|
Character ranges can also be included in a character set, by writing two
|
|
characters with a <samp>`-'</samp> between them. Thus, <samp>`[a-z]'</samp> matches any
|
|
lower-case letter. Ranges may be intermixed freely with individual characters,
|
|
as in <samp>`[a-z$%.]'</samp>, which matches any lower case letter or <samp>`$'</samp>,
|
|
<samp>`%'</samp> or period.
|
|
|
|
Note that the usual special characters are not special any more inside a
|
|
character set. A completely different set of special characters exists inside
|
|
character sets: <samp>`]'</samp>, <samp>`-'</samp> and <samp>`^'</samp>.
|
|
|
|
To include a <samp>`]'</samp> in a character set, you must make it the first character.
|
|
For example, <samp>`[]a]'</samp> matches <samp>`]'</samp> or <samp>`a'</samp>. To include a <samp>`-'</samp>,
|
|
you must use it in a context where it cannot possibly indicate a range: that
|
|
is, as the first character, or immediately after a range.
|
|
|
|
</dd><dt><samp>`[^ ... ]'</samp>
|
|
</dt><dd>
|
|
<samp>`[^'</samp> begins a <em>complement character set</em>, which matches any character
|
|
except the ones specified. Thus, <samp>`[^a-z0-9A-Z]'</samp> matches all characters
|
|
<em>except</em> letters and digits.
|
|
|
|
<samp>`^'</samp> is not special in a character set unless it is the first character.
|
|
The character following the <samp>`^'</samp> is treated as if it were first (it may be
|
|
a <samp>`-'</samp> or a <samp>`]'</samp>).
|
|
|
|
</dd><dt><samp>`^'</samp>
|
|
</dt><dd>
|
|
is a special character that matches the empty string -- but only if at the
|
|
beginning of the string being matched. Otherwise it fails to match anything.
|
|
Thus, <samp>`^foo'</samp> matches a <samp>`foo'</samp> which occurs at the beginning of the
|
|
string.
|
|
|
|
</dd><dt><samp>`$'</samp>
|
|
</dt><dd>
|
|
is similar to <samp>`^'</samp> but matches only at the <em>end</em> of the string. Thus,
|
|
<samp>`xx*$'</samp> matches a string of one or more <samp>`x'</samp>'s at the end of the
|
|
string.
|
|
|
|
</dd><dt><samp>`%'</samp>
|
|
</dt><dd>
|
|
has two functions: it quotes the above special characters (including <samp>`%'</samp>),
|
|
and it introduces additional special constructs.
|
|
|
|
Because <samp>`%'</samp> quotes special characters, <samp>`%$'</samp> is a regular expression
|
|
that matches only <samp>`$'</samp>, and <samp>`%['</samp> is a regular expression that matches
|
|
only <samp>`['</samp>, and so on.
|
|
|
|
For the most part, <samp>`%'</samp> followed by any character matches only that
|
|
character. However, there are several exceptions: characters that, when
|
|
preceded by <samp>`%'</samp>, are special constructs. Such characters are always
|
|
ordinary when encountered on their own.
|
|
|
|
No new special characters will ever be defined. All extensions to the regular
|
|
expression syntax are made by defining new two-character constructs that begin
|
|
with <samp>`%'</samp>.
|
|
|
|
</dd><dt><samp>`%|'</samp>
|
|
</dt><dd>
|
|
specifies an alternative. Two regular expressions <var>a</var> and <var>b</var> with
|
|
<samp>`%|'</samp> in between form an expression that matches anything that either
|
|
<var>a</var> or <var>b</var> will match.
|
|
|
|
Thus, <samp>`foo%|bar'</samp> matches either <samp>`foo'</samp> or <samp>`bar'</samp> but no other
|
|
string.
|
|
|
|
<samp>`%|'</samp> applies to the largest possible surrounding expressions. Only a
|
|
surrounding <samp>`%( ... %)'</samp> grouping can limit the grouping power of
|
|
<samp>`%|'</samp>.
|
|
|
|
Full backtracking capability exists for when multiple <samp>`%|'</samp>'s are used.
|
|
|
|
</dd><dt><samp>`%( ... %)'</samp>
|
|
</dt><dd>
|
|
is a grouping construct that serves three purposes:
|
|
|
|
|
|
<ol>
|
|
<li>
|
|
|
|
To enclose a set of <samp>`%|'</samp> alternatives for other operations. Thus,
|
|
<samp>`%(foo%|bar%)x'</samp> matches either <samp>`foox'</samp> or <samp>`barx'</samp>.
|
|
|
|
</li><li>
|
|
|
|
To enclose a complicated expression for a following <samp>`*'</samp>, <samp>`+'</samp>, or
|
|
<samp>`?'</samp> to operate on. Thus, <samp>`ba%(na%)*'</samp> matches <samp>`bananana'</samp>, etc.,
|
|
with any number of <samp>`na'</samp>'s, including none.
|
|
|
|
</li><li>
|
|
|
|
To mark a matched substring for future reference.
|
|
</li></ol>
|
|
|
|
This last application is not a consequence of the idea of a parenthetical
|
|
grouping; it is a separate feature that happens to be assigned as a second
|
|
meaning to the same <samp>`%( ... %)'</samp> construct because there is no conflict
|
|
in practice between the two meanings. Here is an explanation of this feature:
|
|
|
|
</dd><dt><samp>`%<var>digit</var>'</samp>
|
|
</dt><dd>
|
|
After the end of a <samp>`%( ... %)'</samp> construct, the matcher remembers the
|
|
beginning and end of the text matched by that construct. Then, later on in the
|
|
regular expression, you can use <samp>`%'</samp> followed by <var>digit</var> to mean
|
|
"match the same text matched by the <var>digit</var>'th <samp>`%( ... %)'</samp>
|
|
construct in the pattern." The <samp>`%( ... %)'</samp> constructs are numbered
|
|
in the order that their <samp>`%('</samp>'s appear in the pattern.
|
|
|
|
The strings matching the first nine <samp>`%( ... %)'</samp> constructs appearing
|
|
in a regular expression are assigned numbers 1 through 9 in order of their
|
|
beginnings. <samp>`%1'</samp> through <samp>`%9'</samp> may be used to refer to the text
|
|
matched by the corresponding <samp>`%( ... %)'</samp> construct.
|
|
|
|
For example, <samp>`%(.*%)%1'</samp> matches any string that is composed of two
|
|
identical halves. The <samp>`%(.*%)'</samp> matches the first half, which may be
|
|
anything, but the <samp>`%1'</samp> that follows must match the same exact text.
|
|
|
|
</dd><dt><samp>`%b'</samp>
|
|
</dt><dd>
|
|
matches the empty string, but only if it is at the beginning or
|
|
end of a word. Thus, <samp>`%bfoo%b'</samp> matches any occurrence of
|
|
<samp>`foo'</samp> as a separate word. <samp>`%bball%(s%|%)%b'</samp> matches
|
|
<samp>`ball'</samp> or <samp>`balls'</samp> as a separate word.
|
|
|
|
For the purposes of this construct and the five that follow, a word is defined
|
|
to be a sequence of letters and/or digits.
|
|
|
|
</dd><dt><samp>`%B'</samp>
|
|
</dt><dd>
|
|
matches the empty string, provided it is <em>not</em> at the beginning or
|
|
end of a word.
|
|
|
|
</dd><dt><samp>`%<'</samp>
|
|
</dt><dd>
|
|
matches the empty string, but only if it is at the beginning
|
|
of a word.
|
|
|
|
</dd><dt><samp>`%>'</samp>
|
|
</dt><dd>
|
|
matches the empty string, but only if it is at the end of a word.
|
|
|
|
</dd><dt><samp>`%w'</samp>
|
|
</dt><dd>
|
|
matches any word-constituent character (i.e., any letter or digit).
|
|
|
|
</dd><dt><samp>`%W'</samp>
|
|
</dt><dd>
|
|
matches any character that is not a word constituent.
|
|
</dd></dl>
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>substitute</b> <i>(str <var>template</var>, list <var>subs</var>)</i>
|
|
</dt><dd><a name="IDX42"></a>
|
|
Performs a standard set of substitutions on the string <var>template</var>, using
|
|
the information contained in <var>subs</var>, returning the resulting, transformed
|
|
<var>template</var>. <var>Subs</var> should be a list like those returned by
|
|
<code>match()</code> or <code>rmatch()</code> when the match succeeds; otherwise,
|
|
<code>E_INVARG</code> is raised.
|
|
|
|
|
|
<p>
|
|
In <var>template</var>, the strings <samp>`%1'</samp> through <samp>`%9'</samp> will be replaced by
|
|
the text matched by the first through ninth parenthesized sub-patterns when
|
|
<code>match()</code> or <code>rmatch()</code> was called. The string <samp>`%0'</samp> in
|
|
<var>template</var> will be replaced by the text matched by the pattern as a whole
|
|
when <code>match()</code> or <code>rmatch()</code> was called. The string <samp>`%%'</samp> will
|
|
be replaced by a single <samp>`%'</samp> sign. If <samp>`%'</samp> appears in <var>template</var>
|
|
followed by any other character, <code>E_INVARG</code> will be raised.
|
|
|
|
|
|
|
|
</p><pre>subs = match("*** Welcome to LambdaMOO!!!", "%(%w*%) to %(%w*%)");
|
|
substitute("I thank you for your %1 here in %2.", subs)
|
|
=> "I thank you for your Welcome here in LambdaMOO."
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>crypt</b> <i>(str <var>text</var> [, str <var>salt</var>])</i>
|
|
</dt><dd><a name="IDX43"></a>
|
|
Encrypts the given <var>text</var> using the standard UNIX encryption method. If
|
|
provided, <var>salt</var> should be a string at least two characters long, the first
|
|
two characters of which will be used as the extra encryption "salt" in the
|
|
algorithm. If <var>salt</var> is not provided, a random pair of characters is used.
|
|
In any case, the salt used is also returned as the first two characters of the
|
|
resulting encrypted string.
|
|
|
|
|
|
<p>
|
|
Aside from the possibly-random selection of the salt, the encryption algorithm
|
|
is entirely deterministic. In particular, you can test whether or not a given
|
|
string is the same as the one used to produce a given piece of encrypted text;
|
|
simply extract the first two characters of the encrypted text and pass the
|
|
candidate string and those two characters to <code>crypt()</code>. If the result is
|
|
identical to the given encrypted text, then you've got a match.
|
|
|
|
|
|
|
|
</p><pre>crypt("foobar") => "J3fSFQfgkp26w"
|
|
crypt("foobar", "J3") => "J3fSFQfgkp26w"
|
|
crypt("mumble", "J3") => "J3D0.dh.jjmWQ"
|
|
crypt("foobar", "J4") => "J4AcPxOJ4ncq2"
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>string_hash</b> <i>(str <var>text</var>)</i>
|
|
</dt><dd><a name="IDX44"></a>
|
|
</dd><dt><u>Function:</u> str <b>binary_hash</b> <i>(str <var>bin-string</var>)</i>
|
|
</dt><dd><a name="IDX45"></a>
|
|
Returns a 32-character hexadecimal string encoding the result of applying the
|
|
MD5 cryptographically secure hash function to the contents of the string
|
|
<var>text</var> or the binary string <var>bin-string</var>. MD5, like other such
|
|
functions, has the property that, if
|
|
|
|
<pre>string_hash(<var>x</var>) == string_hash(<var>y</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
then, almost certainly,
|
|
|
|
</p><pre>equal(<var>x</var>, <var>y</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
This can be useful, for example, in certain networking applications: after
|
|
sending a large piece of text across a connection, also send the result of
|
|
applying <code>string_hash()</code> to the text; if the destination site also
|
|
applies <code>string_hash()</code> to the text and gets the same result, you can be
|
|
quite confident that the large text has arrived unchanged.
|
|
</p></dd></dl>
|
|
|
|
|
|
|
|
|
|
<h4><a name="SEC45" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC45">Operations on Lists</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>length</b> <i>(list <var>list</var>)</i>
|
|
</dt><dd><a name="IDX46"></a>
|
|
Returns the number of elements in <var>list</var>. It is also permissible to
|
|
pass a string to <code>length()</code>; see the description in the previous
|
|
section.
|
|
|
|
|
|
|
|
<pre>length({1, 2, 3}) => 3
|
|
length({}) => 0
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>is_member</b> <i>(<var>value</var>, list <var>list</var>)</i>
|
|
</dt><dd><a name="IDX47"></a>
|
|
Returns true if there is an element of <var>list</var> that is completely
|
|
indistinguishable from <var>value</var>. This is much the same operation as
|
|
"<code><var>value</var> in <var>list</var></code>" except that, unlike <code>in</code>, the
|
|
<code>is_member()</code> function does not treat upper- and lower-case characters in
|
|
strings as equal.
|
|
|
|
|
|
|
|
<pre>"Foo" in {1, "foo", #24} => 2
|
|
is_member("Foo", {1, "foo", #24}) => 0
|
|
is_member("Foo", {1, "Foo", #24}) => 2
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>listinsert</b> <i>(list <var>list</var>, <var>value</var> [, int <var>index</var>])</i>
|
|
</dt><dd><a name="IDX48"></a>
|
|
</dd><dt><u>Function:</u> list <b>listappend</b> <i>(list <var>list</var>, <var>value</var> [, int <var>index</var>])</i>
|
|
</dt><dd><a name="IDX49"></a>
|
|
These functions return a copy of <var>list</var> with <var>value</var> added as a new
|
|
element. <code>listinsert()</code> and <code>listappend()</code> add <var>value</var> before
|
|
and after (respectively) the existing element with the given <var>index</var>, if
|
|
provided.
|
|
|
|
|
|
<p>
|
|
The following three expressions always have the same value:
|
|
|
|
|
|
|
|
</p><pre>listinsert(<var>list</var>, <var>element</var>, <var>index</var>)
|
|
listappend(<var>list</var>, <var>element</var>, <var>index</var> - 1)
|
|
{@<var>list</var>[1..<var>index</var> - 1], <var>element</var>, @<var>list</var>[<var>index</var>..length(<var>list</var>)]}
|
|
</pre>
|
|
|
|
<p>
|
|
If <var>index</var> is not provided, then <code>listappend()</code> adds the <var>value</var>
|
|
at the end of the list and <code>listinsert()</code> adds it at the beginning; this
|
|
usage is discouraged, however, since the same intent can be more clearly
|
|
expressed using the list-construction expression, as shown in the examples
|
|
below.
|
|
|
|
|
|
|
|
</p><pre>x = {1, 2, 3};
|
|
listappend(x, 4, 2) => {1, 2, 4, 3}
|
|
listinsert(x, 4, 2) => {1, 4, 2, 3}
|
|
listappend(x, 4) => {1, 2, 3, 4}
|
|
listinsert(x, 4) => {4, 1, 2, 3}
|
|
{@x, 4} => {1, 2, 3, 4}
|
|
{4, @x} => {4, 1, 2, 3}
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>listdelete</b> <i>(list <var>list</var>, int <var>index</var>)</i>
|
|
</dt><dd><a name="IDX50"></a>
|
|
Returns a copy of <var>list</var> with the <var>index</var>th element removed. If
|
|
<var>index</var> is not in the range <code>[1..length(<var>list</var>)]</code>, then
|
|
<code>E_RANGE</code> is raised.
|
|
|
|
|
|
|
|
<pre>x = {"foo", "bar", "baz"};
|
|
listdelete(x, 2) => {"foo", "baz"}
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>listset</b> <i>(list <var>list</var>, <var>value</var>, int <var>index</var>)</i>
|
|
</dt><dd><a name="IDX51"></a>
|
|
Returns a copy of <var>list</var> with the <var>index</var>th element replaced by
|
|
<var>value</var>. If <var>index</var> is not in the range
|
|
<code>[1..length(<var>list</var>)]</code>, then <code>E_RANGE</code> is raised.
|
|
|
|
|
|
|
|
<pre>x = {"foo", "bar", "baz"};
|
|
listset(x, "mumble", 2) => {"foo", "mumble", "baz"}
|
|
</pre>
|
|
|
|
<p>
|
|
This function exists primarily for historical reasons; it was used heavily
|
|
before the server supported indexed assignments like <code>x[i] = v</code>. New code
|
|
should always use indexed assignment instead of <samp>`listset()'</samp> wherever
|
|
possible.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>setadd</b> <i>(list <var>list</var>, <var>value</var>)</i>
|
|
</dt><dd><a name="IDX52"></a>
|
|
</dd><dt><u>Function:</u> list <b>setremove</b> <i>(list <var>list</var>, <var>value</var>)</i>
|
|
</dt><dd><a name="IDX53"></a>
|
|
Returns a copy of <var>list</var> with the given <var>value</var> added or removed, as
|
|
appropriate. <code>setadd()</code> only adds <var>value</var> if it is not already an
|
|
element of <var>list</var>; <var>list</var> is thus treated as a mathematical set.
|
|
<var>value</var> is added at the end of the resulting list, if at all. Similarly,
|
|
<code>setremove()</code> returns a list identical to <var>list</var> if <var>value</var> is not
|
|
an element. If <var>value</var> appears more than once in <var>list</var>, only the
|
|
first occurrence is removed in the returned copy.
|
|
|
|
|
|
|
|
<pre>setadd({1, 2, 3}, 3) => {1, 2, 3}
|
|
setadd({1, 2, 3}, 4) => {1, 2, 3, 4}
|
|
setremove({1, 2, 3}, 3) => {1, 2}
|
|
setremove({1, 2, 3}, 4) => {1, 2, 3}
|
|
setremove({1, 2, 3, 2}, 2) => {1, 3, 2}
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
|
|
|
|
<h3><a name="SEC46" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC46">Manipulating Objects</a></h3>
|
|
|
|
<p>
|
|
Objects are, of course, the main focus of most MOO programming and, largely due
|
|
to that, there are a lot of built-in functions for manipulating them.
|
|
|
|
|
|
|
|
|
|
</p><h4><a name="SEC47" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC47">Fundamental Operations on Objects</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> obj <b>create</b> <i>(obj <var>parent</var> [, obj <var>owner</var>])</i>
|
|
</dt><dd><a name="IDX54"></a>
|
|
Creates and returns a new object whose parent is <var>parent</var> and whose owner
|
|
is as described below. Either the given <var>parent</var> object must be <code>#-1</code>
|
|
or valid and fertile (i.e., its <samp>`f'</samp> bit must be set) or else the
|
|
programmer must own <var>parent</var> or be a wizard; otherwise <code>E_PERM</code> is
|
|
raised. <code>E_PERM</code> is also raised if <var>owner</var> is provided and not
|
|
the same as the programmer, unless the programmer is a wizard. After the new
|
|
object is created, its <code>initialize</code> verb, if any, is called with no
|
|
arguments.
|
|
|
|
|
|
<p>
|
|
The new object is assigned the least non-negative object number that has not
|
|
yet been used for a created object. Note that no object number is ever reused,
|
|
even if the object with that number is recycled.
|
|
|
|
|
|
</p><p>
|
|
The owner of the new object is either the programmer (if <var>owner</var> is not
|
|
provided), the new object itself (if <var>owner</var> was given as <code>#-1</code>), or
|
|
<var>owner</var> (otherwise).
|
|
|
|
|
|
</p><p>
|
|
The other built-in properties of the new object are initialized as follows:
|
|
|
|
</p><pre>name ""
|
|
location #-1
|
|
contents {}
|
|
programmer 0
|
|
wizard 0
|
|
r 0
|
|
w 0
|
|
f 0
|
|
</pre>
|
|
|
|
<p>
|
|
The function <samp>`is_player()'</samp> returns false for newly created objects.
|
|
|
|
|
|
</p><p>
|
|
In addition, the new object inherits all of the other properties on
|
|
<var>parent</var>. These properties have the same permission bits as on
|
|
<var>parent</var>. If the <samp>`c'</samp> permissions bit is set, then the owner of the
|
|
property on the new object is the same as the owner of the new object itself;
|
|
otherwise, the owner of the property on the new object is the same as that on
|
|
<var>parent</var>. The initial value of every inherited property is <em>clear</em>;
|
|
see the description of the built-in function <code>clear_property()</code> for
|
|
details.
|
|
|
|
|
|
</p><p>
|
|
If the intended owner of the new object has a property named
|
|
<samp>`ownership_quota'</samp> and the value of that property is an integer, then
|
|
<code>create()</code> treats that value as a <em>quota</em>. If the quota is less than
|
|
or equal to zero, then the quota is considered to be exhausted and
|
|
<code>create()</code> raises <code>E_QUOTA</code> instead of creating an object.
|
|
Otherwise, the quota is decremented and stored back into the
|
|
<samp>`ownership_quota'</samp> property as a part of the creation of the new object.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>chparent</b> <i>(obj <var>object</var>, obj <var>new-parent</var>)</i>
|
|
</dt><dd><a name="IDX55"></a>
|
|
Changes the parent of <var>object</var> to be <var>new-parent</var>. If <var>object</var> is
|
|
not valid, or if <var>new-parent</var> is neither valid nor equal to <code>#-1</code>,
|
|
then <code>E_INVARG</code> is raised. If the programmer is neither a wizard or the
|
|
owner of <var>object</var>, or if <var>new-parent</var> is not fertile (i.e., its
|
|
<samp>`f'</samp> bit is not set) and the programmer is neither the owner of
|
|
<var>new-parent</var> nor a wizard, then <code>E_PERM</code> is raised. If
|
|
<var>new-parent</var> is equal to <code>object</code> or one of its current ancestors,
|
|
<code>E_RECMOVE</code> is raised. If <var>object</var> or one of its descendants
|
|
defines a property with the same name as one defined either on <var>new-parent</var>
|
|
or on one of its ancestors, then <code>E_INVARG</code> is raised.
|
|
|
|
|
|
<p>
|
|
Changing an object's parent can have the effect of removing some properties
|
|
from and adding some other properties to that object and all of its descendants
|
|
(i.e., its children and its children's children, etc.). Let <var>common</var> be
|
|
the nearest ancestor that <var>object</var> and <var>new-parent</var> have in common
|
|
before the parent of <var>object</var> is changed. Then all properties defined by
|
|
ancestors of <var>object</var> under <var>common</var> (that is, those ancestors of
|
|
<var>object</var> that are in turn descendants of <var>common</var>) are removed from
|
|
<var>object</var> and all of its descendants. All properties defined by
|
|
<var>new-parent</var> or its ancestors under <var>common</var> are added to <var>object</var>
|
|
and all of its descendants. As with <code>create()</code>, the newly-added
|
|
properties are given the same permission bits as they have on <var>new-parent</var>,
|
|
the owner of each added property is either the owner of the object it's added
|
|
to (if the <samp>`c'</samp> permissions bit is set) or the owner of that property on
|
|
<var>new-parent</var>, and the value of each added property is <em>clear</em>; see the
|
|
description of the built-in function <code>clear_property()</code> for details. All
|
|
properties that are not removed or added in the reparenting process are
|
|
completely unchanged.
|
|
|
|
|
|
</p><p>
|
|
If <var>new-parent</var> is equal to <code>#-1</code>, then <var>object</var> is given no
|
|
parent at all; it becomes a new root of the parent/child hierarchy. In this
|
|
case, all formerly inherited properties on <var>object</var> are simply removed.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>valid</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX56"></a>
|
|
Returns a non-zero integer (i.e., a true value) if <var>object</var> is a valid
|
|
object (one that has been created and not yet recycled) and zero (i.e., a false
|
|
value) otherwise.
|
|
|
|
|
|
|
|
<pre>valid(#0) => 1
|
|
valid(#-1) => 0
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> obj <b>parent</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX57"></a>
|
|
</dd><dt><u>Function:</u> list <b>children</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX58"></a>
|
|
These functions return the parent and a list of the children of <var>object</var>,
|
|
respectively. If <var>object</var> is not valid, then <code>E_INVARG</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>recycle</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX59"></a>
|
|
The given <var>object</var> is destroyed, irrevocably. The programmer must either
|
|
own <var>object</var> or be a wizard; otherwise, <code>E_PERM</code> is raised. If
|
|
<var>object</var> is not valid, then <code>E_INVARG</code> is raised. The children of
|
|
<var>object</var> are reparented to the parent of <var>object</var>. Before <var>object</var>
|
|
is recycled, each object in its contents is moved to <code>#-1</code> (implying a
|
|
call to <var>object</var>'s <code>exitfunc</code> verb, if any) and then <var>object</var>'s
|
|
<samp>`recycle'</samp> verb, if any, is called with no arguments.
|
|
|
|
|
|
<p>
|
|
After <var>object</var> is recycled, if the owner of the former object has a
|
|
property named <samp>`ownership_quota'</samp> and the value of that property is a
|
|
integer, then <code>recycle()</code> treats that value as a <em>quota</em> and increments
|
|
it by one, storing the result back into the <samp>`ownership_quota'</samp> property.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>object_bytes</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX60"></a>
|
|
Returns the number of bytes of the server's memory required to store the given
|
|
<var>object</var>, including the space used by the values of all of its non-clear
|
|
properties and by the verbs and properties defined directly on the object.
|
|
Raised <code>E_INVARG</code> if <var>object</var> is not a valid object and <code>E_PERM</code>
|
|
if the programmer is not a wizard.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> obj <b>max_object</b> <i>()</i>
|
|
</dt><dd><a name="IDX61"></a>
|
|
Returns the largest object number yet assigned to a created object. Note that
|
|
the object with this number may no longer exist; it may have been recycled.
|
|
The next object created will be assigned the object number one larger than the
|
|
value of <code>max_object()</code>.
|
|
</dd></dl>
|
|
|
|
|
|
|
|
|
|
<h4><a name="SEC48" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC48">Object Movement</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>move</b> <i>(obj <var>what</var>, obj <var>where</var>)</i>
|
|
</dt><dd><a name="IDX62"></a>
|
|
Changes <var>what</var>'s location to be <var>where</var>. This is a complex process
|
|
because a number of permissions checks and notifications must be performed.
|
|
The actual movement takes place as described in the following paragraphs.
|
|
|
|
|
|
<p>
|
|
<var>what</var> should be a valid object and <var>where</var> should be either a valid
|
|
object or <code>#-1</code> (denoting a location of `nowhere'); otherwise
|
|
<code>E_INVARG</code> is raised. The programmer must be either the owner of
|
|
<var>what</var> or a wizard; otherwise, <code>E_PERM</code> is raised.
|
|
|
|
|
|
</p><p>
|
|
If <var>where</var> is a valid object, then the verb-call
|
|
|
|
|
|
|
|
</p><pre><var>where</var>:accept(<var>what</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
is performed before any movement takes place. If the verb returns a
|
|
false value and the programmer is not a wizard, then <var>where</var> is
|
|
considered to have refused entrance to <var>what</var>; <code>move()</code> raises
|
|
<code>E_NACC</code>. If <var>where</var> does not define an <code>accept</code> verb, then it
|
|
is treated as if it defined one that always returned false.
|
|
|
|
|
|
</p><p>
|
|
If moving <var>what</var> into <var>where</var> would create a loop in the containment
|
|
hierarchy (i.e., <var>what</var> would contain itself, even indirectly), then
|
|
<code>E_RECMOVE</code> is raised instead.
|
|
|
|
|
|
</p><p>
|
|
The <samp>`location'</samp> property of <var>what</var> is changed to be <var>where</var>, and
|
|
the <samp>`contents'</samp> properties of the old and new locations are modified
|
|
appropriately. Let <var>old-where</var> be the location of <var>what</var> before it was
|
|
moved. If <var>old-where</var> is a valid object, then the verb-call
|
|
|
|
|
|
|
|
</p><pre><var>old-where</var>:exitfunc(<var>what</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
is performed and its result is ignored; it is not an error if <var>old-where</var>
|
|
does not define a verb named <samp>`exitfunc'</samp>. Finally, if <var>where</var> and
|
|
<var>what</var> are still valid objects, and <var>where</var> is still the location of
|
|
<var>what</var>, then the verb-call
|
|
|
|
|
|
|
|
</p><pre><var>where</var>:enterfunc(<var>what</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
is performed and its result is ignored; again, it is not an error if
|
|
<var>where</var> does not define a verb named <samp>`enterfunc'</samp>.
|
|
</p></dd></dl>
|
|
|
|
|
|
|
|
|
|
<h4><a name="SEC49" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC49">Operations on Properties</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>properties</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX63"></a>
|
|
Returns a list of the names of the properties defined directly on the given
|
|
<var>object</var>, not inherited from its parent. If <var>object</var> is not valid,
|
|
then <code>E_INVARG</code> is raised. If the programmer does not have read
|
|
permission on <var>object</var>, then <code>E_PERM</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>property_info</b> <i>(obj <var>object</var>, str <var>prop-name</var>)</i>
|
|
</dt><dd><a name="IDX64"></a>
|
|
</dd><dt><u>Function:</u> none <b>set_property_info</b> <i>(obj <var>object</var>, str <var>prop-name</var>, list <var>info</var>)</i>
|
|
</dt><dd><a name="IDX65"></a>
|
|
These two functions get and set (respectively) the owner and permission bits
|
|
for the property named <var>prop-name</var> on the given <var>object</var>. If
|
|
<var>object</var> is not valid, then <code>E_INVARG</code> is raised. If <var>object</var>
|
|
has no non-built-in property named <var>prop-name</var>, then <code>E_PROPNF</code> is
|
|
raised. If the programmer does not have read (write) permission on the
|
|
property in question, then <code>property_info()</code> (<code>set_property_info()</code>)
|
|
raises <code>E_PERM</code>. Property info has the following form:
|
|
|
|
|
|
|
|
<pre>{<var>owner</var>, <var>perms</var> [, <var>new-name</var>]}
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>owner</var> is an object, <var>perms</var> is a string containing only
|
|
characters from the set <samp>`r'</samp>, <samp>`w'</samp>, and <samp>`c'</samp>, and <var>new-name</var> is
|
|
a string; <var>new-name</var> is never part of the value returned by
|
|
<code>property_info()</code>, but it may optionally be given as part of the value
|
|
provided to <code>set_property_info()</code>. This list is the kind of value
|
|
returned by <code>property_info()</code> and expected as the third argument to
|
|
<code>set_property_info()</code>; the latter function raises <code>E_INVARG</code> if
|
|
<var>owner</var> is not valid, if <var>perms</var> contains any illegal characters, or,
|
|
when <var>new-name</var> is given, if <var>prop-name</var> is not defined directly on
|
|
<var>object</var> or <var>new-name</var> names an existing property defined on
|
|
<var>object</var> or any of its ancestors or descendants.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>add_property</b> <i>(obj <var>object</var>, str <var>prop-name</var>, <var>value</var>, list <var>info</var>)</i>
|
|
</dt><dd><a name="IDX66"></a>
|
|
Defines a new property on the given <var>object</var>, inherited by all of its
|
|
descendants; the property is named <var>prop-name</var>, its initial value is
|
|
<var>value</var>, and its owner and initial permission bits are given by <var>info</var>
|
|
in the same format as is returned by <code>property_info()</code>, described above.
|
|
If <var>object</var> is not valid or <var>info</var> does not specify a valid owner and
|
|
well-formed permission bits or <var>object</var> or its ancestors or descendants
|
|
already defines a property named <var>prop-name</var>, then <code>E_INVARG</code> is
|
|
raised. If the programmer does not have write permission on <var>object</var> or
|
|
if the owner specified by <var>info</var> is not the programmer and the programmer
|
|
is not a wizard, then <code>E_PERM</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>delete_property</b> <i>(obj <var>object</var>, str <var>prop-name</var>)</i>
|
|
</dt><dd><a name="IDX67"></a>
|
|
Removes the property named <var>prop-name</var> from the given <var>object</var> and all
|
|
of its descendants. If <var>object</var> is not valid, then <code>E_INVARG</code> is
|
|
raised. If the programmer does not have write permission on <var>object</var>,
|
|
then <code>E_PERM</code> is raised. If <var>object</var> does not directly define a
|
|
property named <var>prop-name</var> (as opposed to inheriting one from its parent),
|
|
then <code>E_PROPNF</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>is_clear_property</b> <i>(obj <var>object</var>, str <var>prop-name</var>)</i>
|
|
</dt><dd><a name="IDX68"></a>
|
|
</dd><dt><u>Function:</u> none <b>clear_property</b> <i>(obj <var>object</var>, str <var>prop-name</var>)</i>
|
|
</dt><dd><a name="IDX69"></a>
|
|
These two functions test for clear and set to clear, respectively, the property
|
|
named <var>prop-name</var> on the given <var>object</var>. If <var>object</var> is not valid,
|
|
then <code>E_INVARG</code> is raised. If <var>object</var> has no non-built-in property
|
|
named <var>prop-name</var>, then <code>E_PROPNF</code> is raised. If the programmer
|
|
does not have read (write) permission on the property in question, then
|
|
<code>is_clear_property()</code> (<code>clear_property()</code>) raises <code>E_PERM</code>.
|
|
If a property is clear, then when the value of that property is queried the
|
|
value of the parent's property of the same name is returned. If the parent's
|
|
property is clear, then the parent's parent's value is examined, and so on.
|
|
If <var>object</var> is the definer of the property <var>prop-name</var>, as opposed to
|
|
an inheritor of the property, then <code>clear_property()</code> raises
|
|
<code>E_INVARG</code>.
|
|
</dd></dl>
|
|
|
|
|
|
|
|
|
|
<h4><a name="SEC50" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC50">Operations on Verbs</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>verbs</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX70"></a>
|
|
Returns a list of the names of the verbs defined directly on the given
|
|
<var>object</var>, not inherited from its parent. If <var>object</var> is not valid,
|
|
then <code>E_INVARG</code> is raised. If the programmer does not have read
|
|
permission on <var>object</var>, then <code>E_PERM</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
Most of the remaining operations on verbs accept a string containing the verb's
|
|
name to identify the verb in question. Because verbs can have multiple names
|
|
and because an object can have multiple verbs with the same name, this practice
|
|
can lead to difficulties. To most unambiguously refer to a particular verb,
|
|
one can instead use a positive integer, the index of the verb in the list
|
|
returned by <code>verbs()</code>, described above.
|
|
|
|
|
|
</p><p>
|
|
For example, suppose that <code>verbs(#34)</code> returns this list:
|
|
|
|
|
|
|
|
</p><pre>{"foo", "bar", "baz", "foo"}
|
|
</pre>
|
|
|
|
<p>
|
|
Object <code>#34</code> has two verbs named <samp>`foo'</samp> defined on it (this may not be
|
|
an error, if the two verbs have different command syntaxes). To refer
|
|
unambiguously to the first one in the list, one uses the integer 1; to refer to
|
|
the other one, one uses 4.
|
|
|
|
|
|
</p><p>
|
|
In the function descriptions below, an argument named <var>verb-desc</var> is either
|
|
a string containing the name of a verb or else a positive integer giving the
|
|
index of that verb in its defining object's <code>verbs()</code> list.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
For historical reasons, there is also a second, inferior mechanism for
|
|
referring to verbs with numbers, but its use is strongly discouraged. If the
|
|
property <code>$server_options.support_numeric_verbname_strings</code> exists with a
|
|
true value, then functions on verbs will also accept a numeric string (e.g.,
|
|
<code>"4"</code>) as a verb descriptor. The decimal integer in the string works
|
|
more-or-less like the positive integers described above, but with two
|
|
significant differences:
|
|
|
|
|
|
|
|
</p><ol>
|
|
<li>
|
|
|
|
The numeric string is a <em>zero-based</em> index into <code>verbs()</code>; that is,
|
|
in the string case, you would use the number one less than what you would use
|
|
in the positive integer case.
|
|
|
|
</li><li>
|
|
|
|
When there exists a verb whose actual name looks like a decimal integer, this
|
|
numeric-string notation is ambiguous; the server will in all cases assume that
|
|
the reference is to the first verb in the list for which the given string could
|
|
be a name, either in the normal sense or as a numeric index.
|
|
</li></ol>
|
|
|
|
<p>
|
|
Clearly, this older mechanism is more difficult and risky to use; new code
|
|
should only be written to use the current mechanism, and old code using numeric
|
|
strings should be modified not to do so.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>verb_info</b> <i>(obj <var>object</var>, str <var>verb-desc</var>)</i>
|
|
</dt><dd><a name="IDX71"></a>
|
|
</dd><dt><u>Function:</u> none <b>set_verb_info</b> <i>(obj <var>object</var>, str <var>verb-desc</var>, list <var>info</var>)</i>
|
|
</dt><dd><a name="IDX72"></a>
|
|
These two functions get and set (respectively) the owner, permission bits, and
|
|
name(s) for the verb as specified by <var>verb-desc</var> on the given <var>object</var>.
|
|
If <var>object</var> is not valid, then <code>E_INVARG</code> is raised. If <var>object</var>
|
|
does not define a verb as specified by <var>verb-desc</var>, then <code>E_VERBNF</code> is
|
|
raised. If the programmer does not have read (write) permission on the verb in
|
|
question, then <code>verb_info()</code> (<code>set_verb_info()</code>) raises
|
|
<code>E_PERM</code>. Verb info has the following form:
|
|
|
|
|
|
|
|
<pre>{<var>owner</var>, <var>perms</var>, <var>names</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>owner</var> is an object, <var>perms</var> is a string containing only
|
|
characters from the set <samp>`r'</samp>, <samp>`w'</samp>, <samp>`x'</samp>, and <samp>`d'</samp>, and
|
|
<var>names</var> is a string. This is the kind of value returned by
|
|
<code>verb_info()</code> and expected as the third argument to
|
|
<code>set_verb_info()</code>. <code>set_verb_info()</code> raises <code>E_INVARG</code> if
|
|
<var>owner</var> is not valid, if <var>perms</var> contains any illegal characters, or if
|
|
<var>names</var> is the empty string or consists entirely of spaces; it raises
|
|
<code>E_PERM</code> if <var>owner</var> is not the programmer and the programmer is not a
|
|
wizard.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>verb_args</b> <i>(obj <var>object</var>, str <var>verb-desc</var>)</i>
|
|
</dt><dd><a name="IDX73"></a>
|
|
</dd><dt><u>Function:</u> none <b>set_verb_args</b> <i>(obj <var>object</var>, str <var>verb-desc</var>, list <var>args</var>)</i>
|
|
</dt><dd><a name="IDX74"></a>
|
|
These two functions get and set (respectively) the direct-object, preposition,
|
|
and indirect-object specifications for the verb as specified by <var>verb-desc</var>
|
|
on the given <var>object</var>. If <var>object</var> is not valid, then <code>E_INVARG</code>
|
|
is raised. If <var>object</var> does not define a verb as specified by
|
|
<var>verb-desc</var>, then <code>E_VERBNF</code> is raised. If the programmer does not
|
|
have read (write) permission on the verb in question, then <code>verb_args()</code>
|
|
(<code>set_verb_args()</code>) raises <code>E_PERM</code>. Verb args specifications have
|
|
the following form:
|
|
|
|
|
|
|
|
<pre>{<var>dobj</var>, <var>prep</var>, <var>iobj</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>dobj</var> and <var>iobj</var> are strings drawn from the set <code>"this"</code>,
|
|
<code>"none"</code>, and <code>"any"</code>, and <var>prep</var> is a string that is either
|
|
<code>"none"</code>, <code>"any"</code>, or one of the prepositional phrases listed much
|
|
earlier in the description of verbs in the first chapter. This is the kind of
|
|
value returned by <code>verb_args()</code> and expected as the third argument to
|
|
<code>set_verb_args()</code>. Note that for <code>set_verb_args()</code>, <var>prep</var> must
|
|
be only one of the prepositional phrases, not (as is shown in that table) a set
|
|
of such phrases separated by <samp>`/'</samp> characters. <code>set_verb_args</code> raises
|
|
<code>E_INVARG</code> if any of the <var>dobj</var>, <var>prep</var>, or <var>iobj</var> strings is
|
|
illegal.
|
|
|
|
|
|
|
|
</p><pre>verb_args($container, "take")
|
|
=> {"any", "out of/from inside/from", "this"}
|
|
set_verb_args($container, "take", {"any", "from", "this"})
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>add_verb</b> <i>(obj <var>object</var>, list <var>info</var>, list <var>args</var>)</i>
|
|
</dt><dd><a name="IDX75"></a>
|
|
Defines a new verb on the given <var>object</var>. The new verb's owner, permission
|
|
bits and name(s) are given by <var>info</var> in the same format as is returned by
|
|
<code>verb_info()</code>, described above. The new verb's direct-object,
|
|
preposition, and indirect-object specifications are given by <var>args</var> in the
|
|
same format as is returned by <code>verb_args</code>, described above. The new verb
|
|
initially has the empty program associated with it; this program does nothing
|
|
but return an unspecified value.
|
|
|
|
|
|
<p>
|
|
If <var>object</var> is not valid, or <var>info</var> does not specify a valid owner and
|
|
well-formed permission bits and verb names, or <var>args</var> is not a legitimate
|
|
syntax specification, then <code>E_INVARG</code> is raised. If the programmer does
|
|
not have write permission on <var>object</var> or if the owner specified by
|
|
<var>info</var> is not the programmer and the programmer is not a wizard, then
|
|
<code>E_PERM</code> is raised.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>delete_verb</b> <i>(obj <var>object</var>, str <var>verb-desc</var>)</i>
|
|
</dt><dd><a name="IDX76"></a>
|
|
Removes the verb as specified by <var>verb-desc</var> from the given <var>object</var>.
|
|
If <var>object</var> is not valid, then <code>E_INVARG</code> is raised. If the
|
|
programmer does not have write permission on <var>object</var>, then <code>E_PERM</code>
|
|
is raised. If <var>object</var> does not define a verb as specified by
|
|
<var>verb-desc</var>, then <code>E_VERBNF</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>verb_code</b> <i>(obj <var>object</var>, str <var>verb-desc</var> [, <var>fully-paren</var> [, <var>indent</var>]])</i>
|
|
</dt><dd><a name="IDX77"></a>
|
|
</dd><dt><u>Function:</u> list <b>set_verb_code</b> <i>(obj <var>object</var>, str <var>verb-desc</var>, list <var>code</var>)</i>
|
|
</dt><dd><a name="IDX78"></a>
|
|
These functions get and set (respectively) the MOO-code program associated with
|
|
the verb as specified by <var>verb-desc</var> on <var>object</var>. The program is
|
|
represented as a list of strings, one for each line of the program; this is the
|
|
kind of value returned by <code>verb_code()</code> and expected as the third argument
|
|
to <code>set_verb_code()</code>. For <code>verb_code()</code>, the expressions in the
|
|
returned code are usually written with the minimum-necessary parenthesization;
|
|
if <var>full-paren</var> is true, then all expressions are fully parenthesized.
|
|
Also for <code>verb_code()</code>, the lines in the returned code are usually not
|
|
indented at all; if <var>indent</var> is true, each line is indented to better show
|
|
the nesting of statements.
|
|
|
|
|
|
<p>
|
|
If <var>object</var> is not valid, then <code>E_INVARG</code> is raised. If <var>object</var>
|
|
does not define a verb as specified by <var>verb-desc</var>, then <code>E_VERBNF</code> is
|
|
raised. If the programmer does not have read (write) permission on the verb in
|
|
question, then <code>verb_code()</code> (<code>set_verb_code()</code>) raises
|
|
<code>E_PERM</code>. If the programmer is not, in fact. a programmer, then
|
|
<code>E_PERM</code> is raised.
|
|
|
|
|
|
</p><p>
|
|
For <code>set_verb_code()</code>, the result is a list of strings, the error messages
|
|
generated by the MOO-code compiler during processing of <var>code</var>. If the
|
|
list is non-empty, then <code>set_verb_code()</code> did not install <var>code</var>; the
|
|
program associated with the verb in question is unchanged.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>disassemble</b> <i>(obj <var>object</var>, str <var>verb-desc</var>)</i>
|
|
</dt><dd><a name="IDX79"></a>
|
|
Returns a (longish) list of strings giving a listing of the server's internal
|
|
"compiled" form of the verb as specified by <var>verb-desc</var> on <var>object</var>.
|
|
This format is not documented and may indeed change from release to release,
|
|
but some programmers may nonetheless find the output of <code>disassemble()</code>
|
|
interesting to peruse as a way to gain a deeper appreciation of how the server
|
|
works.
|
|
|
|
|
|
<p>
|
|
If <var>object</var> is not valid, then <code>E_INVARG</code> is raised. If <var>object</var>
|
|
does not define a verb as specified by <var>verb-desc</var>, then <code>E_VERBNF</code> is
|
|
raised. If the programmer does not have read permission on the verb in
|
|
question, then <code>disassemble()</code> raises <code>E_PERM</code>.
|
|
</p></dd></dl>
|
|
|
|
|
|
|
|
|
|
<h4><a name="SEC51" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC51">Operations on Player Objects</a></h4>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>players</b> <i>()</i>
|
|
</dt><dd><a name="IDX80"></a>
|
|
Returns a list of the object numbers of all player objects in the database.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>is_player</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX81"></a>
|
|
Returns a true value if the given <var>object</var> is a player object and a false
|
|
value otherwise. If <var>object</var> is not valid, <code>E_INVARG</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>set_player_flag</b> <i>(obj <var>object</var>, <var>value</var>)</i>
|
|
</dt><dd><a name="IDX82"></a>
|
|
Confers or removes the "player object" status of the given <var>object</var>,
|
|
depending upon the truth value of <var>value</var>. If <var>object</var> is not valid,
|
|
<code>E_INVARG</code> is raised. If the programmer is not a wizard, then
|
|
<code>E_PERM</code> is raised.
|
|
|
|
|
|
<p>
|
|
If <var>value</var> is true, then <var>object</var> gains (or keeps) "player object"
|
|
status: it will be an element of the list returned by <code>players()</code>, the
|
|
expression <code>is_player(<var>object</var>)</code> will return true, and the server will
|
|
treat a call to <code>$do_login_command()</code> that returns <var>object</var> as
|
|
logging in the current connection.
|
|
|
|
|
|
</p><p>
|
|
If <var>value</var> is false, the <var>object</var> loses (or continues to lack) "player
|
|
object" status: it will not be an element of the list returned by
|
|
<code>players()</code>, the expression <code>is_player(<var>object</var>)</code> will return
|
|
false, and users cannot connect to <var>object</var> by name when they log into the
|
|
server. In addition, if a user is connected to <var>object</var> at the time that
|
|
it loses "player object" status, then that connection is immediately broken,
|
|
just as if <code>boot_player(<var>object</var>)</code> had been called (see the
|
|
description of <code>boot_player()</code> below).
|
|
</p></dd></dl>
|
|
|
|
|
|
|
|
|
|
<h3><a name="SEC52" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC52">Operations on Network Connections</a></h3>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>connected_players</b> <i>([<var>include-all</var>])</i>
|
|
</dt><dd><a name="IDX83"></a>
|
|
Returns a list of the object numbers of those player objects with
|
|
currently-active connections. If <var>include-all</var> is provided and true, then
|
|
the list includes the object numbers associated with <em>all</em> current
|
|
connections, including ones that are outbound and/or not yet logged-in.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>connected_seconds</b> <i>(obj <var>player</var>)</i>
|
|
</dt><dd><a name="IDX84"></a>
|
|
</dd><dt><u>Function:</u> int <b>idle_seconds</b> <i>(obj <var>player</var>)</i>
|
|
</dt><dd><a name="IDX85"></a>
|
|
These functions return the number of seconds that the currently-active
|
|
connection to <var>player</var> has existed and been idle, respectively. If
|
|
<var>player</var> is not the object number of a player object with a
|
|
currently-active connection, then <code>E_INVARG</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>notify</b> <i>(obj <var>conn</var>, str <var>string</var> [, <var>no-flush</var>])</i>
|
|
</dt><dd><a name="IDX86"></a>
|
|
Enqueues <var>string</var> for output (on a line by itself) on the connection
|
|
<var>conn</var>. If the programmer is not <var>conn</var> or a wizard, then
|
|
<code>E_PERM</code> is raised. If <var>conn</var> is not a currently-active connection,
|
|
then this function does nothing. Output is normally written to connections
|
|
only between tasks, not during execution.
|
|
|
|
|
|
<p>
|
|
The server will not queue an arbitrary amount of output for a connection; the
|
|
<code>MAX_QUEUED_OUTPUT</code> compilation option (in <samp>`options.h'</samp>) controls the
|
|
limit. When an attempt is made to enqueue output that would take the server
|
|
over its limit, it first tries to write as much output as possible to the
|
|
connection without having to wait for the other end. If that doesn't result in
|
|
the new output being able to fit in the queue, the server starts throwing away
|
|
the oldest lines in the queue until the new ouput will fit. The server
|
|
remembers how many lines of output it has `flushed' in this way and, when next
|
|
it can succeed in writing anything to the connection, it first writes a line
|
|
like <code>>> Network buffer overflow: <var>X</var> lines of output to you have been
|
|
lost <<</code> where <var>X</var> is the number of flushed lines.
|
|
|
|
|
|
</p><p>
|
|
If <var>no-flush</var> is provided and true, then <code>notify()</code> never flushes any
|
|
output from the queue; instead it immediately returns false. <code>Notify()</code>
|
|
otherwise always returns true.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>buffered_output_length</b> <i>([obj <var>conn</var>])</i>
|
|
</dt><dd><a name="IDX87"></a>
|
|
Returns the number of bytes currently buffered for output to the connection
|
|
<var>conn</var>. If <var>conn</var> is not provided, returns the maximum number of bytes
|
|
that will be buffered up for output on any connection.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>read</b> <i>([obj <var>conn</var> [, <var>non-blocking</var>]])</i>
|
|
</dt><dd><a name="IDX88"></a>
|
|
Reads and returns a line of input from the connection <var>conn</var> (or, if not
|
|
provided, from the player that typed the command that initiated the current
|
|
task). If <var>non-blocking</var> is false or not provided, this function suspends
|
|
the current task, resuming it when there is input available to be read. If
|
|
<var>non-blocking</var> is provided and true, this function never suspends the
|
|
calling task; if there is no input currently available for input, <code>read()</code>
|
|
simply returns 0 immediately.
|
|
|
|
|
|
<p>
|
|
If <var>player</var> is provided, then the programmer must either be a wizard or the
|
|
owner of <code>player</code>; if <code>player</code> is not provided, then <code>read()</code>
|
|
may only be called by a wizard and only in the task that was last spawned by a
|
|
command from the connection in question. Otherwise, <code>E_PERM</code> is raised.
|
|
If the given <code>player</code> is not currently connected and has no pending lines
|
|
of input, or if the connection is closed while a task is waiting for input but
|
|
before any lines of input are received, then <code>read()</code> raises
|
|
<code>E_INVARG</code>.
|
|
|
|
|
|
</p><p>
|
|
The restriction on the use of <code>read()</code> without any arguments preserves the
|
|
following simple invariant: if input is being read from a player, it is for the
|
|
task started by the last command that player typed. This invariant adds
|
|
responsibility to the programmer, however. If your program calls another verb
|
|
before doing a <code>read()</code>, then either that verb must not suspend or else
|
|
you must arrange that no commands will be read from the connection in the
|
|
meantime. The most straightforward way to do this is to call
|
|
|
|
</p><pre>set_connection_option(player, "hold-input", 1)
|
|
</pre>
|
|
|
|
<p>
|
|
before any task suspension could happen, then make all of your calls to
|
|
<code>read()</code> and other code that might suspend, and finally call
|
|
|
|
</p><pre>set_connection_option(player, "hold-input", 0)
|
|
</pre>
|
|
|
|
<p>
|
|
to allow commands once again to be read and interpreted normally.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>force_input</b> <i>(obj <var>conn</var>, str <var>line</var> [, <var>at-front</var>])</i>
|
|
</dt><dd><a name="IDX89"></a>
|
|
Inserts the string <var>line</var> as an input task in the queue for the connection
|
|
<var>conn</var>, just as if it had arrived as input over the network. If
|
|
<var>at_front</var> is provided and true, then the new line of input is put at the
|
|
front of <var>conn</var>'s queue, so that it will be the very next line of input
|
|
processed even if there is already some other input in that queue. Raises
|
|
<code>E_INVARG</code> if <var>conn</var> does not specify a current connection and
|
|
<code>E_PERM</code> if the programmer is neither <var>conn</var> nor a wizard.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>flush_input</b> <i>(obj <var>conn</var> [<var>show-messages</var>])</i>
|
|
</dt><dd><a name="IDX90"></a>
|
|
Performs the same actions as if the connection <var>conn</var>'s defined flush
|
|
command had been received on that connection, i.e., removes all pending lines
|
|
of input from <var>conn</var>'s queue and, if <var>show-messages</var> is provided and
|
|
true, prints a message to <var>conn</var> listing the flushed lines, if any. See
|
|
the chapter on server assumptions about the database for more information about
|
|
a connection's defined flush command.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>output_delimiters</b> <i>(obj <var>player</var>)</i>
|
|
</dt><dd><a name="IDX91"></a>
|
|
Returns a list of two strings, the current <em>output prefix</em> and <em>output
|
|
suffix</em> for <var>player</var>. If <var>player</var> does not have an active network
|
|
connection, then <code>E_INVARG</code> is raised. If either string is currently
|
|
undefined, the value <code>""</code> is used instead. See the discussion of the
|
|
<code>PREFIX</code> and <code>SUFFIX</code> commands in the next chapter for more
|
|
information about the output prefix and suffix.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>boot_player</b> <i>(obj <var>player</var>)</i>
|
|
</dt><dd><a name="IDX92"></a>
|
|
Marks for disconnection any currently-active connection to the given
|
|
<var>player</var>. The connection will not actually be closed until the
|
|
currently-running task returns or suspends, but all MOO functions (such as
|
|
<code>notify()</code>, <code>connected_players()</code>, and the like) immediately behave
|
|
as if the connection no longer exists. If the programmer is not either a
|
|
wizard or the same as <var>player</var>, then <code>E_PERM</code> is raised. If there
|
|
is no currently-active connection to <var>player</var>, then this function does
|
|
nothing.
|
|
|
|
|
|
<p>
|
|
If there was a currently-active connection, then the following verb call is
|
|
made when the connection is actually closed:
|
|
|
|
|
|
|
|
</p><pre>$user_disconnected(<var>player</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
It is not an error if this verb does not exist; the call is simply skipped.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>connection_name</b> <i>(obj <var>player</var>)</i>
|
|
</dt><dd><a name="IDX93"></a>
|
|
Returns a network-specific string identifying the connection being used by the
|
|
given player. If the programmer is not a wizard and not <var>player</var>, then
|
|
<code>E_PERM</code> is raised. If <var>player</var> is not currently connected, then
|
|
<code>E_INVARG</code> is raised.
|
|
|
|
|
|
<p>
|
|
For the TCP/IP networking configurations, for in-bound connections, the string
|
|
has the form
|
|
|
|
</p><pre>"port <var>lport</var> from <var>host</var>, port <var>port</var>"
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>lport</var> is the decimal TCP listening port on which the connection
|
|
arrived, <var>host</var> is either the name or decimal TCP address of the host from
|
|
which the player is connected, and <var>port</var> is the decimal TCP port of the
|
|
connection on that host.
|
|
|
|
|
|
</p><p>
|
|
For outbound TCP/IP connections, the string has the form
|
|
|
|
</p><pre>"port <var>lport</var> to <var>host</var>, port <var>port</var>"
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>lport</var> is the decimal local TCP port number from which the
|
|
connection originated, <var>host</var> is either the name or decimal TCP address of
|
|
the host to which the connection was opened, and <var>port</var> is the decimal TCP
|
|
port of the connection on that host.
|
|
|
|
|
|
</p><p>
|
|
For the System V `local' networking configuration, the string is the UNIX login
|
|
name of the connecting user or, if no such name can be found, something of the
|
|
form
|
|
|
|
</p><pre>"User #<var>number</var>"
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>number</var> is a UNIX numeric user ID.
|
|
|
|
|
|
</p><p>
|
|
For the other networking configurations, the string is the same for all
|
|
connections and, thus, useless.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>set_connection_option</b> <i>(obj <var>conn</var>, str <var>option</var>, <var>value</var>)</i>
|
|
</dt><dd><a name="IDX94"></a>
|
|
Controls a number of optional behaviors associated the connection <var>conn</var>.
|
|
Raises <code>E_INVARG</code> if <var>conn</var> does not specify a current connection and
|
|
<code>E_PERM</code> if the programmer is neither <var>conn</var> nor a wizard. The
|
|
following values for <var>option</var> are currently supported:
|
|
|
|
|
|
<dl compact="compact">
|
|
|
|
<dt><code>"hold-input"</code>
|
|
</dt><dd>
|
|
If <var>value</var> is true, then input received on <var>conn</var> will never be treated
|
|
as a command; instead, it will remain in the queue until retrieved by a call to
|
|
<code>read()</code>.
|
|
|
|
</dd><dt><code>"client-echo"</code>
|
|
</dt><dd>
|
|
Send the Telnet Protocol <samp>`WONT ECHO'</samp> or <samp>`WILL ECHO'</samp> command,
|
|
depending on whether <var>value</var> is true or false, respectively. For clients
|
|
that support the Telnet Protocol, this should toggle whether or not the client
|
|
echoes locally the characters typed by the user. Note that the server itself
|
|
never echoes input characters under any circumstances. (This option is only
|
|
available under the TCP/IP networking configurations.)
|
|
|
|
</dd><dt><code>"binary"</code>
|
|
</dt><dd>
|
|
If <var>value</var> is true, then both input from and output to <var>conn</var> can
|
|
contain arbitrary bytes. Input from a connection in binary mode is not broken
|
|
into lines at all; it is delivered to either the read() function or the
|
|
built-in command parser as <em>binary strings</em>, in whatever size chunks come
|
|
back from the operating system. (See the early section on MOO value types for
|
|
a description of the binary string representation.) For output to a connection
|
|
in binary mode, the second argument to `notify()' must be a binary string; if
|
|
it is malformed, E_INVARG is raised.
|
|
|
|
</dd><dt><code>"flush-command"</code>
|
|
</dt><dd>
|
|
If <var>value</var> is a non-empty string, then it becomes the new <em>flush</em>
|
|
command for this connection, by which the player can flush all queued input
|
|
that has not yet been processed by the server. If <var>value</var> is not a
|
|
non-empty string, then <var>conn</var> is set to have no flush command at all. The
|
|
default value of this option can be set via the property
|
|
<code>$server_options.default_flush_command</code>; see the chapter on server
|
|
assumptions about the database for details.
|
|
</dd></dl>
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>connection_options</b> <i>(obj <var>conn</var>)</i>
|
|
</dt><dd><a name="IDX95"></a>
|
|
Returns a list of <code>{<var>name</var>, <var>value</var>}</code> pairs describing the
|
|
current settings of all of the allowed options for the connection <var>conn</var>.
|
|
Raises <code>E_INVARG</code> if <var>conn</var> does not specify a current connection and
|
|
<code>E_PERM</code> if the programmer is neither <var>conn</var> nor a wizard.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> value <b>connection_option</b> <i>(obj <var>conn</var>, str <var>name</var>)</i>
|
|
</dt><dd><a name="IDX96"></a>
|
|
Returns the current setting of the option <var>name</var> for the connection
|
|
<var>conn</var>. Raises <code>E_INVARG</code> if <var>conn</var> does not specify a current
|
|
connection and <code>E_PERM</code> if the programmer is neither <var>conn</var> nor a
|
|
wizard.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> obj <b>open_network_connection</b> <i>(<var>value</var>, ...)</i>
|
|
</dt><dd><a name="IDX97"></a>
|
|
Establishes a network connection to the place specified by the arguments and
|
|
more-or-less pretends that a new, normal player connection has been established
|
|
from there. The new connection, as usual, will not be logged in initially and
|
|
will have a negative object number associated with it for use with
|
|
<code>read()</code>, <code>notify()</code>, and <code>boot_player()</code>. This object number
|
|
is the value returned by this function.
|
|
|
|
|
|
<p>
|
|
If the programmer is not a wizard or if the <code>OUTBOUND_NETWORK</code> compilation
|
|
option was not used in building the server, then <code>E_PERM</code> is raised. If
|
|
the network connection cannot be made for some reason, then other errors will
|
|
be returned, depending upon the particular network implementation in use.
|
|
|
|
|
|
</p><p>
|
|
For the TCP/IP network implementations (the only ones as of this writing that
|
|
support outbound connections), there must be two arguments, a string naming a
|
|
host (possibly using the numeric Internet syntax) and an integer specifying a TCP
|
|
port. If a connection cannot be made because the host does not exist, the port
|
|
does not exist, the host is not reachable or refused the connection,
|
|
<code>E_INVARG</code> is raised. If the connection cannot be made for other
|
|
reasons, including resource limitations, then <code>E_QUOTA</code> is raised.
|
|
|
|
|
|
</p><p>
|
|
The outbound connection process involves certain steps that can take quite a
|
|
long time, during which the server is not doing anything else, including
|
|
responding to user commands and executing MOO tasks. See the chapter on
|
|
server assumptions about the database for details about how the server limits
|
|
the amount of time it will wait for these steps to successfully complete.
|
|
|
|
|
|
</p><p>
|
|
It is worth mentioning one tricky point concerning the use of this function.
|
|
Since the server treats the new connection pretty much like any normal player
|
|
connection, it will naturally try to parse any input from that connection as
|
|
commands in the usual way. To prevent this treatment, you should use
|
|
<code>set_connection_option()</code> to set the <code>"hold-input"</code> option true on
|
|
the connection.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> value <b>listen</b> <i>(obj <var>object</var>, <var>point</var> [, <var>print-messages</var>])</i>
|
|
</dt><dd><a name="IDX98"></a>
|
|
Create a new point at which the server will listen for network connections,
|
|
just as it does normally. <var>Object</var> is the object whose verbs
|
|
<code>do_login_command</code>, <code>do_command</code>, <code>do_out_of_band_command</code>,
|
|
<code>user_connected</code>, <code>user_created</code>, <code>user_reconnected</code>,
|
|
<code>user_disconnected</code>, and <code>user_client_disconnected</code> will be called at
|
|
appropriate points, just as these verbs are called on <code>#0</code> for normal
|
|
connections. (See the chapter on server assumptions about the database for the
|
|
complete story on when these functions are called.) <var>Point</var> is a
|
|
network-configuration-specific parameter describing the listening point. If
|
|
<var>print-messages</var> is provided and true, then the various
|
|
database-configurable messages (also detailed in the chapter on server
|
|
assumptions) will be printed on connections received at the new listening
|
|
point. <code>Listen()</code> returns <var>canon</var>, a `canonicalized' version of
|
|
<var>point</var>, with any configuration-specific defaulting or aliasing accounted
|
|
for.
|
|
|
|
|
|
<p>
|
|
This raises <code>E_PERM</code> if the programmer is not a wizard, <code>E_INVARG</code> if
|
|
<var>object</var> is invalid or there is already a listening point described by
|
|
<var>point</var>, and <code>E_QUOTA</code> if some network-configuration-specific error
|
|
occurred.
|
|
|
|
|
|
</p><p>
|
|
For the TCP/IP configurations, <var>point</var> is a TCP port number on which to
|
|
listen and <var>canon</var> is equal to <var>point</var> unless <var>point</var> is zero, in
|
|
which case <var>canon</var> is a port number assigned by the operating system.
|
|
|
|
|
|
</p><p>
|
|
For the local multi-user configurations, <var>point</var> is the UNIX file name to
|
|
be used as the connection point and <var>canon</var> is always equal to <var>point</var>.
|
|
|
|
|
|
</p><p>
|
|
In the single-user configuration, the can be only one listening point at a
|
|
time; <var>point</var> can be any value at all and <var>canon</var> is always zero.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>unlisten</b> <i>(<var>canon</var>)</i>
|
|
</dt><dd><a name="IDX99"></a>
|
|
Stop listening for connections on the point described by <var>canon</var>, which
|
|
should be the second element of some element of the list returned by
|
|
<code>listeners()</code>. Raises <code>E_PERM</code> if the programmer is not a wizard and
|
|
<code>E_INVARG</code> if there does not exist a listener with that description.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>listeners</b> <i>()</i>
|
|
</dt><dd><a name="IDX100"></a>
|
|
Returns a list describing all existing listening points, including the default
|
|
one set up automatically by the server when it was started (unless that one has
|
|
since been destroyed by a call to <code>unlisten()</code>). Each element of the list
|
|
has the following form:
|
|
|
|
|
|
|
|
<pre>{<var>object</var>, <var>canon</var>, <var>print-messages</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>object</var> is the first argument given in the call to <code>listen()</code>
|
|
to create this listening point, <var>print-messages</var> is true if the third
|
|
argument in that call was provided and true, and <var>canon</var> was the value
|
|
returned by that call. (For the initial listening point, <var>object</var> is
|
|
<code>#0</code>, <var>canon</var> is determined by the command-line arguments or a
|
|
network-configuration-specific default, and <var>print-messages</var> is true.)
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
Please note that there is nothing special about the initial listening point
|
|
created by the server when it starts; you can use <code>unlisten()</code> on it just
|
|
as if it had been created by <code>listen()</code>. This can be useful; for example,
|
|
under one of the TCP/IP configurations, you might start up your server on some
|
|
obscure port, say 12345, connect to it by yourself for a while, and then open
|
|
it up to normal users by evaluating the statments
|
|
|
|
</p><pre>unlisten(12345); listen(#0, 7777, 1)
|
|
</pre>
|
|
|
|
|
|
|
|
<h3><a name="SEC53" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC53">Operations Involving Times and Dates</a></h3>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>time</b> <i>()</i>
|
|
</dt><dd><a name="IDX101"></a>
|
|
Returns the current time, represented as the number of seconds that have
|
|
elapsed since midnight on 1 January 1970, Greenwich Mean Time.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>ctime</b> <i>([int <var>time</var>])</i>
|
|
</dt><dd><a name="IDX102"></a>
|
|
Interprets <var>time</var> as a time, using the same representation as given in the
|
|
description of <code>time()</code>, above, and converts it into a 28-character,
|
|
human-readable string in the following format:
|
|
|
|
|
|
|
|
<pre>Mon Aug 13 19:13:20 1990 PDT
|
|
</pre>
|
|
|
|
<p>
|
|
If the current day of the month is less than 10, then an extra blank appears
|
|
between the month and the day:
|
|
|
|
|
|
|
|
</p><pre>Mon Apr 1 14:10:43 1991 PST
|
|
</pre>
|
|
|
|
<p>
|
|
If <var>time</var> is not provided, then the current time is used.
|
|
|
|
|
|
</p><p>
|
|
Note that <code>ctime()</code> interprets <var>time</var> for the local time zone of the
|
|
computer on which the MOO server is running.
|
|
</p></dd></dl>
|
|
|
|
|
|
|
|
|
|
<h3><a name="SEC54" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC54">MOO-Code Evaluation and Task Manipulation</a></h3>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>raise</b> <i>(<var>code</var> [, str <var>message</var> [, <var>value</var>]])</i>
|
|
</dt><dd><a name="IDX103"></a>
|
|
Raises <var>code</var> as an error in the same way as other MOO expressions,
|
|
statements, and functions do. <var>Message</var>, which defaults to the value of
|
|
<code>tostr(<var>code</var>)</code>, and <var>value</var>, which defaults to zero, are made
|
|
available to any <code>try</code>-<code>except</code> statements that catch the error. If
|
|
the error is not caught, then <var>message</var> will appear on the first line of
|
|
the traceback printed to the user.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> value <b>call_function</b> <i>(str <var>func-name</var>, <var>arg</var>, ...)</i>
|
|
</dt><dd><a name="IDX104"></a>
|
|
Calls the built-in function named <var>func-name</var>, passing the given arguments,
|
|
and returns whatever that function returns. Raises <code>E_INVARG</code> if
|
|
<var>func-name</var> is not recognized as the name of a known built-in function.
|
|
This allows you to compute the name of the function to call and, in particular,
|
|
allows you to write a call to a built-in function that may or may not exist in
|
|
the particular version of the server you're using.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>function_info</b> <i>([str <var>name</var>])</i>
|
|
</dt><dd><a name="IDX105"></a>
|
|
Returns descriptions of the built-in functions available on the server. If
|
|
<var>name</var> is provided, only the description of the function with that name is
|
|
returned. If <var>name</var> is omitted, a list of descriptions is returned, one
|
|
for each function available on the server. Raised <code>E_INVARG</code> if
|
|
<var>name</var> is provided but no function with that name is available on the
|
|
server.
|
|
|
|
|
|
<p>
|
|
Each function description is a list of the following form:
|
|
|
|
|
|
|
|
</p><pre>{<var>name</var>, <var>min-args</var>, <var>max-args</var>, <var>types</var>
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>name</var> is the name of the built-in function, <var>min-args</var> is the
|
|
minimum number of arguments that must be provided to the function,
|
|
<var>max-args</var> is the maximum number of arguments that can be provided to the
|
|
function or <code>-1</code> if there is no maximum, and <var>types</var> is a list of
|
|
<var>max-args</var> integers (or <var>min-args</var> if <var>max-args</var> is <code>-1</code>),
|
|
each of which represents the type of argument required in the corresponding
|
|
position. Each type number is as would be returned from the <code>typeof()</code>
|
|
built-in function except that <code>-1</code> indicates that any type of value is
|
|
acceptable and <code>-2</code> indicates that either integers or floating-point
|
|
numbers may be given. For example, here are several entries from the list:
|
|
|
|
|
|
|
|
</p><pre>{"listdelete", 2, 2, {4, 0}}
|
|
{"suspend", 0, 1, {0}}
|
|
{"server_log", 1, 2, {2, -1}}
|
|
{"max", 1, -1, {-2}}
|
|
{"tostr", 0, -1, {}}
|
|
</pre>
|
|
|
|
<p>
|
|
<code>Listdelete()</code> takes exactly 2 arguments, of which the first must be a
|
|
list (<code>LIST == 4</code>) and the second must be an integer (<code>INT == 0</code>).
|
|
<code>Suspend()</code> has one optional argument that, if provided, must be an
|
|
integer. <code>Server_log()</code> has one required argument that must be a string
|
|
(<code>STR == 2</code>) and one optional argument that, if provided, may be of any
|
|
type. <code>Max()</code> requires at least one argument but can take any number
|
|
above that, and the first argument must be either an integer or a
|
|
floating-point number; the type(s) required for any other arguments can't be
|
|
determined from this description. Finally, <code>tostr()</code> takes any number of
|
|
arguments at all, but it can't be determined from this description which
|
|
argument types would be acceptable in which positions.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>eval</b> <i>(str <var>string</var>)</i>
|
|
</dt><dd><a name="IDX106"></a>
|
|
The MOO-code compiler processes <var>string</var> as if it were to be the program
|
|
associated with some verb and, if no errors are found, that fictional verb is
|
|
invoked. If the programmer is not, in fact, a programmer, then <code>E_PERM</code>
|
|
is raised. The normal result of calling <code>eval()</code> is a two element list.
|
|
The first element is true if there were no compilation errors and false
|
|
otherwise. The second element is either the result returned from the fictional
|
|
verb (if there were no compilation errors) or a list of the compiler's error
|
|
messages (otherwise).
|
|
|
|
|
|
<p>
|
|
When the fictional verb is invoked, the various built-in variables have values
|
|
as shown below:
|
|
|
|
|
|
|
|
</p><pre>player the same as in the calling verb
|
|
this #-1
|
|
caller the same as the initial value of <code>this</code> in the calling verb
|
|
|
|
args {}
|
|
argstr ""
|
|
|
|
verb ""
|
|
dobjstr ""
|
|
dobj #-1
|
|
prepstr ""
|
|
iobjstr ""
|
|
iobj #-1
|
|
</pre>
|
|
|
|
<p>
|
|
The fictional verb runs with the permissions of the programmer and as if its
|
|
<samp>`d'</samp> permissions bit were on.
|
|
|
|
|
|
|
|
</p><pre>eval("return 3 + 4;") => {1, 7}
|
|
</pre>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>set_task_perms</b> <i>(obj <var>who</var>)</i>
|
|
</dt><dd><a name="IDX107"></a>
|
|
Changes the permissions with which the currently-executing verb is running to
|
|
be those of <var>who</var>. If the programmer is neither <var>who</var> nor a wizard,
|
|
then <code>E_PERM</code> is raised.
|
|
|
|
|
|
|
|
<blockquote>
|
|
<p>
|
|
<strong>Note</strong>: This does not change the owner of the currently-running verb,
|
|
only the permissions of this particular invocation. It is used in verbs owned
|
|
by wizards to make themselves run with lesser (usually non-wizard) permissions.
|
|
</p></blockquote>
|
|
|
|
</dd></dl>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> obj <b>caller_perms</b> <i>()</i>
|
|
</dt><dd><a name="IDX108"></a>
|
|
Returns the permissions in use by the verb that called the currently-executing
|
|
verb. If the currently-executing verb was not called by another verb (i.e., it
|
|
is the first verb called in a command or server task), then
|
|
<code>caller_perms()</code> returns <code>#-1</code>.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>ticks_left</b> <i>()</i>
|
|
</dt><dd><a name="IDX109"></a>
|
|
</dd><dt><u>Function:</u> int <b>seconds_left</b> <i>()</i>
|
|
</dt><dd><a name="IDX110"></a>
|
|
These two functions return the number of ticks or seconds (respectively) left
|
|
to the current task before it will be forcibly terminated. These are useful,
|
|
for example, in deciding when to call <samp>`suspend()'</samp> to continue a long-lived
|
|
computation.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>task_id</b> <i>()</i>
|
|
</dt><dd><a name="IDX111"></a>
|
|
Returns the non-zero, non-negative integer identifier for the
|
|
currently-executing task. Such integers are randomly selected for each task and
|
|
can therefore safely be used in circumstances where unpredictability is
|
|
required.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> value <b>suspend</b> <i>([int <var>seconds</var>])</i>
|
|
</dt><dd><a name="IDX112"></a>
|
|
Suspends the current task, and resumes it after at least <var>seconds</var> seconds.
|
|
(If <var>seconds</var> is not provided, the task is suspended indefinitely; such a
|
|
task can only be resumed by use of the <code>resume()</code> function.) When the
|
|
task is resumed, it will have a full quota of ticks and seconds. This function
|
|
is useful for programs that run for a long time or require a lot of ticks. If
|
|
<var>seconds</var> is negative, then <code>E_INVARG</code> is raised. <code>Suspend()</code>
|
|
returns zero unless it was resumed via <code>resume()</code>, in which case it
|
|
returns the second argument given to that function.
|
|
|
|
|
|
<p>
|
|
In some sense, this function forks the `rest' of the executing task. However,
|
|
there is a major difference between the use of <samp>`suspend(<var>seconds</var>)'</samp>
|
|
and the use of the <samp>`fork (<var>seconds</var>)'</samp>. The <samp>`fork'</samp> statement
|
|
creates a new task (a <em>forked task</em>) while the currently-running task still
|
|
goes on to completion, but a <code>suspend()</code> suspends the currently-running
|
|
task (thus making it into a <em>suspended task</em>). This difference may be best
|
|
explained by the following examples, in which one verb calls another:
|
|
|
|
|
|
|
|
</p><pre>.program #0:caller_A
|
|
#0.prop = 1;
|
|
#0:callee_A();
|
|
#0.prop = 2;
|
|
.
|
|
|
|
.program #0:callee_A
|
|
fork(5)
|
|
#0.prop = 3;
|
|
endfork
|
|
.
|
|
|
|
.program #0:caller_B
|
|
#0.prop = 1;
|
|
#0:callee_B();
|
|
#0.prop = 2;
|
|
.
|
|
|
|
.program #0:callee_B
|
|
suspend(5);
|
|
#0.prop = 3;
|
|
.
|
|
</pre>
|
|
|
|
<p>
|
|
Consider <code>#0:caller_A</code>, which calls <code>#0:callee_A</code>. Such a task would
|
|
assign 1 to <code>#0.prop</code>, call <code>#0:callee_A</code>, fork a new task, return to
|
|
<code>#0:caller_A</code>, and assign 2 to <code>#0.prop</code>, ending this task. Five
|
|
seconds later, if the forked task had not been killed, then it would begin to
|
|
run; it would assign 3 to <code>#0.prop</code> and then stop. So, the final value of
|
|
<code>#0.prop</code> (i.e., the value after more than 5 seconds) would be 3.
|
|
|
|
|
|
</p><p>
|
|
Now consider <code>#0:caller_B</code>, which calls <code>#0:callee_B</code> instead of
|
|
<code>#0:callee_A</code>. This task would assign 1 to <code>#0.prop</code>, call
|
|
<code>#0:callee_B</code>, and suspend. Five seconds later, if the suspended task had
|
|
not been killed, then it would resume; it would assign 3 to <code>#0.prop</code>,
|
|
return to <code>#0:caller_B</code>, and assign 2 to <code>#0.prop</code>, ending the task.
|
|
So, the final value of <code>#0.prop</code> (i.e., the value after more than 5
|
|
seconds) would be 2.
|
|
|
|
|
|
</p><p>
|
|
A suspended task, like a forked task, can be described by the
|
|
<code>queued_tasks()</code> function and killed by the <code>kill_task()</code> function.
|
|
Suspending a task does not change its task id. A task can be suspended again
|
|
and again by successive calls to <code>suspend()</code>.
|
|
|
|
|
|
</p><p>
|
|
By default, there is no limit to the number of tasks any player may suspend,
|
|
but such a limit can be imposed from within the database. See the chapter on
|
|
server assumptions about the database for details.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>resume</b> <i>(int <var>task-id</var> [, <var>value</var>])</i>
|
|
</dt><dd><a name="IDX113"></a>
|
|
Immediately ends the suspension of the suspended task with the given
|
|
<var>task-id</var>; that task's call to <code>suspend()</code> will return <var>value</var>,
|
|
which defaults to zero. If <var>value</var> is of type <code>ERR</code>, it will be
|
|
raised, rather than returned, in the suspended task. <code>Resume()</code> raises
|
|
<code>E_INVARG</code> if <var>task-id</var> does not specify an existing suspended task
|
|
and <code>E_PERM</code> if the programmer is neither a wizard nor the owner of the
|
|
specified task.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>queue_info</b> <i>([obj <var>player</var>])</i>
|
|
</dt><dd><a name="IDX114"></a>
|
|
If <var>player</var> is omitted, returns a list of object numbers naming all players
|
|
that currently have active task queues inside the server. If <var>player</var> is
|
|
provided, returns the number of background tasks currently queued for that
|
|
user. It is guaranteed that <code>queue_info(<var>X</var>)</code> will return zero for
|
|
any <var>X</var> not in the result of <code>queue_info()</code>.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>queued_tasks</b> <i>()</i>
|
|
</dt><dd><a name="IDX115"></a>
|
|
Returns information on each of the background tasks (i.e., forked, suspended or
|
|
reading) owned by the programmer (or, if the programmer is a wizard, all queued
|
|
tasks). The returned value is a list of lists, each of which encodes certain
|
|
information about a particular queued task in the following format:
|
|
|
|
|
|
|
|
<pre>{<var>task-id</var>, <var>start-time</var>, <var>x</var>, <var>y</var>,
|
|
<var>programmer</var>, <var>verb-loc</var>, <var>verb-name</var>, <var>line</var>, <var>this</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>task-id</var> is an integer identifier for this queued task,
|
|
<var>start-time</var> is the time after which this task will begin execution (in
|
|
<code>time()</code> format), <var>x</var> and <var>y</var> are obsolete values that are no
|
|
longer interesting, <var>programmer</var> is the permissions with which this task
|
|
will begin execution (and also the player who <em>owns</em> this task),
|
|
<var>verb-loc</var> is the object on which the verb that forked this task was
|
|
defined at the time, <var>verb-name</var> is that name of that verb, <var>line</var> is
|
|
the number of the first line of the code in that verb that this task will
|
|
execute, and <var>this</var> is the value of the variable <samp>`this'</samp> in that verb.
|
|
For reading tasks, <var>start-time</var> is <code>-1</code>.
|
|
|
|
|
|
</p><p>
|
|
The <var>x</var> and <var>y</var> fields are now obsolete and are retained only for
|
|
backward-compatibility reasons. They may be reused for new purposes in some
|
|
future version of the server.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>kill_task</b> <i>(int <var>task-id</var>)</i>
|
|
</dt><dd><a name="IDX116"></a>
|
|
Removes the task with the given <var>task-id</var> from the queue of waiting tasks.
|
|
If the programmer is not the owner of that task and not a wizard, then
|
|
<code>E_PERM</code> is raised. If there is no task on the queue with the given
|
|
<var>task-id</var>, then <code>E_INVARG</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>callers</b> <i>([<var>include-line-numbers</var>])</i>
|
|
</dt><dd><a name="IDX117"></a>
|
|
Returns information on each of the verbs and built-in functions currently
|
|
waiting to resume execution in the current task. When one verb or function
|
|
calls another verb or function, execution of the caller is temporarily
|
|
suspended, pending the called verb or function returning a value. At any given
|
|
time, there could be several such pending verbs and functions: the one that
|
|
called the currently executing verb, the verb or function that called that one,
|
|
and so on. The result of <code>callers()</code> is a list, each element of which
|
|
gives information about one pending verb or function in the following format:
|
|
|
|
|
|
|
|
<pre>{<var>this</var>, <var>verb-name</var>, <var>programmer</var>, <var>verb-loc</var>, <var>player</var>, <var>line-number</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
For verbs, <var>this</var> is the initial value of the variable <samp>`this'</samp> in that
|
|
verb, <var>verb-name</var> is the name used to invoke that verb, <var>programmer</var> is
|
|
the player with whose permissions that verb is running, <var>verb-loc</var> is the
|
|
object on which that verb is defined, <var>player</var> is the initial value of the
|
|
variable <samp>`player'</samp> in that verb, and <var>line-number</var> indicates which line
|
|
of the verb's code is executing. The <var>line-number</var> element is included
|
|
only if the <var>include-line-numbers</var> argument was provided and true.
|
|
|
|
|
|
</p><p>
|
|
For functions, <var>this</var>, <var>programmer</var>, and <var>verb-loc</var> are all
|
|
<code>#-1</code>, <var>verb-name</var> is the name of the function, and <var>line-number</var>
|
|
is an index used internally to determine the current state of the built-in
|
|
function. The simplest correct test for a built-in function entry is
|
|
|
|
|
|
|
|
</p><pre>(VERB-LOC == #-1 && PROGRAMMER == #-1 && VERB-NAME != "")
|
|
</pre>
|
|
|
|
<p>
|
|
The first element of the list returned by <code>callers()</code> gives information on
|
|
the verb that called the currently-executing verb, the second element describes
|
|
the verb that called that one, and so on. The last element of the list
|
|
describes the first verb called in this task.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>task_stack</b> <i>(int <var>task-id</var> [, <var>include-line-numbers</var>])</i>
|
|
</dt><dd><a name="IDX118"></a>
|
|
Returns information like that returned by the <code>callers()</code> function, but
|
|
for the suspended task with the given <var>task-id</var>; the
|
|
<var>include-line-numbers</var> argument has the same meaning as in
|
|
<code>callers()</code>. Raises <code>E_INVARG</code> if <var>task-id</var> does not specify an
|
|
existing suspended task and <code>E_PERM</code> if the programmer is neither a wizard
|
|
nor the owner of the specified task.
|
|
</dd></dl>
|
|
|
|
|
|
|
|
|
|
<h3><a name="SEC55" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC55">Administrative Operations</a></h3>
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> str <b>server_version</b> <i>()</i>
|
|
</dt><dd><a name="IDX119"></a>
|
|
Returns a string giving the version number of the running MOO server.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>server_log</b> <i>(str <var>message</var> [, <var>is-error</var>])</i>
|
|
</dt><dd><a name="IDX120"></a>
|
|
The text in <var>message</var> is sent to the server log with a distinctive prefix
|
|
(so that it can be distinguished from server-generated messages). If the
|
|
programmer is not a wizard, then <code>E_PERM</code> is raised. If <var>is-error</var>
|
|
is provided and true, then <var>message</var> is marked in the server log as an
|
|
error.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> obj <b>renumber</b> <i>(obj <var>object</var>)</i>
|
|
</dt><dd><a name="IDX121"></a>
|
|
The object number of the object currently numbered <var>object</var> is changed to
|
|
be the least nonnegative object number not currently in use and the new object
|
|
number is returned. If <var>object</var> is not valid, then <code>E_INVARG</code> is
|
|
raised. If the programmer is not a wizard, then <code>E_PERM</code> is raised.
|
|
If there are no unused nonnegative object numbers less than <var>object</var>, then
|
|
<var>object</var> is returned and no changes take place.
|
|
|
|
|
|
<p>
|
|
The references to <var>object</var> in the parent/children and location/contents
|
|
hierarchies are updated to use the new object number, and any verbs, properties
|
|
and/or objects owned by <var>object</var> are also changed to be owned by the new
|
|
object number. The latter operation can be quite time consuming if the
|
|
database is large. No other changes to the database are performed; in
|
|
particular, no object references in property values or verb code are updated.
|
|
|
|
|
|
</p><p>
|
|
This operation is intended for use in making new versions of the LambdaCore
|
|
database from the then-current LambdaMOO database, and other similar
|
|
situations. Its use requires great care.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>reset_max_object</b> <i>()</i>
|
|
</dt><dd><a name="IDX122"></a>
|
|
The server's idea of the highest object number ever used is changed to be the
|
|
highest object number of a currently-existing object, thus allowing reuse of
|
|
any higher numbers that refer to now-recycled objects. If the programmer is
|
|
not a wizard, then <code>E_PERM</code> is raised.
|
|
|
|
|
|
<p>
|
|
This operation is intended for use in making new versions of the LambdaCore
|
|
database from the then-current LambdaMOO database, and other similar
|
|
situations. Its use requires great care.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> list <b>memory_usage</b> <i>()</i>
|
|
</dt><dd><a name="IDX123"></a>
|
|
On some versions of the server, this returns statistics concerning the server
|
|
consumption of system memory. The result is a list of lists, each in the
|
|
following format:
|
|
|
|
|
|
|
|
<pre>{<var>block-size</var>, <var>nused</var>, <var>nfree</var>}
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>block-size</var> is the size in bytes of a particular class of memory
|
|
fragments, <var>nused</var> is the number of such fragments currently in use in the
|
|
server, and <var>nfree</var> is the number of such fragments that have been reserved
|
|
for use but are currently free.
|
|
|
|
|
|
</p><p>
|
|
On servers for which such statistics are not available, <code>memory_usage()</code>
|
|
returns <code>{}</code>. The compilation option <code>USE_GNU_MALLOC</code> controls
|
|
whether or not statistics are available; if the option is not provided,
|
|
statistics are not available.
|
|
</p></dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>dump_database</b> <i>()</i>
|
|
</dt><dd><a name="IDX124"></a>
|
|
Requests that the server checkpoint the database at its next opportunity. It
|
|
is not normally necessary to call this function; the server automatically
|
|
checkpoints the database at regular intervals; see the chapter on server
|
|
assumptions about the database for details. If the programmer is not a wizard,
|
|
then <code>E_PERM</code> is raised.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> int <b>db_disk_size</b> <i>()</i>
|
|
</dt><dd><a name="IDX125"></a>
|
|
Returns the total size, in bytes, of the most recent full representation of the
|
|
database as one or more disk files. Raises <code>E_QUOTA</code> if, for some reason,
|
|
no such on-disk representation is currently available.
|
|
</dd></dl>
|
|
|
|
|
|
<p>
|
|
</p><dl>
|
|
<dt><u>Function:</u> none <b>shutdown</b> <i>([str <var>message</var>])</i>
|
|
</dt><dd><a name="IDX126"></a>
|
|
Requests that the server shut itself down at its next opportunity. Before
|
|
doing so, a notice (incorporating <var>message</var>, if provided) is printed to all
|
|
connected players. If the programmer is not a wizard, then <code>E_PERM</code> is
|
|
raised.
|
|
</dd></dl>
|
|
|
|
|
|
|
|
|
|
<h1><a name="SEC56" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC56">Server Commands and Database Assumptions</a></h1>
|
|
|
|
<p>
|
|
This chapter describes all of the commands that are built into the server and
|
|
every property and verb in the database specifically accessed by the server.
|
|
Aside from what is listed here, no assumptions are made by the server
|
|
concerning the contents of the database.
|
|
|
|
|
|
|
|
|
|
</p><h2><a name="SEC57" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC57">Built-in Commands</a></h2>
|
|
|
|
<p>
|
|
As was mentioned in the chapter on command parsing, there are five commands
|
|
whose interpretation is fixed by the server: <code>PREFIX</code>,
|
|
<code>OUTPUTPREFIX</code>, <code>SUFFIX</code>, <code>OUTPUTSUFFIX</code>, and <code>.program</code>.
|
|
The first four of these are intended for use by programs that connect to the
|
|
MOO, so-called `client' programs. The <code>.program</code> command is used by
|
|
programmers to associate a MOO program with a particular verb. The server can,
|
|
in addition, recognize a sixth special command on any or all connections, the
|
|
<em>flush</em> command.
|
|
|
|
|
|
</p><p>
|
|
The server also performs special processing on command lines that begin with
|
|
certain punctuation characters.
|
|
|
|
|
|
</p><p>
|
|
This section discusses these built-in pieces of the command-interpretation
|
|
process.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC58" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC58">Command-Output Delimiters</a></h3>
|
|
|
|
<p>
|
|
Every MOO network connection has associated with it two strings, the
|
|
<em>output prefix</em> and the <em>output suffix</em>. Just before executing a
|
|
command typed on that connection, the server prints the output prefix, if any,
|
|
to the player. Similarly, just after finishing the command, the output suffix,
|
|
if any, is printed to the player. Initially, these strings are not defined, so
|
|
no extra printing takes place.
|
|
|
|
|
|
</p><p>
|
|
The <code>PREFIX</code> and <code>SUFFIX</code> commands are used to set and clear these
|
|
strings. They have the following simple syntax:
|
|
|
|
|
|
|
|
</p><pre>PREFIX <var>output-prefix</var>
|
|
SUFFIX <var>output-suffix</var>
|
|
</pre>
|
|
|
|
<p>
|
|
That is, all text after the command name and any following spaces is used as
|
|
the new value of the appropriate string. If there is no non-blank text after
|
|
the command string, then the corresponding string is cleared. For
|
|
compatibility with some general MUD client programs, the server also recognizes
|
|
<code>OUTPUTPREFIX</code> as a synonym for <code>PREFIX</code> and <code>OUTPUTSUFFIX</code> as a
|
|
synonym for <code>SUFFIX</code>.
|
|
|
|
|
|
</p><p>
|
|
These commands are intended for use by programs connected to the MOO, so that
|
|
they can issue MOO commands and reliably determine the beginning and end of the
|
|
resulting output. For example, one editor-based client program sends this
|
|
sequence of commands on occasion:
|
|
|
|
|
|
|
|
</p><pre>PREFIX >>MOO-Prefix<<
|
|
SUFFIX >>MOO-Suffix<<
|
|
@list <var>object</var>:<var>verb</var> without numbers
|
|
PREFIX
|
|
SUFFIX
|
|
</pre>
|
|
|
|
<p>
|
|
The effect of which, in a LambdaCore-derived database, is to print out the code
|
|
for the named verb preceded by a line containing only <samp>`>>MOO-Prefix<<'</samp> and
|
|
followed by a line containing only <samp>`>>MOO-Suffix<<'</samp>. This enables the
|
|
editor to reliably extract the program text from the MOO output and show it to
|
|
the user in a separate editor window. There are many other possible uses.
|
|
|
|
|
|
</p><p>
|
|
The built-in function <code>output_delimiters()</code> can be used by MOO code to
|
|
find out the output prefix and suffix currently in effect on a particular
|
|
network connection.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC59" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC59">Programming</a></h3>
|
|
|
|
<p>
|
|
The <code>.program</code> command is a common way for programmers to associate a
|
|
particular MOO-code program with a particular verb. It has the following
|
|
syntax:
|
|
|
|
|
|
|
|
</p><pre>.program <var>object</var>:<var>verb</var>
|
|
...<var>several lines of MOO code</var>...
|
|
.
|
|
</pre>
|
|
|
|
<p>
|
|
That is, after typing the <code>.program</code> command, then all lines of input from
|
|
the player are considered to be a part of the MOO program being defined. This
|
|
ends as soon as the player types a line containing only a dot (<samp>`.'</samp>). When
|
|
that line is received, the accumulated MOO program is checked for proper MOO
|
|
syntax and, if correct, associated with the named verb.
|
|
|
|
|
|
</p><p>
|
|
If, at the time the line containing only a dot is processed, (a) the player is
|
|
not a programmer, (b) the player does not have write permission on the named
|
|
verb, or (c) the property <code>$server_options.protect_set_verb_code</code> exists
|
|
and has a true value and the player is not a wizard, then an error message is
|
|
printed and the named verb's program is not changed.
|
|
|
|
|
|
</p><p>
|
|
In the <code>.program</code> command, <var>object</var> may have one of three forms:
|
|
|
|
|
|
|
|
</p><ul>
|
|
<li>
|
|
|
|
The name of some object visible to the player. This is exactly like the kind
|
|
of matching done by the server for the direct and indirect objects of ordinary
|
|
commands. See the chapter on command parsing for details. Note that the
|
|
special names <samp>`me'</samp> and <samp>`here'</samp> may be used.
|
|
|
|
</li><li>
|
|
|
|
An object number, in the form <code>#<var>number</var></code>.
|
|
|
|
</li><li>
|
|
|
|
A <em>system property</em> (that is, a property on <code>#0</code>), in the form
|
|
<code>$<var>name</var></code>. In this case, the current value of <code>#0.<var>name</var></code>
|
|
must be a valid object.
|
|
</li></ul>
|
|
|
|
|
|
|
|
<h3><a name="SEC60" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC60">Flushing Unprocessed Input</a></h3>
|
|
|
|
<p>
|
|
It sometimes happens that a user changes their mind about having typed one or
|
|
more lines of input and would like to `untype' them before the server actually
|
|
gets around to processing them. If they react quickly enough, they can type
|
|
their connection's defined <em>flush</em> command; when the server first reads
|
|
that command from the network, it immediately and completely flushes any as-yet
|
|
unprocessed input from that user, printing a message to the user describing
|
|
just which lines of input were discarded, if any.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<em>Fine point:</em> The flush command is handled very early in the server's
|
|
processing of a line of input, before the line is entered into the task queue
|
|
for the connection and well before it is parsed into words like other commands.
|
|
For this reason, it must be typed exactly as it was defined, alone on the line,
|
|
without quotation marks, and without any spaces before or after it.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
When a connection is first accepted by the server, it is given an initial flush
|
|
command setting taken from the current default. This initial setting can be
|
|
changed later using the <code>set_connection_option()</code> command.
|
|
|
|
|
|
</p><p>
|
|
By default, each connection is initially given <samp>`.flush'</samp> as its flush
|
|
command. If the property <code>$server_options.default_flush_command</code> exists,
|
|
then its value overrides this default. If
|
|
<code>$server_options.default_flush_command</code> is a non-empty string, then that
|
|
string is the flush command for all new connections; otherwise, new connections
|
|
are initially given no flush command at all.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC61" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC61">Initial Punctuation in Commands</a></h3>
|
|
|
|
<p>
|
|
The server interprets command lines that begin with any of the following
|
|
characters specially:
|
|
|
|
|
|
|
|
</p><pre>" : ;
|
|
</pre>
|
|
|
|
<p>
|
|
Before processing the command, the initial punctuation character is replaced by
|
|
the corresponding word below, followed by a space:
|
|
|
|
|
|
|
|
</p><pre>say emote eval
|
|
</pre>
|
|
|
|
<p>
|
|
For example, the command line
|
|
|
|
|
|
|
|
</p><pre>"Hello, there.
|
|
</pre>
|
|
|
|
<p>
|
|
is transformed into
|
|
|
|
|
|
|
|
</p><pre>say Hello, there.
|
|
</pre>
|
|
|
|
<p>
|
|
before parsing.
|
|
|
|
|
|
|
|
|
|
</p><h2><a name="SEC62" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC62">Server Assumptions About the Database</a></h2>
|
|
|
|
<p>
|
|
There are a small number of circumstances under which the server directly and
|
|
specifically accesses a particular verb or property in the database. This
|
|
section gives a complete list of such circumstances.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC63" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC63">Server Options Set in the Database</a></h3>
|
|
|
|
<p>
|
|
Many optional behaviors of the server can be controlled from within the
|
|
database by creating the property <code>#0.server_options</code> (also known as
|
|
<code>$server_options</code>), assigning as its value a valid object number, and then
|
|
defining various properties on that object. At a number of times, the server
|
|
checks for whether the property <code>$server_options</code> exists and has an object
|
|
number as its value. If so, then the server looks for a variety of other
|
|
properties on that <code>$server_options</code> object and, if they exist, uses their
|
|
values to control how the server operates.
|
|
|
|
|
|
</p><p>
|
|
The specific properties searched for are each described in the appropriate
|
|
section below, but here is a brief list of all of the relevant properties for
|
|
ease of reference:
|
|
|
|
|
|
</p><dl compact="compact">
|
|
|
|
<dt><code>bg_seconds</code>
|
|
</dt><dd>
|
|
The number of seconds allotted to background tasks.
|
|
</dd><dt><code>bg_ticks</code>
|
|
</dt><dd>
|
|
The number of ticks allotted to background tasks.
|
|
</dd><dt><code>connect_timeout</code>
|
|
</dt><dd>
|
|
The maximum number of seconds to allow an un-logged-in in-bound connection to
|
|
remain open.
|
|
</dd><dt><code>default_flush_command</code>
|
|
</dt><dd>
|
|
The initial setting of each new connection's flush command.
|
|
</dd><dt><code>fg_seconds</code>
|
|
</dt><dd>
|
|
The number of seconds allotted to foreground tasks.
|
|
</dd><dt><code>fg_ticks</code>
|
|
</dt><dd>
|
|
The number of ticks allotted to foreground tasks.
|
|
</dd><dt><code>max_stack_depth</code>
|
|
</dt><dd>
|
|
The maximum number of levels of nested verb calls.
|
|
</dd><dt><code>name_lookup_timeout</code>
|
|
</dt><dd>
|
|
The maximum number of seconds to wait for a network hostname/address lookup.
|
|
</dd><dt><code>outbound_connect_timeout</code>
|
|
</dt><dd>
|
|
The maximum number of seconds to wait for an outbound network connection to
|
|
successfully open.
|
|
</dd><dt><code>protect_<var>property</var></code>
|
|
</dt><dd>
|
|
Restrict reading of built-in <var>property</var> to wizards.
|
|
</dd><dt><code>protect_<var>function</var></code>
|
|
</dt><dd>
|
|
Restrict use of built-in <var>function</var> to wizards.
|
|
</dd><dt><code>support_numeric_verbname_strings</code>
|
|
</dt><dd>
|
|
Enables use of an obsolete verb-naming mechanism.
|
|
</dd></dl>
|
|
|
|
|
|
|
|
<h3><a name="SEC64" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC64">Server Messages Set in the Database</a></h3>
|
|
|
|
<p>
|
|
There are a number of circumstances under which the server itself generates
|
|
messages on network connections. Most of these can be customized or even
|
|
eliminated from within the database. In each such case, a property on
|
|
<code>$server_options</code> is checked at the time the message would be printed. If
|
|
the property does not exist, a default message is printed. If the property
|
|
exists and its value is not a string or a list containing strings, then no
|
|
message is printed at all. Otherwise, the string(s) are printed in place of
|
|
the default message, one string per line. None of these messages are ever
|
|
printed on an outbound network connection created by the function
|
|
<code>open_network_connection()</code>.
|
|
|
|
|
|
</p><p>
|
|
The following list covers all of the customizable messages, showing for each
|
|
the name of the relevant property on <code>$server_options</code>, the default
|
|
message, and the circumstances under which the message is printed:
|
|
|
|
|
|
</p><dl compact="compact">
|
|
|
|
<dt><code>boot_msg = "*** Disconnected ***"</code>
|
|
</dt><dd>
|
|
The function <code>boot_player()</code> was called on this connection.
|
|
|
|
</dd><dt><code>connect_msg = "*** Connected ***"</code>
|
|
</dt><dd>
|
|
The user object that just logged in on this connection existed before
|
|
<code>$do_login_command()</code> was called.
|
|
|
|
</dd><dt><code>create_msg = "*** Created ***"</code>
|
|
</dt><dd>
|
|
The user object that just logged in on this connection did not exist before
|
|
<code>$do_login_command()</code> was called.
|
|
|
|
</dd><dt><code>recycle_msg = "*** Recycled ***"</code>
|
|
</dt><dd>
|
|
The logged-in user of this connection has been recycled or renumbered (via the
|
|
renumber() function).
|
|
|
|
</dd><dt><code>redirect_from_msg = "*** Redirecting connection to new port ***"</code>
|
|
</dt><dd>
|
|
The logged-in user of this connection has just logged in on some other
|
|
connection.
|
|
|
|
</dd><dt><code>redirect_to_msg = "*** Redirecting old connection to this port ***"</code>
|
|
</dt><dd>
|
|
The user who just logged in on this connection was already logged in on some
|
|
other connection.
|
|
|
|
</dd><dt><code>server_full_msg</code>
|
|
</dt><dd>
|
|
Default:
|
|
|
|
<pre>*** Sorry, but the server cannot accept any more connections right now.
|
|
*** Please try again later.
|
|
</pre>
|
|
|
|
This connection arrived when the server really couldn't accept any more
|
|
connections, due to running out of a critical operating system resource.
|
|
|
|
</dd><dt><code>timeout_msg = "*** Timed-out waiting for login. ***"</code>
|
|
</dt><dd>
|
|
This in-bound network connection was idle and un-logged-in for at least
|
|
<code>CONNECT_TIMEOUT</code> seconds (as defined in the file <samp>`options.h'</samp> when
|
|
the server was compiled).
|
|
</dd></dl>
|
|
|
|
|
|
<blockquote>
|
|
<p>
|
|
<em>Fine point:</em> If the network connection in question was received at a
|
|
listening point (established by the <samp>`listen()'</samp> function) handled by an
|
|
object <var>obj</var> other than <code>#0</code>, then system messages for that connection
|
|
are looked for on <code><var>obj</var>.server_options</code>; if that property does not
|
|
exist, then <code>$server_options</code> is used instead.
|
|
</p></blockquote>
|
|
|
|
|
|
|
|
<h3><a name="SEC65" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC65">Checkpointing the Database</a></h3>
|
|
|
|
<p>
|
|
The server maintains the entire MOO database in main memory, not on disk. It
|
|
is therefore necessary for it to dump the database to disk if it is to persist
|
|
beyond the lifetime of any particular server execution. The server is careful
|
|
to dump the database just before shutting down, of course, but it is also
|
|
prudent for it to do so at regular intervals, just in case something untoward
|
|
happens.
|
|
|
|
|
|
</p><p>
|
|
To determine how often to make these <em>checkpoints</em> of the database, the
|
|
server consults the value of <code>#0.dump_interval</code>. If it exists and its
|
|
value is an integer greater than or equal to 60, then it is taken as the number
|
|
of seconds to wait between checkpoints; otherwise, the server makes a new
|
|
checkpoint every 3600 seconds (one hour). If the value of
|
|
<code>#0.dump_interval</code> implies that the next checkpoint should be scheduled at
|
|
a time after 3:14:07 a.m. on Tuesday, January 19, 2038, then the server instead
|
|
uses the default value of 3600 seconds in the future.
|
|
|
|
|
|
</p><p>
|
|
The decision about how long to wait between checkpoints is made again
|
|
immediately after each one begins. Thus, changes to <code>#0.dump_interval</code>
|
|
will take effect after the next checkpoint happens.
|
|
|
|
|
|
</p><p>
|
|
Whenever the server begins to make a checkpoint, it makes the following verb
|
|
call:
|
|
|
|
|
|
|
|
</p><pre>$checkpoint_started()
|
|
</pre>
|
|
|
|
<p>
|
|
When the checkpointing process is complete, the server makes the following verb
|
|
call:
|
|
|
|
|
|
|
|
</p><pre>$checkpoint_finished(<var>success</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
where <var>success</var> is true if and only if the checkpoint was successfully
|
|
written on the disk. Checkpointing can fail for a number of reasons, usually
|
|
due to exhaustion of various operating system resources such as virtual memory
|
|
or disk space. It is not an error if either of these verbs does not exist; the
|
|
corresponding call is simply skipped.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC66" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC66">Accepting and Initiating Network Connections</a></h3>
|
|
|
|
<p>
|
|
When the server first accepts a new, incoming network connection, it is given
|
|
the low-level network address of computer on the other end. It immediately
|
|
attempts to convert this address into the human-readable host name that will be
|
|
entered in the server log and returned by the <code>connection_name()</code>
|
|
function. This conversion can, for the TCP/IP networking configurations,
|
|
involve a certain amount of communication with remote name servers, which can
|
|
take quite a long time and/or fail entirely. While the server is doing this
|
|
conversion, it is not doing anything else at all; in particular, it it not
|
|
responding to user commands or executing MOO tasks.
|
|
|
|
|
|
</p><p>
|
|
By default, the server will wait no more than 5 seconds for such a name lookup
|
|
to succeed; after that, it behaves as if the conversion had failed, using
|
|
instead a printable representation of the low-level address. If the property
|
|
<code>name_lookup_timeout</code> exists on <code>$server_options</code> and has an integer
|
|
as its value, that integer is used instead as the timeout interval.
|
|
|
|
|
|
</p><p>
|
|
When the <code>open_network_connection()</code> function is used, the server must
|
|
again do a conversion, this time from the host name given as an argument into
|
|
the low-level address necessary for actually opening the connection. This
|
|
conversion is subject to the same timeout as in the in-bound case; if the
|
|
conversion does not succeed before the timeout expires, the connection attempt
|
|
is aborted and <code>open_network_connection()</code> raises <code>E_QUOTA</code>.
|
|
|
|
|
|
</p><p>
|
|
After a successful conversion, though, the server must still wait for the
|
|
actual connection to be accepted by the remote computer. As before, this can
|
|
take a long time during which the server is again doing nothing else. Also as
|
|
before, the server will by default wait no more than 5 seconds for the
|
|
connection attempt to succeed; if the timeout expires,
|
|
<code>open_network_connection()</code> again raises <code>E_QUOTA</code>. This default
|
|
timeout interval can also be overridden from within the database, by defining
|
|
the property <code>outbound_connect_timeout</code> on <code>$server_options</code> with an
|
|
integer as its value.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC67" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC67">Associating Network Connections with Players</a></h3>
|
|
|
|
<p>
|
|
When a network connection is first made to the MOO, it is identified by a
|
|
unique, negative object number. Such a connection is said to be
|
|
<em>un-logged-in</em> and is not yet associated with any MOO player object.
|
|
|
|
|
|
</p><p>
|
|
Each line of input on an un-logged-in connection is first parsed into words in
|
|
the usual way (see the chapter on command parsing for details) and then these
|
|
words are passed as the arguments in a call to the verb
|
|
<code>$do_login_command()</code>. For example, the input line
|
|
|
|
|
|
|
|
</p><pre>connect Munchkin frebblebit
|
|
</pre>
|
|
|
|
<p>
|
|
would result in the following call being made:
|
|
|
|
|
|
|
|
</p><pre>$do_login_command("connect", "Munchkin", "frebblebit")
|
|
</pre>
|
|
|
|
<p>
|
|
In that call, the variable <code>player</code> will have as its value the negative
|
|
object number associated with the appropriate network connection. The
|
|
functions <code>notify()</code> and <code>boot_player()</code> can be used with such object
|
|
numbers to send output to and disconnect un-logged-in connections. Also, the
|
|
variable <code>argstr</code> will have as its value the unparsed command line as
|
|
received on the network connection.
|
|
|
|
|
|
</p><p>
|
|
If <code>$do_login_command()</code> returns a valid player object and the connection
|
|
is still open, then the connection is considered to have <em>logged into</em> that
|
|
player. The server then makes one of the following verbs calls, depending on
|
|
the player object that was returned:
|
|
|
|
|
|
|
|
</p><pre>$user_created(<var>player</var>)
|
|
$user_connected(<var>player</var>)
|
|
$user_reconnected(<var>player</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
The first of these is used if the returned object number is greater than the
|
|
value returned by the <code>max_object()</code> function before
|
|
<code>$do_login_command()</code> was invoked, that is, it is called if the returned
|
|
object appears to have been freshly created. If this is not the case, then one
|
|
of the other two verb calls is used. The <code>$user_connected()</code> call is used
|
|
if there was no existing active connection for the returned player object.
|
|
Otherwise, the <code>$user_reconnected()</code> call is used instead.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<em>Fine point:</em> If a user reconnects and the user's old and new connections
|
|
are on two different listening points being handled by different objects (see
|
|
the description of the <code>listen()</code> function for more details), then
|
|
<code>user_client_disconnected</code> is called for the old connection and
|
|
<code>user_connected</code> for the new one.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
If an in-bound network connection does not successfully log in within a certain
|
|
period of time, the server will automatically shut down the connection, thereby
|
|
freeing up the resources associated with maintaining it. Let <var>L</var> be the
|
|
object handling the listening point on which the connection was received (or
|
|
<code>#0</code> if the connection came in on the initial listening point). To
|
|
discover the timeout period, the server checks on
|
|
<code><var>L</var>.server_options</code> or, if it doesn't exist, on
|
|
<code>$server_options</code> for a <code>connect_timeout</code> property. If one is found
|
|
and its value is a positive integer, then that's the number of seconds the
|
|
server will use for the timeout period. If the <code>connect_timeout</code> property
|
|
exists but its value isn't a positive integer, then there is no timeout at
|
|
all. If the property doesn't exist, then the default timeout is 300 seconds.
|
|
|
|
|
|
</p><p>
|
|
When any network connection (even an un-logged-in or outbound one) is
|
|
terminated, by either the server or the client, then one of the following two
|
|
verb calls is made:
|
|
|
|
|
|
|
|
</p><pre>$user_disconnected(<var>player</var>)
|
|
$user_client_disconnected(<var>player</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
The first is used if the disconnection is due to actions taken by the server
|
|
(e.g., a use of the <code>boot_player()</code> function or the un-logged-in timeout
|
|
described above) and the second if the disconnection was initiated by the
|
|
client side.
|
|
|
|
|
|
</p><p>
|
|
It is not an error if any of these five verbs do not exist; the corresponding
|
|
call is simply skipped.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<strong>Note</strong>: Only one network connection can be controlling a given player
|
|
object at a given time; should a second connection attempt to log in as that
|
|
player, the first connection is unceremoniously closed (and
|
|
<code>$user_reconnected()</code> called, as described above). This makes it easy to
|
|
recover from various kinds of network problems that leave connections open but
|
|
inaccessible.
|
|
</p></blockquote>
|
|
|
|
<p>
|
|
When the network connection is first established, the null command is
|
|
automatically entered by the server, resulting in an initial call to
|
|
<code>$do_login_command()</code> with no arguments. This signal can be used by the
|
|
verb to print out a welcome message, for example.
|
|
|
|
|
|
|
|
</p><blockquote>
|
|
<p>
|
|
<strong>Warning</strong>: If there is no <code>$do_login_command()</code> verb defined, then
|
|
lines of input from un-logged-in connections are simply discarded. Thus, it is
|
|
<em>necessary</em> for any database to include a suitable definition for this
|
|
verb.
|
|
</p></blockquote>
|
|
|
|
|
|
|
|
<h3><a name="SEC68" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC68">Out-of-Band Commands</a></h3>
|
|
|
|
<p>
|
|
It is possible to compile the server with an option defining an
|
|
<em>out-of-band prefix</em> for commands. This is a string that the server will
|
|
check for at the beginning of every line of input from players, regardless of
|
|
whether or not those players are logged in and regardless of whether or not
|
|
reading tasks are waiting for input from those players. If a given line of
|
|
input begins with the defined out-of-band prefix (leading spaces, if any, are
|
|
<em>not</em> stripped before testing), then it is not treated as a normal command
|
|
or as input to any reading task. Instead, the line is parsed into a list of
|
|
words in the usual way and those words are given as the arguments in a call to
|
|
<code>$do_out_of_band_command()</code>. For example, if the out-of-band prefix were
|
|
defined to be <samp>`#$#'</samp>, then the line of input
|
|
|
|
|
|
|
|
</p><pre>#$# client-type fancy
|
|
</pre>
|
|
|
|
<p>
|
|
would result in the following call being made in a new server task:
|
|
|
|
|
|
|
|
</p><pre>$do_out_of_band_command("#$#", "client-type", "fancy")
|
|
</pre>
|
|
|
|
<p>
|
|
During the call to <code>$do_out_of_band_command()</code>, the variable <code>player</code>
|
|
is set to the object number representing the player associated with the
|
|
connection from which the input line came. Of course, if that connection has
|
|
not yet logged in, the object number will be negative. Also, the variable
|
|
<code>argstr</code> will have as its value the unparsed input line as received on the
|
|
network connection.
|
|
|
|
|
|
</p><p>
|
|
Out-of-band commands are intended for use by fancy client programs that may
|
|
generate asynchronous <em>events</em> of which the server must be notified. Since
|
|
the client cannot, in general, know the state of the player's connection
|
|
(logged-in or not, reading task or not), out-of-band commands provide the only
|
|
reliable client-to-server communications channel.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC69" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC69">The First Tasks Run By the Server</a></h3>
|
|
|
|
<p>
|
|
Whenever the server is booted, there are a few tasks it runs right at the
|
|
beginning, before accepting connections or getting the value of
|
|
<code>#0.dump_interval</code> to schedule the first checkpoint (see below for more
|
|
information on checkpoint scheduling).
|
|
|
|
|
|
</p><p>
|
|
First, the server calls <code>$user_disconnected()</code> once for each user who
|
|
was connected at the time the database file was written; this allows for any
|
|
cleaning up that's usually done when users disconnect (e.g., moving their
|
|
player objects back to some `home' location, etc.).
|
|
|
|
|
|
</p><p>
|
|
Next, it checks for the existence of the verb <code>$server_started()</code>. If
|
|
there is such a verb, then the server runs a task invoking that verb with no
|
|
arguments and with <code>player</code> equal to <code>#-1</code>. This is useful for
|
|
carefully scheduling checkpoints and for re-initializing any state that is not
|
|
properly represented in the database file (e.g., re-opening certain outbound
|
|
network connections, clearing out certain tables, etc.).
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC70" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC70">Controlling the Execution of Tasks</a></h3>
|
|
|
|
<p>
|
|
As described earlier, in the section describing MOO tasks, the server places
|
|
limits on the number of seconds for which any task may run continuously and the
|
|
number of "ticks," or low-level operations, any task may execute in one
|
|
unbroken period. By default, foreground tasks may use 30,000 ticks and five
|
|
seconds, and background tasks may use 15,000 ticks and three seconds. These
|
|
defaults can be overridden from within the database by defining any or all of
|
|
the following properties on <code>$server_options</code> and giving them integer
|
|
values:
|
|
|
|
|
|
</p><dl compact="compact">
|
|
|
|
<dt><code>bg_seconds</code>
|
|
</dt><dd>
|
|
The number of seconds allotted to background tasks.
|
|
</dd><dt><code>bg_ticks</code>
|
|
</dt><dd>
|
|
The number of ticks allotted to background tasks.
|
|
</dd><dt><code>fg_seconds</code>
|
|
</dt><dd>
|
|
The number of seconds allotted to foreground tasks.
|
|
</dd><dt><code>fg_ticks</code>
|
|
</dt><dd>
|
|
The number of ticks allotted to foreground tasks.
|
|
</dd></dl>
|
|
|
|
<p>
|
|
The server ignores the values of <code>fg_ticks</code> and <code>bg_ticks</code> if they
|
|
are less than 100 and similarly ignores <code>fg_seconds</code> and <code>bg_seconds</code>
|
|
if their values are less than 1. This may help prevent utter disaster should
|
|
you accidentally give them uselessly-small values.
|
|
|
|
|
|
</p><p>
|
|
Recall that command tasks and server tasks are deemed <em>foreground</em> tasks,
|
|
while forked, suspended, and reading tasks are defined as <em>background</em>
|
|
tasks. The settings of these variables take effect only at the beginning of
|
|
execution or upon resumption of execution after suspending or reading.
|
|
|
|
|
|
</p><p>
|
|
The server also places a limit on the number of levels of nested verb calls,
|
|
raising <code>E_MAXREC</code> from a verb-call expression if the limit is exceeded.
|
|
The limit is 50 levels by default, but this can be increased from within the
|
|
database by defining the <code>max_stack_depth</code> property on
|
|
<code>$server_options</code> and giving it an integer value greater than 50. The
|
|
maximum stack depth for any task is set at the time that task is created and
|
|
cannot be changed thereafter. This implies that suspended tasks, even after
|
|
being saved in and restored from the DB, are not affected by later changes to
|
|
$server_options.max_stack_depth.
|
|
|
|
|
|
</p><p>
|
|
Finally, the server can place a limit on the number of forked or suspended
|
|
tasks any player can have queued at a given time. Each time a <code>fork</code>
|
|
statement or a call to <code>suspend()</code> is executed in some verb, the server
|
|
checks for a property named <code>queued_task_limit</code> on the programmer. If
|
|
that property exists and its value is a non-negative integer, then that integer
|
|
is the limit. Otherwise, if <code>$server_options.queued_task_limit</code> exists
|
|
and its value is a non-negative integer, then that's the limit. Otherwise,
|
|
there is no limit. If the programmer already has a number of queued tasks that
|
|
is greater than or equal to the limit, <code>E_QUOTA</code> is raised instead of
|
|
either forking or suspending. Reading tasks are affected by the queued-task
|
|
limit.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC71" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC71">Controlling the Handling of Aborted Tasks</a></h3>
|
|
|
|
<p>
|
|
The server will abort the execution of tasks for either of two reasons:
|
|
|
|
</p><ol>
|
|
<li>an error was raised within the task but not caught, or
|
|
|
|
</li><li>the task exceeded the limits on ticks and/or seconds.
|
|
|
|
</li></ol>
|
|
|
|
<p>
|
|
In each case, after aborting the task, the server attempts to call a particular
|
|
<em>handler verb</em> within the database to allow code there to handle this
|
|
mishap in some appropriate way. If this verb call suspends or returns a true
|
|
value, then it is considered to have handled the situation completely and no
|
|
further processing will be done by the server. On the other hand, if the
|
|
handler verb does not exist, or if the call either returns a false value
|
|
without suspending or itself is aborted, the server takes matters into its own
|
|
hands.
|
|
|
|
|
|
</p><p>
|
|
First, an error message and a MOO verb-call stack <em>traceback</em> are
|
|
printed to the player who typed the command that created the original aborted
|
|
task, explaining why the task was aborted and where in the task the problem
|
|
occurred. Then, if the call to the handler verb was itself aborted, a second
|
|
error message and traceback are printed, describing that problem as well. Note
|
|
that if the handler-verb call itself is aborted, no further `nested' handler
|
|
calls are made; this policy prevents what might otherwise be quite a vicious
|
|
little cycle.
|
|
|
|
|
|
</p><p>
|
|
The specific handler verb, and the set of arguments it is passed, differs for
|
|
the two causes of aborted tasks.
|
|
|
|
|
|
</p><p>
|
|
If an error is raised and not caught, then the verb-call
|
|
|
|
</p><pre>$handle_uncaught_error(<var>code</var>, <var>msg</var>, <var>value</var>, <var>traceback</var>, <var>formatted</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
is made, where <var>code</var>, <var>msg</var>, <var>value</var>, and <var>traceback</var> are the
|
|
values that would have been passed to a handler in a <code>try</code>-<code>except</code>
|
|
statement and <var>formatted</var> is a list of strings being the lines of error and
|
|
traceback output that will be printed to the player if
|
|
<code>$handle_uncaught_error</code> returns false without suspending.
|
|
|
|
|
|
</p><p>
|
|
If a task runs out of ticks or seconds, then the verb-call
|
|
|
|
</p><pre>$handle_task_timeout(<var>resource</var>, <var>traceback</var>, <var>formatted</var>)
|
|
</pre>
|
|
|
|
<p>
|
|
is made, where <var>resource</var> is the appropriate one of the strings
|
|
<code>"ticks"</code> or <code>"seconds"</code>, and <var>traceback</var> and <var>formatted</var> are
|
|
as above.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC72" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC72">Matching in Command Parsing</a></h3>
|
|
|
|
<p>
|
|
In the process of matching the direct and indirect object strings in a command
|
|
to actual objects, the server uses the value of the <code>aliases</code> property, if
|
|
any, on each object in the contents of the player and the player's location.
|
|
For complete details, see the chapter on command parsing.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC73" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC73">Restricting Access to Built-in Properties and Functions</a></h3>
|
|
|
|
<p>
|
|
Whenever verb code attempts to read the value of a built-in property <var>prop</var>
|
|
on any object, the server checks to see if the property
|
|
<code>$server_options.protect_<var>prop</var></code> exists and has a true value. If so,
|
|
then <code>E_PERM</code> is raised if the programmer is not a wizard.
|
|
|
|
|
|
</p><p>
|
|
Whenever verb code calls a built-in function <code><var>func</var>()</code> and the caller
|
|
is not the object <code>#0</code>, the server checks to see if the property
|
|
<code>$server_options.protect_<var>func</var></code> exists and has a true value. If so,
|
|
then the server next checks to see if the verb <code>$bf_<var>func</var>()</code> exists;
|
|
if that verb exists, then the server calls it <em>instead</em> of the built-in
|
|
function, returning or raising whatever that verb returns or raises. If the
|
|
<code>$bf_<var>func</var>()</code> does not exist and the programmer is not a wizard, then
|
|
the server immediately raises <code>E_PERM</code>, <em>without</em> actually calling
|
|
the function. Otherwise (if the caller is <code>#0</code>, if
|
|
<code>$server_options.protect_<var>func</var></code> either doesn't exist or has a false
|
|
value, or if <code>$bf_<var>func</var>()</code> exists but the programmer is a wizard),
|
|
then the built-in function is called normally.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC74" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC74">Creating and Recycling Objects</a></h3>
|
|
|
|
<p>
|
|
Whenever the <code>create()</code> function is used to create a new object, that
|
|
object's <code>initialize</code> verb, if any, is called with no arguments. The call
|
|
is simply skipped if no such verb is defined on the object.
|
|
|
|
|
|
</p><p>
|
|
Symmetrically, just before the <code>recycle()</code> function actually destroys an
|
|
object, the object's <code>recycle</code> verb, if any, is called with no arguments.
|
|
Again, the call is simply skipped if no such verb is defined on the object.
|
|
|
|
|
|
</p><p>
|
|
Both <code>create()</code> and <code>recycle()</code> check for the existence of an
|
|
<code>ownership_quota</code> property on the owner of the newly-created or -destroyed
|
|
object. If such a property exists and its value is an integer, then it is
|
|
treated as a <em>quota</em> on object ownership. Otherwise, the following two
|
|
paragraphs do not apply.
|
|
|
|
|
|
</p><p>
|
|
The <code>create()</code> function checks whether or not the quota is positive; if
|
|
so, it is reduced by one and stored back into the <code>ownership_quota</code>
|
|
property on the owner. If the quota is zero or negative, the quota is
|
|
considered to be exhausted and <code>create()</code> raises <code>E_QUOTA</code>.
|
|
|
|
|
|
</p><p>
|
|
The <code>recycle()</code> function increases the quota by one and stores it back
|
|
into the <code>ownership_quota</code> property on the owner.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC75" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC75">Object Movement</a></h3>
|
|
|
|
<p>
|
|
During evaluation of a call to the <code>move()</code> function, the server can make
|
|
calls on the <code>accept</code> and <code>enterfunc</code> verbs defined on the
|
|
destination of the move and on the <code>exitfunc</code> verb defined on the source.
|
|
The rules and circumstances are somewhat complicated and are given in detail in
|
|
the description of the <code>move()</code> function.
|
|
|
|
|
|
|
|
|
|
</p><h3><a name="SEC76" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC76">Temporarily Enabling Obsolete Server Features</a></h3>
|
|
|
|
<p>
|
|
If the property <code>$server_options.support_numeric_verbname_strings</code> exists
|
|
and has a true value, then the server supports a obsolete mechanism for less
|
|
ambiguously referring to specific verbs in various built-in functions. For
|
|
more details, see the discussion given just following the description of the
|
|
<code>verbs()</code> function.
|
|
|
|
|
|
|
|
|
|
</p><h1><a name="SEC77" href="http://www.hayseed.net/MOO/manuals/ProgrammersManual_toc.html#TOC77">Function Index</a></h1>
|
|
<p>
|
|
Jump to:
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_a">a</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_b">b</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_c">c</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_d">d</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_e">e</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_f">f</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_i">i</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_k">k</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_l">l</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_m">m</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_n">n</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_o">o</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_p">p</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_q">q</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_r">r</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_s">s</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_t">t</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_u">u</a>
|
|
-
|
|
<a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#findex_v">v</a>
|
|
</p><p>
|
|
</p><h2><a name="findex_a">a</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX15">abs</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX22">acos</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX66">add_property</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX75">add_verb</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX21">asin</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX23">atan</a>
|
|
</li></dir>
|
|
<h2><a name="findex_b">b</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX45">binary_hash</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX92">boot_player</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX87">buffered_output_length</a>
|
|
</li></dir>
|
|
<h2><a name="findex_c">c</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX104">call_function</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX108">caller_perms</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX117">callers</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX30">ceil</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX58">children</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX55">chparent</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX69">clear_property</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX83">connected_players</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX84">connected_seconds</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX93">connection_name</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX96">connection_option</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX95">connection_options</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX19">cos</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX25">cosh</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX54">create</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX43">crypt</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX102">ctime</a>
|
|
</li></dir>
|
|
<h2><a name="findex_d">d</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX125">db_disk_size</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX38">decode_binary</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX67">delete_property</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX76">delete_verb</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX79">disassemble</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX124">dump_database</a>
|
|
</li></dir>
|
|
<h2><a name="findex_e">e</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX39">encode_binary</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX9">equal</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX106">eval</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX27">exp</a>
|
|
</li></dir>
|
|
<h2><a name="findex_f">f</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX16">floatstr(float</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX31">floor</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX90">flush_input</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX89">force_input</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX105">function_info</a>
|
|
</li></dir>
|
|
<h2><a name="findex_i">i</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX85">idle_seconds</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX35">index</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX68">is_clear_property</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX47">is_member</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX81">is_player</a>
|
|
</li></dir>
|
|
<h2><a name="findex_k">k</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX116">kill_task</a>
|
|
</li></dir>
|
|
<h2><a name="findex_l">l</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX33">length</a>, <a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX46">length</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX49">listappend</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX50">listdelete</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX98">listen</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX100">listeners</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX48">listinsert</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX51">listset</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX28">log</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX29">log10</a>
|
|
</li></dir>
|
|
<h2><a name="findex_m">m</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX40">match</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX14">max</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX61">max_object</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX123">memory_usage</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX13">min</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX62">move</a>
|
|
</li></dir>
|
|
<h2><a name="findex_n">n</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX86">notify</a>
|
|
</li></dir>
|
|
<h2><a name="findex_o">o</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX60">object_bytes</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX97">open_network_connection</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX91">output_delimiters</a>
|
|
</li></dir>
|
|
<h2><a name="findex_p">p</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX57">parent</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX1">pass</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX80">players</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX63">properties</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX64">property_info</a>
|
|
</li></dir>
|
|
<h2><a name="findex_q">q</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX114">queue_info</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX115">queued_tasks</a>
|
|
</li></dir>
|
|
<h2><a name="findex_r">r</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX103">raise</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX12">random</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX88">read</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX59">recycle</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX121">renumber</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX122">reset_max_object</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX113">resume</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX36">rindex</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX41">rmatch</a>
|
|
</li></dir>
|
|
<h2><a name="findex_s">s</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX110">seconds_left</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX120">server_log</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX119">server_version</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX94">set_connection_option</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX82">set_player_flag</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX65">set_property_info</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX107">set_task_perms</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX74">set_verb_args</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX78">set_verb_code</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX72">set_verb_info</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX52">setadd</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX53">setremove</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX126">shutdown</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX18">sin</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX24">sinh</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX17">sqrt</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX37">strcmp</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX44">string_hash</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX34">strsub</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX42">substitute</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX112">suspend</a>
|
|
</li></dir>
|
|
<h2><a name="findex_t">t</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX20">tan</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX26">tanh</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX111">task_id</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX118">task_stack</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX109">ticks_left</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX101">time</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX8">tofloat</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX5">toint</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX4">toliteral</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX6">tonum</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX7">toobj</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX3">tostr</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX32">trunc</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX2">typeof</a>
|
|
</li></dir>
|
|
<h2><a name="findex_u">u</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX99">unlisten</a>
|
|
</li></dir>
|
|
<h2><a name="findex_v">v</a></h2>
|
|
<dir>
|
|
<li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX56">valid</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX10">value_bytes</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX11">value_hash</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX73">verb_args</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX77">verb_code</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX71">verb_info</a>
|
|
</li><li><a href="http://www.hayseed.net/MOO/manuals/ProgrammersManual.html#IDX70">verbs</a>
|
|
</li></dir>
|
|
|
|
|
|
<p></p><hr><p>
|
|
This document was generated on 26 August 1999 using
|
|
<a href="http://web.archive.org/web/20090526023917/http://wwwinfo.cern.ch/dis/texi2html/">texi2html</a> 1.56k.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</p></body></html>
|
|
<!--
|
|
FILE ARCHIVED ON 2:39:17 May 26, 2009 AND RETRIEVED FROM THE
|
|
INTERNET ARCHIVE ON 7:48:28 Mar 26, 2012.
|
|
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
|
|
|
|
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
|
|
SECTION 108(a)(3)).
|
|
--> |