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.

As was mentioned in the chapter on command parsing, there are three commands
whose interpretation is fixed by the server: PREFIX, SUFFIX, and
.program. The first two of these are intended for use by programs that
connect to the MOO, so-called `client' programs. The .program command
is used by programmers to associate a MOO program with a particular verb.

The server also performs special processing on command lines that begin with
certain punctuation characters.

This section discusses these built-in pieces of the command-interpretation
process.

Every MOO network connection has associated with it two strings, the
output prefix and the output suffix. 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.

The PREFIX and SUFFIX commands are used to set and clear these
strings. They have the following simple syntax:

PREFIX output-prefix
SUFFIX output-suffix

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.

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:

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 >>MOO-Prefix<< and
followed by a line containing only >>MOO-Suffix<<. 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.

The built-in function output_delimiters() can be used by MOO code to
find out the output prefix and suffix currently in effect on a particular
network connection.

The .program command is a common way for programmers to associate a
particular MOO-code program with a particular verb. It has the following
syntax:

.program object:verb
...several lines of MOO code...
.

That is, after typing the .program 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 (.). When
that line is received, the accumulated MOO program is checked for proper MOO
syntax and, if correct, associated with the named verb.

In the .program command, object may have one of three forms:

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 me and here may be used.

An object number, in the form #number.

A system property (that is, a property on #0), in the form
$name. In this case, the current value of #0.name
must be a valid object.

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.

Whenever the server is booted, it checks for the existence of the verb
#0:server_started(). If there is such a verb, then the very first task
run is a server task invoking that verb with no arguments and with
player equal to #-1. This task runs even before the server gets
the value of #0.dump_interval to schedule the first checkpoint. (See
below for more information on checkpoint scheduling.)

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.

To determine how often to make these checkpoints of the database, the
server consults the value of #0.dump_interval. If it exists and its
value is a number 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).

The decision about how long to wait between checkpoints is made again
immediately after each one begins. Thus, changes to #0.dump_interval
will take effect after the next checkpoint happens.

Whenever the server begins to make a checkpoint, it makes the following verb
call:

#0:checkpoint_started()

When the checkpointing process is complete, the server makes the following verb
call:

#0:checkpoint_finished(success)

where success 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.

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
un-logged-in and is not yet associated with any MOO player object.

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
#0:do_login_command(). For example, the input line

connect Munchkin frebblebit

would result in the following call being made:

#0:do_login_command("connect", "Munchkin", "frebblebit")

In that call, the variable player will have as its value the negative
object number associated with the appropriate network connection. The
functions notify() and boot_player() can be used with such object
numbers to send output to and disconnect un-logged-in connections. Also, the
variable argstr will have as its value the unparsed command line as
received on the network connection.

If #0:do_login_command returns a valid player object, then the
connection is considered to have logged into that player. The server
then makes one of the following verbs calls, depending on the player object
that was returned:

The first of these is used if the returned object number is greater than the
value returned by the max_object() function before
#0:do_login_command 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 #0:user_connected call is used
if there was no existing active connection for the returned player object.
Otherwise, the #0:user_reconnected call is used instead.

When the network connection is terminated, either by the client side or though
the use of the boot_player() function, then one of the following two
verb calls is made:

#0:user_disconnected(player)
#0:user_client_disconnected(player)

The first is used if the disconnection is due to a use of the
boot_player() function and the second if the disconnection was initiated
by the client side.

It is not an error if any of these five verbs do not exist; the corresponding
call is simply skipped.

Note: 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
#0:user_reconnected called, as described above). This makes it easy to
recover from various kinds of network problems that leave connections open but
inaccessible.

When the network connection is first established, the null command is
automatically entered by the server, resulting in an initial call to
#0:do_login_command with no arguments. This signal can be used by the
verb to print out a welcome message, for example.

Warning: If there is no #0:do_login_command verb defined, then
the line of input is simply discarded. Thus, it is necessary for any
database to include a suitable definition for this verb.

It is possible to compile the server with an option defining an
out-of-band prefix 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
not 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
#0:do_out_of_band_command. For example, if the out-of-band prefix were
defined to be #$#, then the line of input

#$# client-type fancy

would result in the following call being made in a new server task:

#0:do_out_of_band_command("#$#", "client-type", "fancy")

During the call to #0:do_out_of_band_command, the variable player
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
argstr will have as its value the unparsed input line as received on the
network connection.

Out-of-band commands are intended for use by fancy client programs that may
generate asynchronous events 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.

In the process of matching the direct and indirect object strings in a command
to actual objects, the server uses the value of the aliases 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.

Whenever the create() function is used to create a new object, that
object's initialize verb, if any, is called with no arguments. The call
is simply skipped if no such verb is defined on the object.

Symmetrically, just before the recycle() function actually destroys an
object, the object's recycle verb, if any, is called with no arguments.
Again, the call is simply skipped if no such verb is defined on the object.

Both create() and recycle() check for the existence of an
ownership_quota property on the owner of the newly-created or -destroyed
object. If such a property exists and its value is a number, then it is
treated as a quota on object ownership. Otherwise, the following two
paragraphs do not apply.

The create() function checks whether or not the quota is positive; if
so, it is reduced by one and stored back into the ownership_quota
property on the owner. If the quota is zero or negative, the quota is
considered to be exhausted and create() returns E_QUOTA.

The recycle() function increases the quota by one and stores it back
into the ownership_quota property on the owner.

During evaluation of a call to the move() function, the server can make
calls on the accept and enterfunc verbs defined on the
destination of the move and on the exitfunc verb defined on the source.
The rules and circumstances are somewhat complicated and are given in detail in
the description of the move() function.