===== help $help ================================

The Help System

When a player types help, the following list of objects is consulted for .help properties: the player itself, all ancestors of player up to and including $player, and, if the current location is a room, the current location together with all ancestors of the current location back to and including $room. Each help property should have as value either an object or a list of objects (otherwise we just ignore it). These objects are then strung together as a list of `help databases' to be searched in order for the requested topic.

A help database (in the sense of anything that is usable by $player:help()) is any object having the following three verbs:

where string is a supposed help topic, returns a list of strings, i.e., actual help topics that this db knows about, or some boolean false value in the event that this db is clueless... If no arguments are given, this should return a list of all topics in the db

given one of the strings returned by :find_topics this either returns a list of strings (text to be spewed to the player) or returns 1 to indicate that it has already taken care of printing information to the player.

like get_topic, but instead returns the raw text of a help topic as a (download/upload) script

In short if :find_topic reports that a particular db knows about a given topicit returns the full topic name, so that :get_topic may be called on it later. :dump_topic is used by maintainers (see $wiz:@gethelp) to edit help topics.

$generic_help and $help

The Generic Help Database, $generic_help, is the parent class of a particular kind of help database of which $help is an instance. On help databases of this type, every help topic has a corresponding property, interpreted as follows:

this.(topic) = string
one-line help text.

this.(topic) = {"*<verb>*",@args}
call this:<verb>(args,dblist) to get text where dblist is the list of help objects that would have been consulted had the topic not been found on this object.

this.(topic) = other list of strings
multi-line help text

For the {"*<verb>*",...} form, the current verbs available are

{"*forward*", topic, @rest}
- get help text for topic and then append the lines of `rest'. rest may, in turn, begin with a "*<verb>*"...

{"*pass*", topic, @rest}
- get help text for topic from the first help database after this one that actually has help text for topic, and then append lines of `rest'. As with "*forward*" rest may, in turn, begin with a "*<verb>*"...

{"*subst*", @lines}
- All occurences of %[exp] in lines are replaced with the value of exp which is assumed to evaluate to a string. All lines beginning with %;exp are replaced with the value of exp which is assumed to evaluate to a list of strings. Evaluation is done using $no_one's permissions so exp in either case can only refer to public information.

{"*index*", title}
- returns a list of all topics in this database, arranged in columns. title is used as a heading for this index.

{"*objectdoc*", object}
- gets the documentation for the given object (i.e., object:help_msg()) N.B. as with all other *verb* arguments, object must be a string.

{"*verbdoc*", object, verbname}
- gets the documentation for the named verb on the given object (i.e., any strings at the beginning of said verbcode) Individual help dbs are free to define additional verbs that may be used in this context. $help itself defines the following additional such verbs:

- returns a list of all index topics in all databases in the search list. An index topic is one whose actual text is {"*index*", something}. When creating a help db, you should be sure to make an index topic.

- prints indices for all help databases in the search list.

It should be noted (once again) that help databases need not be children of $generic_help, so long as they have :find_topics/:get_topic/:dump_topic working as specified above.

===== help $housekeeper ==========================

The housekeeper is an object that can help keep other objects where they belong. New MOOs may want to add their own user interface for the housekeeper; here is some information that may be helpful.

To indicate what objects should be cleaned:

:add_cleanup(object[, requestor[, where]])
Ask the housekeeper to clean 'object' for 'requestor' to 'where'. Requestor defaults to 'player'. Where defaults to object.location.

:remove_cleanup(what[, requestor])
Remove 'what' from the cleanup list at 'requestor's request. Will remove it only if 'requestor' made the original request and owns the object or the destination.

To actually get the housekeeper to clean stuff up:

Clean up player's objects. Argument is 'up' or 'up!' for manually requested cleanups. 'up!' means to clean things even if it's against the housekeeper's better judgement.

:replace(object[, insist])
Clean up the indicated object. 'insist' is as in :cleanup.

Starts the housekeeper cleaning continuously, killing any previous continuous task. This should be called only when starting up a new MOO, or if something has gone wrong, as normally it will just keep going without any help.

Clean up all the places in housekeeper.public_places by getting rid of all contents not in their .residents lists. This is called by :continuous, so it doesn't need to be called directly.

To find out what's being cleaned to where for whom:

Show 'player' the personal cleanup list for 'whom', or the housekeeper's complete list if no argument is given.

Show 'player' a brief summary of eir personal cleanup list.


===== help $login ================================

This object manages command parsing for unconnected players and governs the initiation of an actual connection. There are verbs pertaining to registration, controlling player creation, and doing site-locks (see `help blacklist' on $wiz_help).


Recall that for each line that an unconnected player types, the server parses that line into words (the same way normal commands are parsed into a list of words that is then assigned to `args') and then #0:do_login_command is called.

:parse_command (@args) => {verb, @args}
given the sequence of arguments that were fed to #0:do_login_command this returns the name of a verb on $login to be called together with a list of arguments to be passed to it.

By default this just returns args iff args[1] names an actual verb on $login that is +x and has args {"any","none","any"}. Otherwise, it returns one of

  .blank_command   -- verb to call if command line is empty
  .bogus_command   -- verb to call if command line otherwise unintelligible
In both cases :parse_command returns a verbname followed by the entire args list passed to it (including the would-be verb at the beginning if any).

Currently the following verbs are availabe to non-connected players

  h*elp @h*elp       -- print .welcome_message
  ?                  -- print a short list of available commands
  w*ho @w*ho         -- print a list of logged in players (excluding wizards)
  co*nnect @co*nnect -- connect to an existing player
  cr*eate @cr*eate   -- create a new player
  up*time @up*time   -- tell how long the server has been running
  version @version   -- tell which version of the server is running
  q*uit @q*uit       -- logoff
Adding a new command is fairly straightforward; just create a verb on $login, making sure a previous verb doesn't already match the name you want to give it. Then give it args of "any" "none "any" and make sure it is +x. Such a verb should begin with `if (caller != #0) return E_PERM; ...' so as to prevent anyone other from a not-logged-in player from making use of it.


    -- the message for "help" to print.
    == 0 => @create prints .registration_string if one tries to use it
    == 1 => anyone from a non-blacklisted site (see `help blacklist')
            may use @create to make a new player

    -- an email address for character creation requests
    -- string to print to players to give them information about how to get 
       a character created for them, .registration_address is substituted 
       for %e, % for %%
    -- string to print to @newted players (see `help @newt').
       same substitutions as for .registration_string.
Other verbs

:registration_string() => .registration_string with substitutions

:newt_registration_string() => .newt_registration_string with substitutions

decides whether someone on connection should be allowed to create a player. If you decide this shouldn't depend strictly on the blacklist and on the value of .create_enabled, here's where the extra code can go.

prints a warning message to append to the login banner in the event that the server will be going down soon.

prints a warning message to append to the login banner in the event that $player_db is being reloaded to warn players that their character names might not be recognized.


see `help blacklist'


===== help $mail_agent ============================

This object contains a two distinct sets of routines:

1. utilities for performing basic mailsystem functions, e.g., matching on recipient names, resolving mail forwarding, formatting messages, sending messages

Recipient Matching

match           - match on a $mail_recipient
match_recipient - match on either a $mail_recipient or a player
match_failed    - print angry messages to the user for $failed/ambiguous_match

look_self       - provides a list of available $mail_recipients

Message Format

make_message        - produces a message in the canonical transmission format
name                - single recipient     => string for address field
name_list           - list of recipients   => string for address field
parse_address_field - address field string => object list

Sending Messages

send_message  - advertised message sending routine.
raw_send      - raw message sending routine 
                (only called by $mail_editor:send and this:send_message)
resolve_addr  - converts a given list recipients into a list of actual 
                recipients and objects to be notified.
sends_to      - Does X forward (transitively) to Y

Mail Options

2. canonical versions of mail_recipient verbs

Ideally, the verbs to perform operations on a given mail recipient would be located on the recipient itself, except for the fact that these verbs also need to be located on players, which for various reasons, shouldn't be children of $mail_recipient. Multiple inheritance would solve our problems, but we don't have it yet. Ergo, both $mail_recipient and $player refer to the following verbs here:

display_seq_full     print entire text of messages  (@read)
display_seq_headers  print headers of messages      (@mail)
rm_message_seq       remove messages                (@rmm)
undo_rmm             undo last rm_message_seq       (@unrmm)
expunge_rmm          flush removed messages         (@unrmm expunge)
list_rmm             list removed messages          (@unrmm list)
renumber             renumber messages              (@renumber)
display_seq_full     print entire text of messages  (@read)
display_seq_headers  print headers of messages      (@mail)
rm_message_seq       remove messages                (@rmm)
undo_rmm             undo last rm_message_seq       (@unrmm)
expunge_rmm          flush removed messages         (@unrmm expunge)
list_rmm             list removed messages          (@unrmm list)
renumber             renumber messages              (@renumber)
msg_summary_line     msg header => display_seq_headers/list_rmm summary line
parse_message_seq    command line msg sequence spec => message sequence
new_message_num      => message number of next new message
length_all_msgs      => number of messages (total)
length_num_le        => number of messages numbered <= some number
length_date_le       => number of messages dated <= some date
exists_num_eq        => true iff there exists a messsage with the given number
from_msg_seq         => message sequence of msgs from given sender(s)
to_msg_seq           => message sequence of msgs to given recipient(s)
subject_msg_seq      => message sequence of msgs with subjects containing text
body_msg_seq         => message sequence of msgs with bodies containing text
messages_in_seq      => list of {message number, message} pairs
messages             == :messages_in_seq(1,:length_all_msgs()+1)   (obsolete)
The $mail_agent versions of these verbs are set_task_perms(caller_perms()) and perform their operations on caller, which in turn is assumed to have done any necessary security checks.

===== help $mail_browser ==========================

The $mail_browser is a web system tool for reading MOO mail folders.It has two customizable properties on it:

The "headerlist_len" property is the length of the headers list displayed when someone browses a folder.

The "guest_subscribed_folders" is the list of mail folders (as a LIST of OBJ numbers) that guest and anonymous web users are shown as their "subscribed" folders. They can access the others (that are public) through the "list all folders" link, but this is basically the short list of ones you recommend.

===== help mail-format ============================

Mail Transmission Format

There is a standard message format used for transmitting messages. This is the format that $mail_editor:make_message produces, and that :receive_message verbs on players and $mail_recipients expect to see. The (currently experimental) @refile and @copym commands also use this format to transfer messages.

This *transmission* format is distinct from the *storage* format, though, for convenience this same format is often used as well for storing messages in player collections and ordinary $mail_recipient children though, in general, there is no requirement that this be the case.

A transmitted message is a list in the following form

date (number),
the time() value at the time the message was sent.

from (string),
the sending object (address list form) if this is not a player, an additional header will indicate the current ownership of the object.

to (string),
recipients (address list form) which can either be players or $mail_recipient descendents.

subject (string),
subject of the message, or " " if there is no subject,

@additional optional headers (list of strings),
each header has the form "<header-name>: text" where <header-name>: is padded out to a width of 10 columns for the convenience of :display_message. Currently "Reply-to: <address list>" is the only additional header in use, "",

@body of message (list of strings)

Note that the from, to and subject lines do *not* include a header name like "From:", "To:", or "Subject:". The @'s indicate that the lists in question get spliced in (as usual), thus the entire message is a list whose first element is a number and the rest are strings.

The address lists that appear in the from and to lines is a string in the form a sequence of object ids, each enclosed in parentheses and preceded by optional text, e.g.,

  "*Core-DB-Issues (#8175), Rog (#4292), and Haakon (#2)"
The text is intended to give the current name of each object for the benefit of human readers, but is actually ignored by all header parsing routines. The convention is that the text is either a player name or a * followed by a mailing list name.

===== help mail-forwarding =========================

There are 3 personal properties that you can use to customize how your mail is composed and forwarded
 -- list of objects that will receive any mail that gets sent to you.
    Objects on this list should either be players or descendants of 
    If this list is nonempty, you will not receive any mail yourself unless
    you are on it.  E.g., if Rog is #4292 and ur-Rog is #6349

  #6349.mail_forward={}            -- usual case; ur-Rog gets his own mail.
  #6349.mail_forward={#4292}       -- Rog gets ur-Rog's mail instead.
  #6349.mail_forward={#6349,#4292} -- ur-Rog gets mail and Rog gets a copy.
  #6349.mail_forward={#-1}         -- ur-Rog's mail disappears without a trace.

 -- list of objects to be notified whenever mail is sent to you.
    This list may include anything that has a :notify_mail() verb.
    Notification will take place regardless of whether or how your mail
    is forwarded.  

Thus, in the previous example

  #4292.mail_notify={#6349} --- means that ur-Rog will be told
                                whenever Rog is sent new mail.

 -- this controls lots of miscellaneous things.  Use the @mail-option command
    to view and set these options (see `help @mail-option')
See `help mail-resolve [mail-resolution]' for more detail on how mail forwarding and mail notification work. See `help MR-subscribing' for information on how to change .mail_forward and .mail_notify on $mail_recipient children, where they are !c properties.

===== help $mail_recipient =========================

Generic Mail Recipient

A "mail recipient" is, by definition, an object that can be sent mail. Mail recipients must either be players or descendants of $mail_recipient.

One source of confusion is that the terms "mail recipient", "mail folder", "mailing list", and "mail collection" really all refer to the same kind of object. It so happens that $mail_recipient serve several distinct functions and we tend to use whatever term happens to best match the application under discussion, e.g., it's a "mailing list" if we're playing with its .mail_forward property but it's also a "mail folder" if we're examining the messages that have been saved in it.

Note that, by default, a freshly created recipient is accessibly only by you. If you wish to make a publically accessible recipient, set .readers=1. Furthermore, if you want to allow a message on your recipient to be removed by its sender without your intervention, set .rmm_own_msgs=1. Finally, in order for other players to be able to refer to your recipient by name, the object must reside in $mail_agent. $mail_agent will not accept the object unless it has an actual description and a name distinct from all other mail recipient names/aliases.


  MR-access       -- controlling read, write and send access to a recipient
  MR-naming       -- naming conventions and how to match on recipient names
  MR-sequences    -- message sequence arguments to $mail_recipient verbs
  MR-reading      -- reading messages/headers on recipients
  MR-searching    -- searching message lists for patterns in certain fields
  MR-writing      -- removing and renumbering messages
  MR-subscribing  -- updating .mail_forward, .mail_notify and the story
                     of .current_message

===== help mail-resolution ==========================

Resolving Mail Forwarding & Notification

For each recipient of a given mail message, the following two verbs are called to determine where the message should actually go and who should be notified about it:

    should return either
     . a list of objects (either players or $mail_recipients)
         to which mail for this recipient will be redirected.
     . a string error message to be printed to the player sending the message.
If this recipient is one of the original destinations (i.e., not the result of a previous forwarding), no mail is actually sent.

If :mail_forward returns a nonempty list, the recipient itself will *not* actually receive the mail message unless it is included in the list. #-1 is allowed to be on the list; it is ignored but does make the list nonempty. Thus, having :mail_forward() return {#-1} is the canonical way to have arriving mail disappear without being kept or forwarded.

should return a list of objects that are to be told about any mail sent to this recipient (whether or not the recipient actually receives it).
Said objects must have a :notify_mail verb, but other from that, there is no restriction on what these can be.

    object:notify_mail is called with the arguments 
    (sender,recipients,msgnumbers) where 
      recipients  == list of recipients including object in .mail_notify
      msgsnumbers == corresponding list of :receive_message return values
                 (or 0 if :receive_message is not actually called, which
                  will be the case if the recipient forwards without keeping)
When called as part of a mail send, the `from' argument is the immediate predecessor on the forwarding chain. The default versions of these verbs return the values of .mail_forward and .mail_notify respectively (pronoun_subbing if the value is a string), unless this is a moderated mailing list and `from' is an unapproved sender (see `help MR-access') in which case the following verbs are called instead:
    what :mail_forward should return for mail coming from unapproved senders
    This returns .moderator_forward (pronoun_subbed if a string) by default.
    what :mail_notify should return for mail coming from unapproved senders
    This returns .moderator_notify (pronoun_subbed if a string) by default.
Since the :mail_forward verbs only see the previous sender in the forwarding chain, if, e.g, B is moderated but A can send to B (i.e., B:mail_forward(A) returns an actual list), then any mail sent to A goes to B even if the original sender isn't normally allowed to send to B directly.
These verbs should all allow `from' to be omitted in which case they should return as if `from' were a generic approved sender (e.g., wizard).

It should rarely be necessary to actually modify any of :*_forward/*_notify verbs, since one has a fair amount of control over their behavior via the following properties

  .moderated          (see `help MR-access')

===== help mail-resolve ============= SEE mail-resolution

===== help mail-system ============================

Mail System

The following topics describe the guts of the LambdaCore mail system

sending-mail     	-- how to send mail from a program; what happens.
mail-forwarding  	-- how to do mail forwarding/notification (the simple version)
mail-resolve     	-- how mail forwarding/notification works, in gory detail
receiving-mail   	-- what :receive_message should do
mail-format      	-- format of transmitted messages
mail-command-parsing   (TODO) -- routines for parsing mail commands

$mail_recipient  	-- generic non-player mail recipient
$mail_agent      	-- mail utility object

===== help MR-access=============================

Controlling Access to Mail Recipients

:is_writable_by(one) - one may alter/add/remove saved messages
:is_readable_by(one) - one may read messages.
:is_usable_by(one)   - one may send to this list

By default, these verbs refer to the following properties:

writers   - list of players other from the owner who can do anything
readers   - if == 1, indicates a public mailing list.
            list of additional readers (by default anyone who receives mail 
            sent to the list can read the saved messages).
moderated - if false, indicates a normal mail recipient everyone can send to.
            otherwise this should be a list of approved senders.

  A mailing list is "public" if everyone can read it.
  A mailing list is "moderated" if not everyone can send to it.
Note that while being able to write to a recipient implies being able to read from it or send to it, neither of read-ability or send-ability implies the other.

It is highly recommended that if you are creating custom mail recipients with variable reader/sender lists, i.e., you find you need to write your own :is_readable/usable/writabe_by verbs, you are best off if such verbs are of the form return pass(@args) || << your_test(args[1]) >>

and have .writers == .readers == {} and .moderated == 1.  This will ensure
 (1) wizards having write access
     --- necessary in order for :receive_message to work
 (2) writers being able to read and send (the converse being a ludicrous 
 (3) persons on the mail_forward list of someone with reader access will also
     have read access (convenient).

===== help MR-naming============================

One may always refer to a list by its object number. In order to refer to it by name, it must be contained in $mail_agent, which holds all mailing lists, i.e., those that you want others to be able to refer to by name.

The .aliases field holds the names by which one may refer to the list, but only those names not containing spaces actually count for anything. As with certain other types of objects (e.g., players), set_aliases() needs to be called in order to change the .aliases field.

    is the canonical way to obtain the objectid of a mailing list 
    given the name ("*" is assumed; an initial "*" will be dropped).

    is the canonical way to obtain the objectid of a list or player
    matching the given name.  An initial "*" indicates that this is 
    supposed to be a list.

    is the mail_recipient counterpart to $command_utils:object_match_failed

===== help MR-reading============================

Read verbs

The following verbs may be used to extract headers/messages from readable mail recipients/players;

:display_seq_headers (message sequence, current message number, last_read_date)
Does a @mail listing of the given message sequence. If current message number is given and the sequence includes it, we mark it with a `>'. Likewise if the sequence includes any new messages (i.e., dated after last_read_date), these are also indicated as such.

display_seq_full (message sequence, preamble) Does a @read listing of the given message sequence. Each message is preceded by preamble.
=> {new current message number, new last_read_date}

:messages_in_seq (index)
=> {n, msg}
:messages_in_seq (message sequence)
=> {{n_1,msg_1},{n_2,msg_2},...}
where the n_i are message numbers and the msg_i are messages in transmission format (see `help mail-format')

:list_rmm () Does an `@unrmm list' listing of messages in .messages_going

===== help MR-searching==========================

Search verbs

The following verbs can be used on a readable mail-recipient/player to search for messages with fields matching a given pattern.

from_msg_seq (objectid or list [,mask])
  => message sequence: messages from (one of) the given objectid(s)

%from_msg_seq (string or list [,mask])
  => message sequence: messages with (one of) the given string(s)
     in the From: line

to_msg_seq (objectid or list [,mask])
  => message sequence: messages to (one of) the given objectid(s)

%to_msg_seq (string or list [,mask])
  => message sequence: messages with (one of) the given string(s)
     in the To: line

subject_msg_seq (string [,mask])
  => message sequence: messages with given string occurring in Subject:

body_msg_seq (string [,mask])
  => message sequence: messages with given string occurring in body of message
In all cases `mask' is a message sequence which one may supply to limit the range of the search. One way of looking at it is that the message sequence to be returned is first intersected with mask.

===== help MR-sequences==========================

Message Sequences

A "message sequence" is a handle by which one may refer to a particular subset of a mail recipient's (player or $mail_recipient-descendant) saved messages. Routines like rcpt:display_seq_headers or rcpt:display_seq_full need to be supplied with message-sequence arguments to deterimine which headers or full-messages to display.

Message sequences can in turn be obtained from routines like rcpt:parse_message_seq, which takes a command-line description of a message sequence on that particular recipient and returns the corresponding message sequence handle.

The actual form of a message sequence (though you shouldn't actually need to make use of this) is that of a set of integers in the format used by $seq_utils (see `help $seq_utils'). It should however be noted that these integers are *not* themselves message numbers, but rather indices into the list of saved messages. For example, if a particular recipient holds 5 messages numbered 1,3,5,7,9. Then the message sequence handle representing messages 3,5,7 collectively, would be {2,5} which is $seq_utils-ese for the range 2..4, namely the second, third and fourth messages saved on that recipient.

The following verbs are available for obtaining indices to use in message sequences

  :length_all_msgs()    => total number of messages, or equivalently,
                        => index of last message
  :length_num_le(n)     => number of messages numbered <= n, or equivalently,
                        => index of highest numbered message <= n
  :exists_num_eq(n)     => 0 unless there exists a message numbered n in which
                           case we return the index of that message.
  :length_date_le(date) => number of messages dated <= date, or equivalently,
                        => index of most recent message dated <= date

  :length_date_gt(date) => number of messages dated > date
Note that r:length_date_gt(date) == r:length_all_msgs()-r:length_date_le(date).
The only reason :length_date_gt is provided as a separate routine is in order to do quick checks for the existence of new mail (as @rn needs to do).

===== help MR-subscribing=========================

Subscribing to Mail Recipients

There are two notions of being "subscribed" to a mailing list/recipient.

(1) Hard subscribed == being on the recipient's .mail_forward list so that mail sent to this list is forwarded to one's own .messages as well (see `help mail-forwarding').

(2) Soft subscribed == keeping track of a current message for this recipient and (optionally) being on the recipient's .mail_notify list.

Each player has a .current_message property that contains, for each recipient the player cares to keep track of, a current message number and a last read date.

player:current_message(rcpt)                 (somewhat obsolete)
 => player's current message number for rcpt 

 => player's {current message number for rcpt, last-read-date for rcpt}

 => adds a current_message entry for rcpt  (NOOP if rcpt == player)

 => sets player's current message number for rcpt to n iff n!=E_NONE
    updates the last-read-date for rcpt to date iff date > last-read-date

 => removes current-message info for rcpt  (NOOP if rcpt == player)
On $mail_recipient, .mail_forward and .mail_notify are -c so one needs to use the following verbs to actually modify them.
A recipient's owner is, of course, allowed to make arbitrary changes to .mail_forward and .mail_notify. However, the default versions of these verbs also allow any player to add him/herself to a recipient's .mail_forward or .mail_notify if the recipient is readable (see `help MR-access') by him/her.

Likewise any player may use the :delete* verbs to delete him/herself from any .mail_forward/.mail_notify list, regardless of his actual access to the list.

===== help MR-writing============================

Write verbs

The following verbs can be used to manipulate writable mail recipients/players:

:rm_message_seq (message sequence)
Does an @rmmail. Messages in message sequence are removed from this recipient's saved .messages and written to .messages_going.

:undo_rmm ()
Does an @unrmm. Messages in .messages_going are copied back to .messages.

:expunge_rmm ()
Does an @unrmm expunge. Blows away .messages_going.

:renumber ()
Does a @renumber.