MudOS Docs

MudOS Documentation

These were extracted from the docs in the MudOS distribution, using a python script I wrote. Various people’s names appear below, signing each piece of documentation they wrote. I am not any of the people mentioned below.

Table of Contents

applies

__INIT author_file catch_tell
clean_up compile_object connect
crash create creator_file
domain_file epilog error_handler
flag get_bb_uid get_root_uid
get_save_file_name heart_beat id
init log_error logon
make_path_absolute move_or_destruct net_dead
object_name parse_command parse_command_adjectiv_id_list
parse_command_all_word parse_command_id_list parse_command_plural_id_list
parse_command_prepos_list preload privs_file
process_input receive_message receive_snoop
reset retrieve_ed_setup save_ed_setup
slow_shutdown telnet_suboption terminal_type
valid_bind valid_compile_to_c valid_hide
valid_link valid_object valid_override
valid_read valid_save_binary valid_seteuid
valid_shadow valid_socket valid_write
window_size write_prompt

interactive

catch_tell logon net_dead
process_input receive_message receive_snoop
telnet_suboption terminal_type window_size
write_prompt

master

author_file compile_object connect
crash creator_file domain_file
epilog error_handler flag
get_bb_uid get_root_uid get_save_file_name
log_error make_path_absolute object_name
parse_command_all_word parse_command_prepos_list preload
privs_file retrieve_ed_setup save_ed_setup
slow_shutdown valid_bind valid_compile_to_c
valid_hide valid_link valid_object
valid_override valid_read valid_save_binary
valid_seteuid valid_shadow valid_socket
valid_write

parsing

parse_command parse_command_adjectiv_id_list parse_command_id_list
parse_command_plural_id_list

efun

arrays

allocate filter_array map_array
member_array sort_array unique_array

buffers

allocate_buffer crc32 read_buffer
write_buffer

calls

call_other call_out call_stack
catch origin previous_object
query_shadowing remove_call_out remove_shadow
shadow this_object throw

compile

generate_source

filesystem

cp file_length file_size
get_dir link mkdir
read_bytes read_file rename
rm rmdir stat
tail write_bytes write_file

floats

acos asin atan
ceil cos exp
floor log pow
sin sqrt tan
to_int

functions

bind evaluate function_owner

general

copy fetch_variable filter
map restore_variable save_variable
sizeof store_variable typeof

interactive

add_action command commands
disable_commands disable_wizard ed
ed_cmd ed_start enable_commands
enable_wizard exec find_player
get_char in_edit in_input
input_to interactive message
notify_fail printf query_ed_mode
query_host_name query_idle query_ip_name
query_ip_number query_ip_port query_notify_fail
query_snoop query_snooping receive
remove_action remove_interactive resolve
say set_this_player shout
snoop this_interactive this_player
this_user userp users
wizardp write

internals

cache_stats debug_info debugmalloc
dump_file_descriptors dump_prog dump_socket_status
dumpallobj get_config malloc_status
memory_info mud_status opcprof
query_load_average refs rusage
set_debug_level set_malloc_mask swap
time_expression trace traceprefix

mappings

allocate_mapping filter_mapping keys
m_delete m_indices m_values
map_delete map_mapping match_path
unique_mapping values

mixed

arrayp bufferp classp
floatp functionp intp
mapp nullp objectp
pointerp stringp undefinedp

mudlib

author_stats domain_stats export_uid
find_living geteuid getuid
living livings query_privs
set_author set_light set_living_name
set_privs seteuid

numbers

random to_float

objects

all_inventory children clone_object
clonep deep_inventory destruct
environment file_name find_object
first_inventory heart_beat_info heart_beats
load_object master move_object
new next_inventory objects
present query_heart_beat reload_object
restore_object save_object set_heart_beat
set_hide tell_object tell_room
virtualp

parsing

query_verb TODO

sockets

socket_accept socket_acquire socket_address
socket_bind socket_close socket_connect
socket_create socket_error socket_error.h
socket_listen socket_release socket_write

strings

capitalize clear_bit crypt
explode implode lower_case
next_bit pluralize reg_assoc
regexp repeat_string replace_string
set_bit sprintf sscanf
strcmp strlen strsrch
terminal_colour test_bit upper_case

system

all_previous_objects call_out_info check_memory
ctime debug_message deep_inherit_list
error eval_cost external_start
find_call_out flush_messages function_exists
function_profile functions inherit_list
inherits localtime lpc_info
max_eval_cost memory_summary named_livings
program_info reclaim_objects replace_program
replaceable reset_eval_cost set_eval_limit
set_reset shallow_inherit_list shutdown
time uptime variables

lpc

concepts

defines lpc message_doc
MudOSdriver objects oop
preprocessor simul_efun socket_efuns

constructs

for function if
include inherit prototypes
switch while

etc

error_msgs

types

array.2d buffer float
function general mappings

Documentation

__INIT - obsolete apply

void __INIT(); 

This function used to be called in objects right before create.
global variable initialization is now handled by another function that
cannot be interfered with, so this is no longer called.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

author_file - determine the author for a given object

string author_file (string file);

This routine is only used if PACKAGE_MUDLIB_STATS is used.

This function must exist in the master object.  It is called by the
author statistic functions in the driver to determine what author a
given object should be associated with.  This is totally arbitrary and
up to the mudlib designers wishes.  It should be noted that the author
that the object is assigned to will receive "credit" for all of the
objects behavior (errors, heart_beats, etc).

See also:
 author_stats,
 domain_stats,
 domain_file

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

catch_tell - provides an interface to interact with users

void catch_tell( string message );

If INTERACTIVE_CATCH_TELL is defined in options.h, whenever the driver
has something to tell an object due to say(), shout(), tell_object(), etc.
catch_tell in the player object will be called with the message to
be printed.  The message can be displayed, discarded, or modified in
any way desired.  This is a useful way to have flexible earmuffs, or
to support intelligent clients.

See also:
 message,
 receive,
 receive_message

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

clean_up - periodically called in inactive objects

int clean_up( int inherited ); 

The clean_up() function is called by the driver on a regular basis in all
objects that have been inactive for the time specified for clean_up() in the
runtime configuration file.  One flag is passed to the function, specifying
whether or not the object has been inheritted by anything.  If clean_up()
returns 0, clean_up() will never be called again on that object.  If it returns
1, it will be called again when the object remains inactive for the specified
clean_up() delay.

One thing that might be commonly done by an object in this function is
destructing itself to conserve memory.  However, one often does not want
to destruct objects which have been inherited, as this will cause a new
copy to be loaded next time they are inherited again, causing more than
one copy of the code to be in memory.

See also:  destruct

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

compile_object - serves as the mudlib interface for the virtual object facility

object compile_object( string pathname );

The driver calls compile_object in the event that the mudlib instructs
the driver to load a file that does not exist.  For example, the driver
will call compile_object("/obj/file.r") in master if the mudlib calls
call_other("/obj/file.r", "some_function") or new("/obj/file.r")
and /obj/file.r.c names a file that does not exist.  The compile_object()
function is expected to return 0 if the mudlib does not wish to
associate an object with the file name "/obj/file.r".  If the mudlib
does wish to associate an object with the filename "/obj/file.r", then
the mudlib should return the object it wishes associated.  After an
association is made between an object and a filename, then it will be
as if the file, file.r.c, did exist (to the driver) and when loaded produced
the object that compile_object() returned.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

connect - get an object for a new user

object connect(int port);

The driver calls connect() in the master object whenever a new user logs
into the driver.  port is the actual port connected to; for example if
you have two login ports defined as 2000 and 3000, either 2000 or 3000 
will be passed to this routine.

The object returned by connect() is used as the initial
user object.  Note that it is possible to change the user object at a later
time (for example, after determining who is logging in) using the exec()
efun.

See also:  logon,  exec

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

crash - function in master that is called in the event the driver crashes

void crash( string crash_message, object command_giver, object current_object );

The driver calls crash() in master in the event that the driver crashes
(segmentation fault, bus error, etc).  This function offers a way to
shutdown the mudlib (safe players and other important data) before the driver
crashes.  It also lets you log various useful information such as what
signal crashed the driver, what object was active, who the current player
was etc.

See also:
 shutdown,
 slow_shutdown

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

create - object initialization

void create(...);

The arguments passed to the function will be the same as those passed to
new() or clone_object() in addition to the filename, if the object was loaded
using either of those efuns.  For example, clone_object(file, 3, "hi") will
cause create(3, "hi") to be called in the object after it is created.

Every object should have a create function defined within it.  Within
that function, all initial object initialization should be done.
create() is called on *all* objects.  *NOTE* - This behavior is
different than the stock 3.1.2 LPmud driver.  In 3.1.2, if an object
is created first by being inherited, then create() wasn't called on
it.  In MudOS, this behavior has changed so that it is *always* called
when an object is created.  As a result, you may see some odd behavior
if you have a create in a parent object that does a write, you will
see two writes, as if create() had been called twice on the same
object.  In reality, create *is* being called twice, but on two
*different* objects: the parent, and the child that is calling
parent::create() manually.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

creator_file - specifies the uid to give to a newly created object

string creator_file(string filename);

This routine is only used if PACKAGE_UIDS is used.

The creator_file() function is called in the master object each time a new
object is created.  The `filename' of the object is passed as the sole
parameter, and the string that creator_file() returns is set as the new
object's uid.  If the AUTO_SETEUID option is enabled at compile-time of the
driver, it is also set as the new object's euid.
.PP
One exception: if the AUTO_TRUST_BACKBONE option is enabled at compile-time of
the driver, and creator_file() returns the backbone uid (as specified by
get_bb_uid() in the master object), the object is given the uid and euid of
the object that loaded it.

See also:
 seteuid,
 clone_object,
 new

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

domain_file - determine the domain for a given object

string domain_file( string file );

This function must exist in the master object.  It is called by the
domain statistic functions in the driver to determine what domain a
given object should be associated with.  This is totally arbitrary and
up to the mudlib designers wishes.  It should be noted that the domain
that the object is assigned to will receive "credit" for all of the
objects behavior (errors, heart_beats, etc).

See also:
 author_stats,
 domain_stats,
 author_file

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

epilog - handle initialization

string array epilog( int load_empty ); 

The driver calls epilog() in master after the master object has been loaded.
Required initialization may be done at this point.  If epilog() returns an
array of filenames, the driver will attempt to load those files via the
preload() function.

The variable 'load_empty' is non-zero if the -e option was specified
when starting up the driver, which has been historically used to mean
no preloads, although the mudlib is free to use another interpretation.

See also:  preload

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

error_handler - function in master object to handle errors

void error_handler( mapping error, int caught );

This function is only called if MUDLIB_ERROR_HANDLER is defined.

This function allows the mudlib to handle runtime errors.
The contents of the 'error' mapping are:
    ([
        "error"   : string,        // the error
        "program" : string,        // the program
        "object"  : object,        // the current object
        "line"    : int,           // the line number
        "trace"   : mapping array  // a trace back
    ])

Each line of traceback is a mapping containing the following:

    ([
        "function"  : string,   // the function name
        "program"   : string,   // the program
        "object"    : object,   // the object
    "file"      : string,   // the file to which the line number refers
        "line"      : int,      // the line number
        "arguments" : array,    // function arguments
        "locals"    : array     // local variables
    ])

arguments and local variables are only available if ARGUMENTS_IN_TRACEBACK
and LOCALS_IN_TRACEBACK are defined.

The 'caught' flag is 1 if the error was trapped by catch().

See also:
catch,
error,
throw,
log_error

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

flag - handle mudlib specific flags specified at driver startup

void flag( string );

This master apply is called for each command line
option passed to the driver with the -f flag.  For example, invoking the
driver via:

./driver -fdebug

will call flag("debug") in the master object during initialization.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

get_bb_uid - get the backbone uid

string get_bb_uid();

This routine is only used if PACKAGE_UIDS is used.

This master apply is called by the driver on startup,
after it has loaded the master object, to get the
backbone uid defined by the mud.  The function should
return a string, eg "BACKBONE"

See also:
 get_root_uid

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

get_root_uid - get the root uid

string get_root_uid();

This function is only used if PACKAGE_UIDS is used.

This master apply is called by the driver each time
it loads the master object, to verify that the master
object has loaded, and to get the root uid defined by
the mud.  The function should return a string, eg "ROOT"

See also:
 get_bb_uid

back to top

get_save_file_name - back up editor file on abnormal exit

string get_save_file_name( string file, object who );

This master apply is called by ed() when a player disconnects
while in the editor and editing a file.  This function
should return an alternate file name for the file to
be saved, to avoid overwriting the original.

Note: This apply used to be named get_ed_buffer_save_file_name().

See also:
 ed

back to top

heart_beat - called periodically in objects in which it is enabled

void heart_beat();

If an object has called set_heart_beat(), this function will be called
periodically in that object.

See also:
 set_heart_beat

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

id - function called by present() in order to identify an object

int id( string an_id );

The present() efunction calls id() to determine if a given object is named
by a given string.  id() should return 1 if the object wishes to be known
by the name in the string anId; it should return 0 otherwise.

See also:
 present

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

init - function in an object called by move_object() to initialize verb/actions

void init();

This function is not called if NO_ADD_ACTIONS is defined.

When the mudlib moves an object "A" inside another object "B", the
driver (the move_object() efunction) does the following:

* if "A" is living, causes "A" to call the init() in "B" * causes each living object in the inventory of "B" to call init() in "A". regardless of whether "A" is living or not. * if "A" is living, causes "A" to call the init() in each object in the inventory of "B".
Note: an object is considered to be living if enable_commands() has been called by that object. Typically, the init() function in an object is used to call add_action() for each command that the object offers. See also: move_object, enable_commands, living, add_action

back to top

log_error - log errors intelligently

void log_error( string file, string message );

Whenever an error occurs during compilation, the function log_error in
the master object is called with the filename that the error occurred
in and the error message itself.  Then, log_error is free to do
whatever it thinks it should do with that information.  Usually this
is deciding based on the filename where the error message should be
logged, and then writing it to that file.  Warnings also pass through
this routine, and can be detected since they start with "Warning:"

See also:
 error_handler

back to top

logon - initialize a logon connection

object logon(); 

This apply is called on the object returned by the connect() master
apply, after that object has been made into an interactive object,
so the object can initiate any logon sequence which is wanted.  This
function is no longer required to exist.  this_user() will be the
interactive object.

See also:  connect

back to top

make_path_absolute - resolve relative path name

string make_path_absolute( string rel_path );

This master apply is called by the ed() efun to
resolve relative path names of a file to read/write, to an absolute path
name.

See also:
 ed

back to top

move_or_destruct - ask an object to move to the specified destination

int move_or_destruct( object dest );

If an object's environment is destructed, this apply is called on it's
contents.  'dest' will be the environment of the destructing object,
or zero if it has none.  If the object does not move itself out of
the object being destructed, it will be destructed as well.

See also:
 destruct,
 move_object

back to top

net_dead - called by the MudOS driver when an interactive object drops its connection

void net_dead( void ); 

If an interactive object (i.e. a user object) suddenly loses its
connection (i.e. it goes "net dead"), then the driver calls this
function on that object giving it a chance to clean up, notify its
environment etc.  Be aware that functions that depend on the object
being interactive will not work as expected.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

object_name - called by the driver to find out an object's name

string object_name( object );

This master apply is called by the sprintf() efun, when
printing the "value" of an object.  This function should
return a string corresponding to the name of the object
(eg a user's name).

See also:
 file_name

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

parse_command(3)      LPC Library Functions      parse_command(3)

NAME
       parse_command()  - try to match a string with a given pat-
       tern

SYNOPSIS
       int parse_command( string command, object env|object *oblist,
                          string pattern, mixed arg, ... );

DESCRIPTION
       parse_command() is a piffed up sscanf(3) operating on word
       basis.   It  works similar to sscanf(3) in that it takes a
       pattern and a variable set of destination arguments. It is
       together  with sscanf(3) the only efun to use pass by ref-
       erence  for  other  variables  than  arrays.    That   is,
       parse_command() returns values in its arguments.

       parse_command()  returns  1  if 'command' is considered to
       have matched

       The 'env' or 'oblist' parameter either holds an object  or
       a list of objects. If it holds a single object than a list
       of  objects  are  automatically  created  by  adding   the
       deep_inventory of the object, ie this is identical:

          parse_command(cmd, environment(), pattern, arg)

       and

          parse_command( cmd, ({ environment() }) +
                         deep_inventory(environment()), pattern, arg)

          Example string = " 'get' / 'take' %i "
               Syntax:
                       'word'          obligatory text
                       [word]          optional text
                       /               Alternative marker
                       %o              Single item, object
                       %l              Living objects
                       %s              Any text
                       %w              Any word
                       %p              One of a list (prepositions)
                       %i              Any items
                       %d              Number 0- or tx(0-99)

       The  'arg'  list  is zero or more arguments. These are the
       result variables as in sscanf. Note that one  variable  is
       needed for each %_

       The return types of different %_ is:
                       %o      Returns an object
                       %s      Returns a string of words

MudOS                       5 Sep 1994                          1

parse_command(3)      LPC Library Functions      parse_command(3)

                       %w      Returns a string of one word
                       %p      Can on entry hold a list of word in array
                               or an empty variable
                               Returns:
                                  if empty variable: a string
                                  if array: array[0] = matched word
                       %i      Returns a special array on the form:
                               [0] = (int) +(wanted) -(order) 0(all)
                               [1..n] (object) Objectpointers
                       %l      Returns a special array on the form:
                               [0] = (int) +(wanted) -(order) 0(all)
                               [1..n] (object) Objectpointers
                                               These are only living objects.
                       %d      Returns a number

       The  only  types of % that uses all the loaded information
       from the objects are %i and %l. These are in fact  identi-
       cal  except that %l filters out all nonliving objects from
       the list of objects before trying to parse.

       The return values of %i and %l is also the  most  complex.
       They return an array consisting of first a number and then
       all possible objects  matching.   As  the  typical  string
       matched  by  %i/%l looks like: 'three red roses', of these
       numerical constructs was matched:

          if numeral >0 then three, four, five etc were matched
          if numeral <0 then second, twentyfirst etc were matched
          if numeral==0 then 'all' or a generic plural form such as
                         'apples' were matched.

       NOTE!

                The efun makes no  semantic  implication  on  the
              given numeral. It does
                not  matter  if 'all apples' or 'second apple' is
              given. A %i will
                return  ALL  possible  objects  matching  in  the
              array. It is up to the
                caller  to  decide what 'second' means in a given
              context.
                Also when given an object  and  not  an  explicit
              array of objects the
                entire recursive inventory of the given object is
              searched. It is up
                to the caller to decide which of the objects  are
              actually visible
                meaning  that  'second' might not at all mean the
              second object in
                the returned array of objects.

CAVEAT
       Patterns of type: "%s %w %i" Might not work as  one  would

MudOS                       5 Sep 1994                          2

parse_command(3)      LPC Library Functions      parse_command(3)

       expect.   %w  will always succeed so the arg corresponding
       to %s will always be empty.

BUGS
       Patterns of the type: 'word' and [word] The 'word' can not
       contain  spaces.   It  must  be a single word.  This is so
       because the pattern is exploded on " " (space) and a  pat-
       tern element can therefore not contain spaces.

       As  another  effect  of  the  exploding on space, separate
       pieces of a pattern MUST be separated with space, ie not "
       'word'/%i " but " 'word' / %i"

       EXAMPLE:
            if (parse_command("spray car",environment(this_player()),
                              " 'spray' / 'paint' [paint] %i ",items))
                {
                   /*
                     If the pattern matched then items holds a return array as
                     described under 'destargs' %i above.
                   */
                }

       MUDLIB SUPPORT

       To  make  the  efun  useful it must have a certain support
       from the mudlib, there is a set of functions that it needs
       to call to get relevant information before it can parse in
       a sensible manner.

       In earlier versions it used the normal id()  lfun  in  the
       LPC  objects  to find out if a given object was identified
       by a certain string. This was  highly  inefficient  as  it
       could  result in hundreds or maybe thousands of calls when
       very long commands were parsed.

       The new version relies on the LPC objects to give it three
       lists of 'names'.

          1 - The normal singular names.
          2 - The plural forms of the names.
          3 - The acknowledged adjectives of the object.

       These are fetched by calls to the functions:

          1 - string *parse_command_id_list();
          2 - string *parse_command_plural_id_list();
          3 - string *parse_command_adjectiv_id_list();

       The  only  really  needed list is the first. If the second
       does not exist than the efun will try to create  one  from
       the  singluar  list.   For grammatical reasons it does not
       always succeed in a perfect way.  This is especially  true

MudOS                       5 Sep 1994                          3

parse_command(3)      LPC Library Functions      parse_command(3)

       when the 'names' are not single words but phrases.

       The third is very nice to have because it makes constructs
       like

       Apart from  these  functions  that  should  exist  in  all
       objects,  and  which  are  therefore  best put in the base
       mudlib object there is also a set of functions  needed  in
       the master object.  These are not absolutely necessary but
       they give extra power to the efun.

       Basically these master object  lfuns  are  there  to  give
       default  values  for  the lists of names fetched from each
       object.

       The names in these lists are applicable  to  any  and  all
       objects, the first three are identical to the lfuns in the
       objects:

          string *parse_command_id_list()
             - Would normally return: ({ "one", "thing" })

          string *parse_command_plural_id_list()
             - Would normally return: ({ "ones", "things", "them" })

          string *parse_command_adjectiv_id_list()
             - Would normally return ({ "iffish" })

       The last two are the default list of the prepositions  and
       a single so called
          string *parse_command_prepos_list()
             - Would normally return: ({ "in", "on", "under" })

          string parse_command_all_word()
             - Would normally return: "all"

MudOS                       5 Sep 1994                          4

back to top

parse_command_adjectiv_id_list - returns a list of names to the parser

string array parse_command_adjectiv_id_list(); [sic] 

This routine is used to find out what adjectives the object responds to, and is
used by the parsing package and the parse_command() efun.  In addition,
anything returned by the master object will work on ANY object.

See also:
 parse_command

back to top

parse_command_all_word - find out what word refers to everything

string parse_command_all_word(); 

This routine is called in the master object to find out what word should
be considered to refer to everyting.  It is used by the parse_command() efun.

See also:
 parse_command

back to top

parse_command_id_list - returns a list of names to the parser

string array parse_command_id_list(); 

This routine is used to find out what nouns the object responds to, and is
used by the parsing package and the parse_command() efun.  In addition,
anything returned by the master object will work on ANY object.

See also:
 parse_command

back to top

parse_command_plural_id_list - returns a list of names to the parser

string array parse_command_plural_id_list(); 

This routine is used to find out what plural nouns the object responds to,
and is used by the parsing package and the parse_command() efun.  In addition,
anything returned by the master object will work on ANY object.

See also:
 parse_command

back to top

parse_command_prepos_list - find out what words are valid prepositions

string array parse_command_prepos_list(); 

This routine is called in the master object to find out what words should
be considered prepositions.  It is used by the parsing package and the
parse_command() efun.

See also:
 parse_command

back to top

preload - preload an object into memory

void preload( string filename );

For each string in the array returned by epilog, the driver calls 
preload(filename).  Note that there is the equivalent of a catch() around
these calls at the driver level, so it is not neccessary for the mudlib
to worry about the sequence being terminated by an error.

Typical behavoir is to use load_object() to attempt to load the file.

See also:  preload, ,
           load_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

privs_file - specifies the privs string to give to a newly created object

string privs_file( string filename );

The privs_file() function is called in the master object when a new file
is created.  The `filename' of the object is passed as the argument, and
the string that privs_file() returns is used as the new object's privs
string.

The privs_file() functionality is only available if the driver is compiled
with the PRIVS option defined.

See also:
 query_privs
 set_privs

back to top

process_input - inspect (and possibly modify) user input

mixed process_input( string );

If process_input is present in the player object, then the MudOS driver
will send it a copy of each line the player types.  If a string is returned,
that string is used as instead of the user input for further processing.
If a non-zero, non-string is returned, no further processing is done.
If zero is returned, processing continues with the original input.
Matching against add_actions is then done.

Note: If NO_ADD_ACTION is defined, then there is no more processing to be
done after process_input.  In this case, the return value is ignored, and
the mudlib is responsible for interpreting the string as a command (or other
user input for non-command based uses).

See also:  add_action

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

receive_message - provides the interface used by the message efun.

void receive_message( mixed cl, mixed message );

The message() efun calls this method in the player object.  The cl
parameter is typically used to indicate the class (say, tell, emote,
combat, room description, etc) of the message.  The receive_message() 
apply together with the message() efun can provide a good mechanism for
interfacing with a "smart" client.

See also:
 catch_tell,
 message,
 receive,
 receive_snoop

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

receive_snoop - catch incoming snoop text

void receive_snoop(string message);

If RECEIVE_SNOOP is defined in options.h or  local_options,
whenever a user is snooping another
user, all snoop text is sent to receive_snoop() in their user object.  Inside
of this function, you can do as you wish with the text.  A common activity
would be to receive() it.

See also:
 catch_tell,  receive

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

reset - allows an object to do self-maintenance

void reset();

After every reset interval (whose exact length is determined on
a mud by mud basis, but averages around every 2 hours), reset()
is called in every object that currently exists.  If LAZY_RESETS
is defined in options.h in the driver, reset() will only be called
in objects when they are touched (near players), so unused objects
will not be loaded from the swap file to reset.

See also:
 set_reset

back to top

retrieve_ed_setup - retrieve a user's editor setup or configuration settings

int retrieve_ed_setup( object user );

This master apply is called by the ed() efun to retrieve
a user's ed setup/configuration settings.  This function
should return the setup (contained in an int).

See also:
 save_ed_setup

back to top

save_ed_setup - save a user's editor setup or configuration settings

int save_ed_setup( object user, int config );

This master apply is called by the ed() efun to save
a user's ed setup/configuration settings (contained in
an int).  This function should return an int for
success (1 or TRUE)/failure (0 or FALSE).

Seel also:
 retrieve_ed_setup

back to top

slow_shutdown - informs the mud that a slow shutdown is in progress

int slow_shutdown( int minutes );

This master apply is called when the driver can't
allocate any more memory from the heap and had to
use its reserved memory block.  This function can
only be called if the "reserved size" config file
setting was set.  The minutes remaining to driver
shutdown is passed to this function.  If this function
does ont exist, or returns zero, the driver shuts
down immediately.

See also:
 crash,
 shutdown

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

telnet_suboption - process telnet suboptions

void telnet_suboption( string buf );

This apply is called on the interactive object with the parameter given
by the SE telnet suboption, for mudlib defined processing.  Note that
terminal type responses and window size responses are interpreted and
sent to terminal_type() and window_size() respectively instead of going
through telnet_suboption().

The first byte of the buffer is typically a type descriptor,
ie TELOPT_TTYPE. The next byte is a procession option, such
as TELQUAL_IS.  Following this is the type dependent data.

See also:  terminal_type,  window_size

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

terminal_type - inform the mudlib of the user's terminal type

void terminal_type( string term );

This apply is called on the interactive object with term set to the
terminal type for the user, as reported by telnet negotiation.  If the
user's client never responds (it's not telnet, for example) this will
never be called.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_bind - determine if it is legal to bind a given function pointer to an object

int valid_bind(object doer, object owner, object victim); 

This is called when 'doer' tries to use the bind() efun to bind a function
pointer owned by 'owner' to the object 'victim'.  If this routine returns
zero, the operation is disallowed.

See also:
 bind

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_compile_to_c - determine whether LPC->C compilation may take place

int valid_compile_to_c(); 

valid_compile_to_c() is called when the generate_source() efun is used to
generate C files or to do runtime compilation of an object.  One might
want to restrict the use of this since the process can be CPU intensive.

See also:  generate_source

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_hide - allows or disallows objects to hide and see hidden objects

int valid_hide( object ob );

Add valid_hide to master.c in order to allow objects to hide themselves,
or see other objects that have hidden themselves.  When an object tries to
use the set_hide() efun to hide itself, valid_hide will be called with the
object that is wanting to hide as the sole parameter.  It should return 1
to allow it, or 0 to not allow it.  The same call takes place when it needs
to be determined if a certain object should be able to see hidden objects.

See also:
 set_hide

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_link - controls the use of the link efun

int valid_link( string from, string to );

The driver calls valid_link(from, to) in the master object from inside the
link(from, to) efunction.  If valid_link() returns 0, then the link()
will fail.  If valid_link() returns 1, then the link will succeed if
rename() would succeed if called with the same arguments.

See also:
 link

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_object - allows control over which objects can be loaded

int valid_object( object obj );

After loading an object, the driver will call valid_object() with the newly
created object as its argument, in the master object.  If the function
exists, and returns 0, then the object will be destructed and the efun that
caused it to load will error out.  If it does not exist, or returns 1, then
loading will proceed as normal.  This is called before the object has a
chance to execute any code, including create(), so not much should be
assumed about the object except that file_name(obj) is valid.

See also:
 valid_override

back to top

valid_override - controls the use of efun:: 

int valid_override( string file, string efun_name, string mainfile );

File will be the actual file the call appears in; mainfile will be the file
being compiled (the two can differ due to #include)

Add valid_override to master.c in order to control the use of the efun::
prefix.  The valid_override function in master.c will be called each
time the driver attempts to compile a function call that begins with
efun::.  If valid_override returns 0, then that compile will fail.  Thus
valid_override provides a way to modify the behavior of efuns that isn't
circumventable via the efun:: prefix (by having a simul_efun of the same
name as the efun to be modified and having valid_override disallow that
simul_efun from being overriden).

If you wish to have the original 3.1.2 efun:: behavior, simply add
a line to master.c that looks like this:

   int valid_override(string file, string efun) { return 1; }

Here is an example valid_override that is more restrictive:

  int
  valid_override(string file, string name)
  {
      if (file == "/adm/obj/simul_efun") {
          return 1;
      }
      if (name == "destruct")
          return 0;
      if (name == "shutdown")
          return 0;
      if (name == "snoop")
          return 0;
      if (name == "exec")
          return 0;
      return 1;
   }

See also:
valid_object,
function_exists

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_read - checks if a certain person has read permission on a file

int valid_read( string file, object user, string func );

Every time an object tries to read a file, the driver calls valid_read
in the master object to check if the read should be allowed.  The
arguments are the filename, the object making the read, and
the calling function name.  If valid_read returns non-zero, the read is
allowed.

See also:
 valid_write

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_save_binary - controls whether or not an object can save its loaded program

int valid_save_binary( string file ); 

This routine is only used when BINARIES are enabled.

When the driver is compiled with ALWAYS_SAVE_BINARIES, or an object uses
'#pragma save_binary', valid_save_binary is called with the program's filename.
If valid_save_binary returns 1, then the program will be saved to disk for
faster reloading, otherwise it will not be saved, and the next reload will
recompile as usual.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_seteuid - secures the use of seteuid

int valid_seteuid( object obj, string euid );

This routine is only used if PACKAGE_UIDS is defined.

The driver calls valid_seteuid(ob, euid) in the master object from inside the
seteuid(euid) efunction.  If valid_seteuid() returns 0, then the seteuid()
call will fail.  If valid_seteuid() returns 1, then the seteuid() will
succeed.  

See also:
 seteuid,
 geteuid,
 getuid,
 export_uid

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_shadow - controls which objects can be shadowed

int valid_shadow( object ob );

When an object attempts to shadow `ob' (with the shadow() efun), valid_shadow
in the master object is called.  One object parameter is passed, which is the
object that previous_object() is attempting to shadow.  valid_shadow() should
return 0 if the shadow should not be permitted, in which case the shadow() call
will return 0 and fail.  If valid_shadow() returns 1, the shadow is allowed.

See also:
 shadow,
 query_shadowing

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_socket - protects the socket efunctions

int valid_socket( object caller, string function, mixed array info );

Each of the socket efunctions calls valid_socket() prior to executing.
If valid_socket returns 0, then the socket efunction fails.  If
valid_socket returns 1, then the socket efunction attempts to succeed.
The first argument 'caller' is the object that called the socket efunction.
The second argument is the name of the socket efunction that is being
called (e.g. socket_write() or socket_bind()).  The third argument is
an array of information.  The first element of the array (when applicable)
is file descriptor being referenced.  The second element of the array
is the owner of the socket (object).  The third element of the array is
the address (string) of the remote end of the socket.  The fourth element
of the array is the port number associated with the socket.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_write - checks if a certain object has write permission on a file

int valid_write( string file, object ob, string func );

Every time an object tries to write a file, the driver calls valid_write
in the master object to check if the write should be allowed.  The
arguments are the filename, the object making the write, and
the calling function name (usually the name of the efun being used).
If valid_write returns non-zero, the write is allowed.

See also:
 valid_read

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

window_size - report the users window size

void window_size(int width, int height);

window_size() is called with the user's window size, as reported by telnet
negotiation.  If the user's client never responds to the query, this is
never called.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

write_prompt - called when the parser wants a prompt to be written.

void write_prompt();

If write_prompt is present in the player object, the driver will call it
whenever the default prompt would normally be printed.  The driver will
not call write_prompt when the player is in input_to or ed.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

catch_tell - provides an interface to interact with users

void catch_tell( string message );

If INTERACTIVE_CATCH_TELL is defined in options.h, whenever the driver
has something to tell an object due to say(), shout(), tell_object(), etc.
catch_tell in the player object will be called with the message to
be printed.  The message can be displayed, discarded, or modified in
any way desired.  This is a useful way to have flexible earmuffs, or
to support intelligent clients.

See also:
 message,
 receive,
 receive_message

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

logon - initialize a logon connection

object logon(); 

This apply is called on the object returned by the connect() master
apply, after that object has been made into an interactive object,
so the object can initiate any logon sequence which is wanted.  This
function is no longer required to exist.  this_user() will be the
interactive object.

See also:  connect

back to top

net_dead - called by the MudOS driver when an interactive object drops its connection

void net_dead( void ); 

If an interactive object (i.e. a user object) suddenly loses its
connection (i.e. it goes "net dead"), then the driver calls this
function on that object giving it a chance to clean up, notify its
environment etc.  Be aware that functions that depend on the object
being interactive will not work as expected.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

process_input - inspect (and possibly modify) user input

mixed process_input( string );

If process_input is present in the player object, then the MudOS driver
will send it a copy of each line the player types.  If a string is returned,
that string is used as instead of the user input for further processing.
If a non-zero, non-string is returned, no further processing is done.
If zero is returned, processing continues with the original input.
Matching against add_actions is then done.

Note: If NO_ADD_ACTION is defined, then there is no more processing to be
done after process_input.  In this case, the return value is ignored, and
the mudlib is responsible for interpreting the string as a command (or other
user input for non-command based uses).

See also:  add_action

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

receive_message - provides the interface used by the message efun.

void receive_message( mixed cl, mixed message );

The message() efun calls this method in the player object.  The cl
parameter is typically used to indicate the class (say, tell, emote,
combat, room description, etc) of the message.  The receive_message() 
apply together with the message() efun can provide a good mechanism for
interfacing with a "smart" client.

See also:
 catch_tell,
 message,
 receive,
 receive_snoop

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

receive_snoop - catch incoming snoop text

void receive_snoop(string message);

If RECEIVE_SNOOP is defined in options.h or  local_options,
whenever a user is snooping another
user, all snoop text is sent to receive_snoop() in their user object.  Inside
of this function, you can do as you wish with the text.  A common activity
would be to receive() it.

See also:
 catch_tell,  receive

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

telnet_suboption - process telnet suboptions

void telnet_suboption( string buf );

This apply is called on the interactive object with the parameter given
by the SE telnet suboption, for mudlib defined processing.  Note that
terminal type responses and window size responses are interpreted and
sent to terminal_type() and window_size() respectively instead of going
through telnet_suboption().

The first byte of the buffer is typically a type descriptor,
ie TELOPT_TTYPE. The next byte is a procession option, such
as TELQUAL_IS.  Following this is the type dependent data.

See also:  terminal_type,  window_size

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

terminal_type - inform the mudlib of the user's terminal type

void terminal_type( string term );

This apply is called on the interactive object with term set to the
terminal type for the user, as reported by telnet negotiation.  If the
user's client never responds (it's not telnet, for example) this will
never be called.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

window_size - report the users window size

void window_size(int width, int height);

window_size() is called with the user's window size, as reported by telnet
negotiation.  If the user's client never responds to the query, this is
never called.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

write_prompt - called when the parser wants a prompt to be written.

void write_prompt();

If write_prompt is present in the player object, the driver will call it
whenever the default prompt would normally be printed.  The driver will
not call write_prompt when the player is in input_to or ed.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

author_file - determine the author for a given object

string author_file (string file);

This routine is only used if PACKAGE_MUDLIB_STATS is used.

This function must exist in the master object.  It is called by the
author statistic functions in the driver to determine what author a
given object should be associated with.  This is totally arbitrary and
up to the mudlib designers wishes.  It should be noted that the author
that the object is assigned to will receive "credit" for all of the
objects behavior (errors, heart_beats, etc).

See also:
 author_stats,
 domain_stats,
 domain_file

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

compile_object - serves as the mudlib interface for the virtual object facility

object compile_object( string pathname );

The driver calls compile_object in the event that the mudlib instructs
the driver to load a file that does not exist.  For example, the driver
will call compile_object("/obj/file.r") in master if the mudlib calls
call_other("/obj/file.r", "some_function") or new("/obj/file.r")
and /obj/file.r.c names a file that does not exist.  The compile_object()
function is expected to return 0 if the mudlib does not wish to
associate an object with the file name "/obj/file.r".  If the mudlib
does wish to associate an object with the filename "/obj/file.r", then
the mudlib should return the object it wishes associated.  After an
association is made between an object and a filename, then it will be
as if the file, file.r.c, did exist (to the driver) and when loaded produced
the object that compile_object() returned.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

connect - get an object for a new user

object connect(int port);

The driver calls connect() in the master object whenever a new user logs
into the driver.  port is the actual port connected to; for example if
you have two login ports defined as 2000 and 3000, either 2000 or 3000 
will be passed to this routine.

The object returned by connect() is used as the initial
user object.  Note that it is possible to change the user object at a later
time (for example, after determining who is logging in) using the exec()
efun.

See also:  logon,  exec

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

crash - function in master that is called in the event the driver crashes

void crash( string crash_message, object command_giver, object current_object );

The driver calls crash() in master in the event that the driver crashes
(segmentation fault, bus error, etc).  This function offers a way to
shutdown the mudlib (safe players and other important data) before the driver
crashes.  It also lets you log various useful information such as what
signal crashed the driver, what object was active, who the current player
was etc.

See also:
 shutdown,
 slow_shutdown

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

creator_file - specifies the uid to give to a newly created object

string creator_file(string filename);

This routine is only used if PACKAGE_UIDS is used.

The creator_file() function is called in the master object each time a new
object is created.  The `filename' of the object is passed as the sole
parameter, and the string that creator_file() returns is set as the new
object's uid.  If the AUTO_SETEUID option is enabled at compile-time of the
driver, it is also set as the new object's euid.
.PP
One exception: if the AUTO_TRUST_BACKBONE option is enabled at compile-time of
the driver, and creator_file() returns the backbone uid (as specified by
get_bb_uid() in the master object), the object is given the uid and euid of
the object that loaded it.

See also:
 seteuid,
 clone_object,
 new

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

domain_file - determine the domain for a given object

string domain_file( string file );

This function must exist in the master object.  It is called by the
domain statistic functions in the driver to determine what domain a
given object should be associated with.  This is totally arbitrary and
up to the mudlib designers wishes.  It should be noted that the domain
that the object is assigned to will receive "credit" for all of the
objects behavior (errors, heart_beats, etc).

See also:
 author_stats,
 domain_stats,
 author_file

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

epilog - handle initialization

string array epilog( int load_empty ); 

The driver calls epilog() in master after the master object has been loaded.
Required initialization may be done at this point.  If epilog() returns an
array of filenames, the driver will attempt to load those files via the
preload() function.

The variable 'load_empty' is non-zero if the -e option was specified
when starting up the driver, which has been historically used to mean
no preloads, although the mudlib is free to use another interpretation.

See also:  preload

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

error_handler - function in master object to handle errors

void error_handler( mapping error, int caught );

This function is only called if MUDLIB_ERROR_HANDLER is defined.

This function allows the mudlib to handle runtime errors.
The contents of the 'error' mapping are:
    ([
        "error"   : string,        // the error
        "program" : string,        // the program
        "object"  : object,        // the current object
        "line"    : int,           // the line number
        "trace"   : mapping array  // a trace back
    ])

Each line of traceback is a mapping containing the following:

    ([
        "function"  : string,   // the function name
        "program"   : string,   // the program
        "object"    : object,   // the object
    "file"      : string,   // the file to which the line number refers
        "line"      : int,      // the line number
        "arguments" : array,    // function arguments
        "locals"    : array     // local variables
    ])

arguments and local variables are only available if ARGUMENTS_IN_TRACEBACK
and LOCALS_IN_TRACEBACK are defined.

The 'caught' flag is 1 if the error was trapped by catch().

See also:
catch,
error,
throw,
log_error

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

flag - handle mudlib specific flags specified at driver startup

void flag( string );

This master apply is called for each command line
option passed to the driver with the -f flag.  For example, invoking the
driver via:

./driver -fdebug

will call flag("debug") in the master object during initialization.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

get_bb_uid - get the backbone uid

string get_bb_uid();

This routine is only used if PACKAGE_UIDS is used.

This master apply is called by the driver on startup,
after it has loaded the master object, to get the
backbone uid defined by the mud.  The function should
return a string, eg "BACKBONE"

See also:
 get_root_uid

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

get_root_uid - get the root uid

string get_root_uid();

This function is only used if PACKAGE_UIDS is used.

This master apply is called by the driver each time
it loads the master object, to verify that the master
object has loaded, and to get the root uid defined by
the mud.  The function should return a string, eg "ROOT"

See also:
 get_bb_uid

back to top

get_save_file_name - back up editor file on abnormal exit

string get_save_file_name( string file, object who );

This master apply is called by ed() when a player disconnects
while in the editor and editing a file.  This function
should return an alternate file name for the file to
be saved, to avoid overwriting the original.

Note: This apply used to be named get_ed_buffer_save_file_name().

See also:
 ed

back to top

log_error - log errors intelligently

void log_error( string file, string message );

Whenever an error occurs during compilation, the function log_error in
the master object is called with the filename that the error occurred
in and the error message itself.  Then, log_error is free to do
whatever it thinks it should do with that information.  Usually this
is deciding based on the filename where the error message should be
logged, and then writing it to that file.  Warnings also pass through
this routine, and can be detected since they start with "Warning:"

See also:
 error_handler

back to top

make_path_absolute - resolve relative path name

string make_path_absolute( string rel_path );

This master apply is called by the ed() efun to
resolve relative path names of a file to read/write, to an absolute path
name.

See also:
 ed

back to top

object_name - called by the driver to find out an object's name

string object_name( object );

This master apply is called by the sprintf() efun, when
printing the "value" of an object.  This function should
return a string corresponding to the name of the object
(eg a user's name).

See also:
 file_name

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

parse_command_all_word - find out what word refers to everything

string parse_command_all_word(); 

This routine is called in the master object to find out what word should
be considered to refer to everyting.  It is used by the parse_command() efun.

See also:
 parse_command

back to top

parse_command_prepos_list - find out what words are valid prepositions

string array parse_command_prepos_list(); 

This routine is called in the master object to find out what words should
be considered prepositions.  It is used by the parsing package and the
parse_command() efun.

See also:
 parse_command

back to top

preload - preload an object into memory

void preload( string filename );

For each string in the array returned by epilog, the driver calls 
preload(filename).  Note that there is the equivalent of a catch() around
these calls at the driver level, so it is not neccessary for the mudlib
to worry about the sequence being terminated by an error.

Typical behavoir is to use load_object() to attempt to load the file.

See also:  preload, ,
           load_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

privs_file - specifies the privs string to give to a newly created object

string privs_file( string filename );

The privs_file() function is called in the master object when a new file
is created.  The `filename' of the object is passed as the argument, and
the string that privs_file() returns is used as the new object's privs
string.

The privs_file() functionality is only available if the driver is compiled
with the PRIVS option defined.

See also:
 query_privs
 set_privs

back to top

retrieve_ed_setup - retrieve a user's editor setup or configuration settings

int retrieve_ed_setup( object user );

This master apply is called by the ed() efun to retrieve
a user's ed setup/configuration settings.  This function
should return the setup (contained in an int).

See also:
 save_ed_setup

back to top

save_ed_setup - save a user's editor setup or configuration settings

int save_ed_setup( object user, int config );

This master apply is called by the ed() efun to save
a user's ed setup/configuration settings (contained in
an int).  This function should return an int for
success (1 or TRUE)/failure (0 or FALSE).

Seel also:
 retrieve_ed_setup

back to top

slow_shutdown - informs the mud that a slow shutdown is in progress

int slow_shutdown( int minutes );

This master apply is called when the driver can't
allocate any more memory from the heap and had to
use its reserved memory block.  This function can
only be called if the "reserved size" config file
setting was set.  The minutes remaining to driver
shutdown is passed to this function.  If this function
does ont exist, or returns zero, the driver shuts
down immediately.

See also:
 crash,
 shutdown

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_bind - determine if it is legal to bind a given function pointer to an object

int valid_bind(object doer, object owner, object victim); 

This is called when 'doer' tries to use the bind() efun to bind a function
pointer owned by 'owner' to the object 'victim'.  If this routine returns
zero, the operation is disallowed.

See also:
 bind

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_compile_to_c - determine whether LPC->C compilation may take place

int valid_compile_to_c(); 

valid_compile_to_c() is called when the generate_source() efun is used to
generate C files or to do runtime compilation of an object.  One might
want to restrict the use of this since the process can be CPU intensive.

See also:  generate_source

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_hide - allows or disallows objects to hide and see hidden objects

int valid_hide( object ob );

Add valid_hide to master.c in order to allow objects to hide themselves,
or see other objects that have hidden themselves.  When an object tries to
use the set_hide() efun to hide itself, valid_hide will be called with the
object that is wanting to hide as the sole parameter.  It should return 1
to allow it, or 0 to not allow it.  The same call takes place when it needs
to be determined if a certain object should be able to see hidden objects.

See also:
 set_hide

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_link - controls the use of the link efun

int valid_link( string from, string to );

The driver calls valid_link(from, to) in the master object from inside the
link(from, to) efunction.  If valid_link() returns 0, then the link()
will fail.  If valid_link() returns 1, then the link will succeed if
rename() would succeed if called with the same arguments.

See also:
 link

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_object - allows control over which objects can be loaded

int valid_object( object obj );

After loading an object, the driver will call valid_object() with the newly
created object as its argument, in the master object.  If the function
exists, and returns 0, then the object will be destructed and the efun that
caused it to load will error out.  If it does not exist, or returns 1, then
loading will proceed as normal.  This is called before the object has a
chance to execute any code, including create(), so not much should be
assumed about the object except that file_name(obj) is valid.

See also:
 valid_override

back to top

valid_override - controls the use of efun:: 

int valid_override( string file, string efun_name, string mainfile );

File will be the actual file the call appears in; mainfile will be the file
being compiled (the two can differ due to #include)

Add valid_override to master.c in order to control the use of the efun::
prefix.  The valid_override function in master.c will be called each
time the driver attempts to compile a function call that begins with
efun::.  If valid_override returns 0, then that compile will fail.  Thus
valid_override provides a way to modify the behavior of efuns that isn't
circumventable via the efun:: prefix (by having a simul_efun of the same
name as the efun to be modified and having valid_override disallow that
simul_efun from being overriden).

If you wish to have the original 3.1.2 efun:: behavior, simply add
a line to master.c that looks like this:

   int valid_override(string file, string efun) { return 1; }

Here is an example valid_override that is more restrictive:

  int
  valid_override(string file, string name)
  {
      if (file == "/adm/obj/simul_efun") {
          return 1;
      }
      if (name == "destruct")
          return 0;
      if (name == "shutdown")
          return 0;
      if (name == "snoop")
          return 0;
      if (name == "exec")
          return 0;
      return 1;
   }

See also:
valid_object,
function_exists

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_read - checks if a certain person has read permission on a file

int valid_read( string file, object user, string func );

Every time an object tries to read a file, the driver calls valid_read
in the master object to check if the read should be allowed.  The
arguments are the filename, the object making the read, and
the calling function name.  If valid_read returns non-zero, the read is
allowed.

See also:
 valid_write

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_save_binary - controls whether or not an object can save its loaded program

int valid_save_binary( string file ); 

This routine is only used when BINARIES are enabled.

When the driver is compiled with ALWAYS_SAVE_BINARIES, or an object uses
'#pragma save_binary', valid_save_binary is called with the program's filename.
If valid_save_binary returns 1, then the program will be saved to disk for
faster reloading, otherwise it will not be saved, and the next reload will
recompile as usual.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_seteuid - secures the use of seteuid

int valid_seteuid( object obj, string euid );

This routine is only used if PACKAGE_UIDS is defined.

The driver calls valid_seteuid(ob, euid) in the master object from inside the
seteuid(euid) efunction.  If valid_seteuid() returns 0, then the seteuid()
call will fail.  If valid_seteuid() returns 1, then the seteuid() will
succeed.  

See also:
 seteuid,
 geteuid,
 getuid,
 export_uid

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_shadow - controls which objects can be shadowed

int valid_shadow( object ob );

When an object attempts to shadow `ob' (with the shadow() efun), valid_shadow
in the master object is called.  One object parameter is passed, which is the
object that previous_object() is attempting to shadow.  valid_shadow() should
return 0 if the shadow should not be permitted, in which case the shadow() call
will return 0 and fail.  If valid_shadow() returns 1, the shadow is allowed.

See also:
 shadow,
 query_shadowing

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_socket - protects the socket efunctions

int valid_socket( object caller, string function, mixed array info );

Each of the socket efunctions calls valid_socket() prior to executing.
If valid_socket returns 0, then the socket efunction fails.  If
valid_socket returns 1, then the socket efunction attempts to succeed.
The first argument 'caller' is the object that called the socket efunction.
The second argument is the name of the socket efunction that is being
called (e.g. socket_write() or socket_bind()).  The third argument is
an array of information.  The first element of the array (when applicable)
is file descriptor being referenced.  The second element of the array
is the owner of the socket (object).  The third element of the array is
the address (string) of the remote end of the socket.  The fourth element
of the array is the port number associated with the socket.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

valid_write - checks if a certain object has write permission on a file

int valid_write( string file, object ob, string func );

Every time an object tries to write a file, the driver calls valid_write
in the master object to check if the write should be allowed.  The
arguments are the filename, the object making the write, and
the calling function name (usually the name of the efun being used).
If valid_write returns non-zero, the write is allowed.

See also:
 valid_read

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

parse_command(3)      LPC Library Functions      parse_command(3)

NAME
       parse_command()  - try to match a string with a given pat-
       tern

SYNOPSIS
       int parse_command( string command, object env|object *oblist,
                          string pattern, mixed arg, ... );

DESCRIPTION
       parse_command() is a piffed up sscanf(3) operating on word
       basis.   It  works similar to sscanf(3) in that it takes a
       pattern and a variable set of destination arguments. It is
       together  with sscanf(3) the only efun to use pass by ref-
       erence  for  other  variables  than  arrays.    That   is,
       parse_command() returns values in its arguments.

       parse_command()  returns  1  if 'command' is considered to
       have matched

       The 'env' or 'oblist' parameter either holds an object  or
       a list of objects. If it holds a single object than a list
       of  objects  are  automatically  created  by  adding   the
       deep_inventory of the object, ie this is identical:

          parse_command(cmd, environment(), pattern, arg)

       and

          parse_command( cmd, ({ environment() }) +
                         deep_inventory(environment()), pattern, arg)

          Example string = " 'get' / 'take' %i "
               Syntax:
                       'word'          obligatory text
                       [word]          optional text
                       /               Alternative marker
                       %o              Single item, object
                       %l              Living objects
                       %s              Any text
                       %w              Any word
                       %p              One of a list (prepositions)
                       %i              Any items
                       %d              Number 0- or tx(0-99)

       The  'arg'  list  is zero or more arguments. These are the
       result variables as in sscanf. Note that one  variable  is
       needed for each %_

       The return types of different %_ is:
                       %o      Returns an object
                       %s      Returns a string of words

MudOS                       5 Sep 1994                          1

parse_command(3)      LPC Library Functions      parse_command(3)

                       %w      Returns a string of one word
                       %p      Can on entry hold a list of word in array
                               or an empty variable
                               Returns:
                                  if empty variable: a string
                                  if array: array[0] = matched word
                       %i      Returns a special array on the form:
                               [0] = (int) +(wanted) -(order) 0(all)
                               [1..n] (object) Objectpointers
                       %l      Returns a special array on the form:
                               [0] = (int) +(wanted) -(order) 0(all)
                               [1..n] (object) Objectpointers
                                               These are only living objects.
                       %d      Returns a number

       The  only  types of % that uses all the loaded information
       from the objects are %i and %l. These are in fact  identi-
       cal  except that %l filters out all nonliving objects from
       the list of objects before trying to parse.

       The return values of %i and %l is also the  most  complex.
       They return an array consisting of first a number and then
       all possible objects  matching.   As  the  typical  string
       matched  by  %i/%l looks like: 'three red roses', of these
       numerical constructs was matched:

          if numeral >0 then three, four, five etc were matched
          if numeral <0 then second, twentyfirst etc were matched
          if numeral==0 then 'all' or a generic plural form such as
                         'apples' were matched.

       NOTE!

                The efun makes no  semantic  implication  on  the
              given numeral. It does
                not  matter  if 'all apples' or 'second apple' is
              given. A %i will
                return  ALL  possible  objects  matching  in  the
              array. It is up to the
                caller  to  decide what 'second' means in a given
              context.
                Also when given an object  and  not  an  explicit
              array of objects the
                entire recursive inventory of the given object is
              searched. It is up
                to the caller to decide which of the objects  are
              actually visible
                meaning  that  'second' might not at all mean the
              second object in
                the returned array of objects.

CAVEAT
       Patterns of type: "%s %w %i" Might not work as  one  would

MudOS                       5 Sep 1994                          2

parse_command(3)      LPC Library Functions      parse_command(3)

       expect.   %w  will always succeed so the arg corresponding
       to %s will always be empty.

BUGS
       Patterns of the type: 'word' and [word] The 'word' can not
       contain  spaces.   It  must  be a single word.  This is so
       because the pattern is exploded on " " (space) and a  pat-
       tern element can therefore not contain spaces.

       As  another  effect  of  the  exploding on space, separate
       pieces of a pattern MUST be separated with space, ie not "
       'word'/%i " but " 'word' / %i"

       EXAMPLE:
            if (parse_command("spray car",environment(this_player()),
                              " 'spray' / 'paint' [paint] %i ",items))
                {
                   /*
                     If the pattern matched then items holds a return array as
                     described under 'destargs' %i above.
                   */
                }

       MUDLIB SUPPORT

       To  make  the  efun  useful it must have a certain support
       from the mudlib, there is a set of functions that it needs
       to call to get relevant information before it can parse in
       a sensible manner.

       In earlier versions it used the normal id()  lfun  in  the
       LPC  objects  to find out if a given object was identified
       by a certain string. This was  highly  inefficient  as  it
       could  result in hundreds or maybe thousands of calls when
       very long commands were parsed.

       The new version relies on the LPC objects to give it three
       lists of 'names'.

          1 - The normal singular names.
          2 - The plural forms of the names.
          3 - The acknowledged adjectives of the object.

       These are fetched by calls to the functions:

          1 - string *parse_command_id_list();
          2 - string *parse_command_plural_id_list();
          3 - string *parse_command_adjectiv_id_list();

       The  only  really  needed list is the first. If the second
       does not exist than the efun will try to create  one  from
       the  singluar  list.   For grammatical reasons it does not
       always succeed in a perfect way.  This is especially  true

MudOS                       5 Sep 1994                          3

parse_command(3)      LPC Library Functions      parse_command(3)

       when the 'names' are not single words but phrases.

       The third is very nice to have because it makes constructs
       like

       Apart from  these  functions  that  should  exist  in  all
       objects,  and  which  are  therefore  best put in the base
       mudlib object there is also a set of functions  needed  in
       the master object.  These are not absolutely necessary but
       they give extra power to the efun.

       Basically these master object  lfuns  are  there  to  give
       default  values  for  the lists of names fetched from each
       object.

       The names in these lists are applicable  to  any  and  all
       objects, the first three are identical to the lfuns in the
       objects:

          string *parse_command_id_list()
             - Would normally return: ({ "one", "thing" })

          string *parse_command_plural_id_list()
             - Would normally return: ({ "ones", "things", "them" })

          string *parse_command_adjectiv_id_list()
             - Would normally return ({ "iffish" })

       The last two are the default list of the prepositions  and
       a single so called
          string *parse_command_prepos_list()
             - Would normally return: ({ "in", "on", "under" })

          string parse_command_all_word()
             - Would normally return: "all"

MudOS                       5 Sep 1994                          4

back to top

parse_command_adjectiv_id_list - returns a list of names to the parser

string array parse_command_adjectiv_id_list(); [sic] 

This routine is used to find out what adjectives the object responds to, and is
used by the parsing package and the parse_command() efun.  In addition,
anything returned by the master object will work on ANY object.

See also:
 parse_command

back to top

parse_command_id_list - returns a list of names to the parser

string array parse_command_id_list(); 

This routine is used to find out what nouns the object responds to, and is
used by the parsing package and the parse_command() efun.  In addition,
anything returned by the master object will work on ANY object.

See also:
 parse_command

back to top

parse_command_plural_id_list - returns a list of names to the parser

string array parse_command_plural_id_list(); 

This routine is used to find out what plural nouns the object responds to,
and is used by the parsing package and the parse_command() efun.  In addition,
anything returned by the master object will work on ANY object.

See also:
 parse_command

back to top

allocate - allocate an array

array allocate( int size );

Allocate an array of  elements.  The number of elements must be >= 0
and not bigger than a system maximum (usually ~10000).  All elements are
initialized to 0.

See also:
 sizeof,
 allocate_mapping

back to top

filter_array - return a selective sub-array

array filter_array( array arr, string fun, object ob, mixed extra, ... );

array filter_array( array arr, function f, mixed extra, ...);

filter_array() is really the same as the filter() efun.

See also:
 filter

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

map_array - modify an array of elements via application of a function

array map_array( array arr, string fun, object ob, mixed extra, ... );

array map_array( array arr, function f, mixed extra, ... );;

The map_array() efun is really just an alias for the map() efun.

See also:
 map

back to top

member_array - returns index of an occurence of a given item in an array or string

int member_array( mixed item, mixed arr);

int member_array( mixed item, mixed arr, int start);

Returns the index of the first occurence of `item' in the array  or string
`arr', or the first occurence at or after 'start'.
If the item is not found, then -1 is returned.

For the purpose of this efun, strings are considered to be arrays of ints.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

sort_array - sort an array

array sort_array( array arr, string fun, object ob, ... );

array sort_array( array arr, function f, ... );

array sort_array( array arr, int direction );

The (ob, fun) syntax behaves the same as if (: call_other, ob, fun :)
was passed as f.

In the first two forms, the returned array is sorted with respect to
the comparison function given.  The function takes two elements as
arguments, and returns -1 if if first argument is less than the second,
0 if they are the same, or 1 if the first argument is greater than the
second.  Any additional arguments are passed to the comparison function
as the third and following arguments.

The third form returns an array with the same elements as 'arr', but
quicksorted using built-in sort routines.  A 'direction' of 1 or 0 will
quicksort in ascending order, while a 'direction' of -1 will
quicksort in descending order.  A limitation of the built-in
sort routines is that the array must be homogeneous, composed entirely
of a single type, where that type is string, int, or float.
Arrays of arrays are sorted by sorting based on the first element,
making database sorts possible.

See also:
 strcmp

back to top

unique_array - partitions an array of objects into groups

array unique_array(object array obarr, string separator);

array unique_array(object array obarr, string separator, mixed skip);

array unique_array(array arr, function f);

array unique_array(array arr, function f, mixed skip);

Groups objects/values together for which the `separator' function
returns the same value.  In the first case, "separator" is a string function
name to try on each object.  In the second case, the function f is called
with the element as the argument.  If 'skip' is passed, elements for which
the separator function returns the same as 'skip' are omitted from the
return value.

The return value is an array of arrays of the form:
     ({
         ({Same1:1, Same1:2, Same1:3, .... Same1:N }),
         ({Same2:1, Same2:2, Same2:3, .... Same2:N }),
         ({Same3:1, Same3:2, Same3:3, .... Same3:N }),
                       ....
                       ....
         ({SameM:1, SameM:2, SameM:3, .... SameM:N }),
     })

i.e. an array of arrays, where each of the elements in the sub arrays returned
the same value as the other elements in the same sub array.

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

allocate_buffer - allocate a buffer

buffer allocate_buffer( int size );

This efun is only available if DISALLOW_BUFFER_TYPE is not compiled in.

Allocate a buffer of 'size' elements.  The number of elements must be >= 0 
and not bigger than a system maximum (usually ~10000).  All elements are 
initialized to 0.

See also:
 bufferp,
 read_buffer,
 write_buffer

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

crc32 - compute the cycle redundancy code for a buffer or string

int crc32( buffer | string x );

Computes and returns the CRC-32 code for the given buffer or string, `x'.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

read_buffer - read from a file and return a buffer

mixed read_buffer( mixed src, int start, int len);

This efun is only available if DISALLOW_BUFFER_TYPE is not compiled in.

If 'src' is a string (filename), then the filename will be read, starting
at byte # 'start', for 'len' bytes, and returned as a buffer.  If neither
argument is given, the entire file is read.

If 'src' is a buffer, then characters are read from the buffer beginning
at byte # 'start' in the buffer, and for 'len' # of bytes, and returned
as a string.

Note that the maximum number of bytes you can read from a file and into
a buffer is controlled via the 'maximum byte transfer' parameter in the
runtime config file.

See also:
 write_buffer,
 allocate_buffer,
 bufferp,
 read_bytes,
 write_bytes

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

write_buffer - write a buffer to a file

int write_buffer(mixed dest, int start, mixed source );

If `dest' is a file, then `source' must be an int (and will be written to
the file in network-byte-order), a buffer, or a string, and `source' will
be written to the file `dest' starting at byte # `start'.

If `dest' is a buffer, then `source' will be written into the buffer starting
at byte # `start' in the buffer.  If `source' is an int, it will be written
in network-byte-order.

See also:
 read_buffer,
 allocate_buffer

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

call_other - call a function in another object

mixed call_other(mixed ob, string func, ...); 

mixed call_other(mixed ob, array args); 

mixed call_other(array obs, string func, ...); 

mixed call_other(array obs, array args); 

ob is either an object pointer, or a string filename (suitable for 
find_object()).  obs is an array of object pointers and strings.
Using an array as the first argument does a call_other for each element of
the array, and returns an array of the results.
If the array form is used for args, then the first element is the function
name, and the remainder are the arguments; e.g.:

call_other(ob, ({ "foo", 1, 3, 5 }))

and

call_other(ob, "foo", 1, 3, 5)

are equivalent.  The function foo() is called in the object ob with the
arguments (1, 3, 5).  The return value of call_other() is the value
returned from the foo() function.  In the case of an array of objects,
the return value of call_other() is an array of the return values.

There is a much more attractive way to do call_others;
call_other(x, "y", z, ...) is the same as:

x->y(z, ...)

ie,

call_other(ob, "query_name");

could be written as:

ob->query_name();

Writing out the call_other call is mainly used when the function name
is in a variable, i.e:

void do_test(string fname, int x) {
    call_other(fname, "test_" + x);
}

An example of using an array as the first argument:

users()->quit();

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

call_out - delayed function call in same object

int call_out( function fun, int delay, mixed arg, ... );

Set up a call to 'fun'.  If fun is a string, it is interpreted as the
name of a function in this_object().  The call will take place 'delay'
seconds later, with the arguments 'arg' and following provided.

Note:
Unless THIS_PLAYER_IN_CALL_OUT is defined, you can't rely on
write() or say() in 'fun' since this_player() is set to 0.
Use tell_object() instead.

If THIS_PLAYER_IN_CALL_OUT is defined, this_player() is the same as
it was when the call_out() call was scheduled.

The return value will be a unique integer identifying the call_out, if
CALLOUT_HANDLES is defined.  This 'handle' can be passed to
remove_call_out() and find_call_out().

See also:
 remove_call_out,
 call_out_info,
 find_call_out

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

call_stack - returns information about the functions involved in calling this function

array call_stack(int);

If the int argument is 0, call_stack() returns an array of the names of the
on the call stack, with the first one being the most recent (i.e. the
currently running program).  If the int argument is 1, call_stack returns
the objects in which that program is executing.  If it is 2, the name
of the functions are returned.  If it is 3, the value of origin() in that
frame is returned.

See also:
 previous_object,
 origin

back to top

catch - catch an evaluation error

mixed catch( mixed expr );

mixed catch { ... }; 

Note: catch is really a keyword and not an efun.

The code inside the { ... } or the expression is evaluated.  If there
is no error, catch() returns zero.  If there is an error, a string (with
a leading '*') will be returned.

The function throw() can also be used to immediately return any value,
except 0.

The catch() is somewhat costly, and should not be used just anywhere.
Rather, use it at places where an error would destroy consistency.

See also:
 error,
 throw,
 error_handler

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

origin - determine how the current function was called

string origin();

Returns an string specifying how the current function was called.  These
values can be found in the driver include "origin.h".  Current values are:

* "driver" - from the driver: applies, heart_beats, etc * "local" - local function call * "call_other" - call_other * "simul" - use of a simul_efun * "call_out" - via a call_out * "efun" - from an efun that takes a function pointer (sort_array, etc)
See also: previous_object

back to top

previous_object - returns the object(s) that called the current function

object previous_object(); 
mixed previous_object(int x); 

Returns an object pointer to the object, if any, that called current function.
Note that local function calls do not set previous_object() to the current
object, but leave it unchanged.  If passed a positive integer, it goes back
the given number of previous objects in the calling chain.
previous_object(0) is the same as previous_object(), previous_object(1) is
the previous object's previous_object(), etc.  previous_object(-1) returns
an array containing all of the previous objects.

See also:
 call_other,
 call_out,
 origin

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_shadowing - determine whether or not a given object it shadowing another

object query_shadowing( object ob );

This efun is only available if NO_SHADOWS is not compiled in.

Returns the object that `ob' is shadowing, or zero (0) if it is not
shadowing any object.

See also:
 shadow,
 valid_shadow

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

remove_call_out - remove a pending call_out

int remove_call_out( string fun | int handle );

Remove next pending call out for function `fun' in the current object,
or the call_out() which returned the integer 'handle'.
The return value is the time remaining before the callback is to be called.
The returned value is -1 if there were no call out pending to this function.
If fun is zero, all the call_outs of the object are removed.

See also:
 call_out,
 call_out_info

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

remove_shadow - clear all the shadows related to an object.

int remove_shadow(object);

This function removes ALL shadows associated with the object passed
as the argument. Note this means all shadows ON the object, and all shadows
ORIGINATED by the object.

This function requires PACKAGE_CONTRIB to be defined in the options file.
This function also requires that the option NO_SHADOWS be undefined.

See also:
 shadow

back to top

shadow - shadow one or more functions in some object

object shadow( object ob, int flag );

This efun is only available if NO_SHADOWS is not compiled in.

If 'flag' is 1 or missing, then current object will shadow 'ob'. If
'flag' is 0, then either 0 will be returned, or the object that is
already shadowing 'ob'.

The master object defines the function "valid_shadow()".  If it returns 1
the target object can't be shadowed, and the "shadow()" function will
return 0 instead of 'ob'.

If an object 'a' shadows an object 'b', then all "call_other(func)" to 'b'
will be redirected to 'a'. If object 'a' has not defined the function,
then the call will be forwarded to 'b' (as if there were no shadow).
There is only one object that can call functions in 'b' with
call_other(), and that is 'a'. Not even object 'b' can "call_other()"
itself. All normal (internal) function calls inside 'b' will however remain
internal to 'b'.

There are two ways to remove the shadow. Either destruct it, or the object
that was shadowed. In the latter case, the shadow will also be destructed
automatically.  Also, there is a efun remove_shadow() in the contrib package.

The result is that it is possible to hide an object behind another one,
but everything can be totally transparent.  The shadow() efunction makes
it possible to change the behavior of an object without changing the
code for the object in question.  One possible use for shadow() is to
add special capabilities to various classes of players (thief, fighter,
mage, etc).  This usage would make it possible to keep the player object
much simpler than it could be if the code for the various classes had
to be in the player object itself.

See also:
 destruct,
 query_shadowing,
 valid_shadow

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

this_object - return the object pointer of the calling object

object this_object();

Return the object pointer of the current object.  Useful for passing the
current object to other functions.

See also:
 this_player,
 previous_object,
 origin

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

throw - forces an error to occur in an object.

void throw(mixed);

Throw can be used to send an arbitrary value to an enclosing catch() statement.
If you want to raise a general error message, see error(), as that will
behave better if it is not caught.  Control is transfered directly to the
enclosing catch() statement, and the value of the catch() statement is the
value thrown.

See also:
 catch,
 error

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

generate_source - generates the C code corresponding to a give object(s)

int generate_source(string file);

int generate_source(string array files);

This efun is only available if LPC_TO_C is compiled into the driver.

generate_source() calls the LPC->C compiler to generate the source code
for a given object or objects.  If more than one file is passed, a directory
named 'mudlib' is created in the SAVE_BINARIES directory, and that directory
can be copied into the driver source directory and compiled into the driver.

If one file is given, the C source for that file is compiled, and the driver
attempts to link it into the running executable using the RUNTIME_LOADING
option.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

cp - copy a file

int cp(string src, string dst);

Copies the file 'src' to the file 'dst'.

Returns 1 for success, returns -1 if the first src is unreadable, -2 if
dst is unreadable, and -3 if an i/o error occurs.

See also:
 rm,
 rmdir,
 rename,
 link

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

file_length - get the number of lines in a file

int file_length( string file );

file_length() returns the number of lines in file 'file'.  Size -1
indicates that 'file' either does not exist, or that it is not
readable. Size -2 indicates that 'file' is a directory.

Note that this efun is not particularly fast on long files, since
determining the number of lines requires reading the entire file.

See also:
 file_size,
 stat,
 get_dir

back to top

file_size - get the size of a file

int file_size( string file );

file_size() returns the size of file 'file' in bytes.  Size -1
indicates that 'file' either does not exist, or that it is not
readable. Size -2 indicates that 'file' is a directory.

See also:
 file_length,
 stat,
 get_dir

back to top

get_dir - returns information pertaining to a filesystem directory

mixed array get_dir(string dir);

mixed array get_dir(string dir, int flag);

If `dir' is a filename ('*' and '?' wildcards are supported), an array of 
strings is returned containing all filenames that match the specification. 
If `dir' is a directory name (ending with a slash--ie: "/u/", "/adm/", etc),
all filenames in that directory are returned.  

If called with a second argument equal to -1, get_dir will return an array
of subarrays, where the format of each subarray is:

  ({ filename, size_of_file, last_time_file_touched })

Where filename is a string and last_time_file_touched is an integer being
number of seconds since January 1, 1970 (same format as time()).  The 
size_of_file element is the same value that is returned by file_size(); the 
size of the file in bytes, or -2 if it's a directory.  

See also: 
 file_size,
 stat,
 time,
 ctime

back to top

link - link a file to another

void link( string original, string reference );

Creates a link 'reference' to the file 'original'.  This efun causes
valid_link(original, reference) to be called in the master object.  If
valid_link() returns 0, the link() call fails.  If valid_link() returns 1
then the link() suceeds iff rename() would succeed if called with the same
arguments.

See also:
 rm,
 rmdir,
 rename,
 mkdir,
 cp

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

mkdir - make a directory

int mkdir( string directory );

Creates the specified directory.  Returns 1 if successful, 0 if not.

See also:
 rm,
 rmdir,
 link

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

read_bytes - reads a contiguous series of bytes from a file into a string

string read_bytes( string path, int start, int length );

This function reads 'length' bytes beginning at byte # 'start' in the
file named 'path'.  The bytes are returned as a string.  Note that
(start + length) must not be past the end of the file or else read_bytes
will fail.  If the second and third arguments are omitted, the entire file
is returned.

See also:
 read_file,
 write_bytes

back to top

read_file - read a file into a string

string read_file( string file, int start_line, int number_of_lines );

Read a line of text from a file into a string.  The second and third
arguments are optional.  If only the first argument is specified, the
entire file is returned (as a string).

The start_line is the line number of the line you wish to read.  This routine
will return 0 if you try to read past the end of the file, or if you try to
read from a nonpositive line.

See also:
 write_file,
 read_buffer

back to top

rename - rename a file

int rename( string src, string dst );

Renames the file 'src' to 'dst'.

rename() returns zero (0) to indicate success.  Nonzero indicates failure.

See also:
 rm,
 rmdir,
 cp,
 link

back to top

rm - remove a file

int rm( string file );

Remove file `file'. Returns 0 for failure and 1 for success.

See also:
 mkdir,
 rmdir,
 link

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

rmdir - remove a directory

int rmdir( string dir );

Remove directory `dir'. 
Returns nonzero for success, zero (0) for failure.

See also:
 rm,
 mkdir,
 link

back to top

stat - returns information pertaining to a file or a directory 

mixed stat(string str);
mixed stat(string str, int x);

If str is the name of a regular file (not a directory), then stat()
will return an array of information pertaining to that file.  The
form of the array is as follows:

   ({ file_size, last_time_file_touched, time_object_loaded })

If stat is called on a directory (not a regular file), or with a second
argument of -1, then stat() behaves identically to get_dir().

See also:
 get_dir,
 stat

back to top

tail - displays the latter portion of a file

int tail( string path );

This efunction displays the latter portion of the file named by path.
It returns 1 if successful, 0 otherwise (e.g. when the file is protected
against reading).

See also:
 read_file,
 read_buffer,
 file_size

back to top

write_bytes - writes a contiguous series of bytes to a file

int write_bytes( string path, int start, string series );

This function writes the bytes in 'series' into the file named by 'path'
beginning at byte # 'start'.  It returns zero (0) upon failure, 1 otherwise.

See also:
 write_file,
 read_bytes

back to top

write_file - appends a string to a file

int write_file( string file, string str, int flag );

Append the string `str' into the file `file'. Returns 0 or 1 for
failure or success.  If flag is 1, write_file overwrites instead of
appending.

See also:
 read_file,
 write_buffer,
 file_size

back to top

acos - return the arccosine of a float

float acos( float f );

This efun is available only if PACKAGE_MATH is compiled in to the driver.

Returns the arccosine of its argument, `f', measured in radians.

See also:
 asin,
 atan,
 cos,
 sin,
 tan

back to top

asin - return the arcsine of a float

float asin( float f );

This efun is only available if PACKAGE_MATH is compiled in.

Returns the arcsine of its argument, `f', measured in radians.

See also:
 acos,
 atan,
 cos,
 sin,
 tan

back to top

atan - return the tangent of a float

float atan( float f );

This efun is only available if PACKAGE_MATH is not compiled in.

Returns the arctangent of its argument, `f', measured in radians.

See also:
 acos,
 asin,
 cos,
 sin,
 tan

back to top

ceil - round a float up to the nearest integer

float ceil( float f );

This efun is only available if PACKAGE_MATH is compiled in.

Returns (as a float) the nearest integer number equal to or greater than f.

See also:
 floor,
 to_int,
 to_float

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

cos - return the cosine of a float

float cos( float f );

This efun is only available if PACKAGE_MATH is compiled into the driver.

Returns the cosine of its argument, `f', measured in radians.

See also:
 acos,
 asin,
 atan, 
 sin,
 tan

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

exp - find e to the power of a float

float exp( float f );

This efun is only available if PACKAGE_MATH is compiled in.

exp() returns e^f.

See also:
 log,
 pow,
 sqrt

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

floor - round a float down to the nearest integer

float floor( float f );

This efun is only available if PACKAGE_MATH is compiled in.

Returns (as a float) the nearest integer number equal to or smaller than f.

See also:
 ceil,
 to_int,
 to_float

back to top

log - returns the natural logarithm of a float

float log( float f );

This efun is only available if PACKAGE_MATH is compiled in.

Returns the natural logarithm of its argument, `f'.  `f' must be positive.

See also:
 exp,
 pow,
 sqrt

back to top

pow - find an exponent of a float

float pow( float x, float y );

This efun is only available if PACKAGE_MATH is defined.

pow() returns x to the y power.  If x is 0.0, y must be positive.  If x is
negative, y must be an integer.

See also:
 exp,
 log,
 sqrt

back to top

sin - return the sine of a float

float sin( float f );

This efun is only available if PACKAGE_MATH is compiled in.

Returns the sine of its argument, `f', measured in radians.

See also:
 acos,
 asin,
 atan,
 cos,
 tan

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

sqrt - returns the square root of a float

float sqrt( float f );

This efun is only available if PACKAGE_MATH is compiled in.

sqrt() returns the non-negative square root of its argument, `f'.  The value
of `f' must not be negative.

See also:
 exp,
 log,
 pow

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

tan - return the tangent of a float

float tan( float f );

This efun is only available if PACKAGE_MATH is compiled in.

Returns the tangent of its argument, 'f', measured in radians.

See also:
 acos,
 asin,
 atan,
 cos,
 sin

back to top

to_int - convert a float or buffer to an int

int to_int( float x );
int to_int( buffer x );
int to_int( string x );

If 'x' is a float, the to_int() call returns the number of type 'int' that is 
equivalent to 'x' (with any decimal stripped off).  If 'x' is a buffer, the
call returns the integer (in network-byte-order) that is embedded in the
buffer.  If 'x' is a string, then the string is converted to an integer.
An undefined value is returned if the string is not a valid number.

See also:
 to_float,
 read_buffer

back to top

bind - bind a function pointer to a new object

function bind(function, object);

bind() causes a function to become owned by the new object.  This changes
the value of this_object() when the function pointer is evaluated.  Functions
that reference global variables or functions in the object that created
them cannot be rebound.  Binding a function to the object it is already
bound to will never fail.

Permission to use this efun is controlled by the valid_bind() master apply.

See also:
 function_owner,
 valid_bind

back to top

evaluate - evaluate a function pointer

mixed evaluate(mixed f, ...);

If f is a function, f is called with the rest of the arguments.
Otherwise, f is returned.  evaluate(f, ...) is the same as (*f)(...).

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

function_owner - return the owner of a given function.

object function_owner(function);

function_owner returns the object that owns the function specified by
the argument.

This function requires PACKAGE_CONTRIB to be defined in the options file.

See also:
 bind

back to top

copy - recursively duplicate a value

mixed copy(mixed);

copy() returns a value with exactly the same value as its argument, but with
all reference types (mappings, arrays, etc) duplicated.  For example:

mapping a, b = ({ 1 });
a = b;
a[0] = 2;
printf("%O %O\n", a, b);

results in ({ 2 }) and ({ 2 }), while:

mapping a, b = ({ 1 });
a = copy(b);
a[0] = 2;
printf("%O %O\n", a, b);

results in ({ 2 }) and ({ 1 }).

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

fetch_variable - set the value of a variable

mixed fetch_variable(string);

Return the value of the variable specified by the argument.
Note that the variable must be defined, and must be defined in this_object().

This function requires PACKAGE_CONTRIB to be defined in the options file.

See also:
 restore_variable,
 store_variable,
 restore_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

filter - select certain elements

mixed filter(mixed x, string fun, object ob, mixed extra, ...);

mixed filter(mixed x, function f, mixed extra, ...);

The (ob, fun) syntax works as if (: call_other, ob, fun :) had been passed as
f.  Filter returns a new structure containing only the elements of x for which
the function returns nonzero.  Currently, it can be used on arrays and
mappings.  In the case of mappings, both the key and the value are passed
to the function.  extra and all the following arguments are passed to the
function after the element.  For example, filter(arr, fun, 2, 3) will
first call fun(arr[0], 2, 3) then fun(arr[1], 2, 3) etc.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

map - modify an mapping

mixed map( mixed x, string fun, object ob, mixed extra, ... );

mixed map( mixed x, function f, mixed extra, ... );

The (ob, fun) syntax works as if (: call_other, ob, fun :) had been passed as
f.  Map returns a new structure containing the return values of f being applied
to each element of x.  Currently, it can be used on arrays, mappings and
strings.  In the case of mappings, both the key and the value are passed
to the function.  In the case of strings, the characters are passed to the
function one at a time as ints.  extra and all the following arguments are
passed to the function after the element.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

restore_variable - restore value of a variable from a string 

mixed restore_variable( string value );

Restores an LPC value from a string.  The format used is the
same format as save/restore_object.

See also:
 save_variable,
 restore_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

save_variable - save the value of variable into a string

string save_variable( mixed var );

Saves an LPC value into a string.  The format is the same as
save/restore_object.

See also:
 restore_variable,
 restore_object

back to top

sizeof - return the number of elements in an array

int sizeof( mixed var );

Return the number of elements in an array, mapping, string, class or
buffer 'var'.  If `var' is not an array, mapping, string, class or 
buffer, then zero (0) is returned.

See also:
 strlen

back to top

store_variable - set the value of a variable

void store_variable(string, mixed);

Set the value of the variable specified by the first argument to the value
specfied by the second argument. Note that the variable must be defined, and
must be defined in this_object().

This function requires PACKAGE_CONTRIB to be defined in the options file.

See also:
 restore_variable,
 fetch_variable,
 save_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

typeof - return the type of an expression

int typeof( mixed var );

Return the type of an expression.  The return values are given in
the driver include "type.h".  They are:

INT             "int"
STRING      "string"
ARRAY       "array"
OBJECT      "object"
MAPPING         "mapping"
FUNCTION        "function"
FLOAT           "float"
BUFFER          "buffer"
CLASS        "class"

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

add_action - bind a command verb to a local function

void add_action( string | function fun, string | string array cmd );

void add_action( string | function fun, string | string array cmd, int flag );

This efun is only available if NO_ADD_ACTION isn't defined.

Set up a function 'fun' to be called the a user types the command 'cmd'.
(What is the command is determined by the first 'word' which consists
of all the characters before the first space, with the exception of
verbs that don't need a space; see below).

If 'cmd' is an array, then that function will be called for any of the
commands in the array.  'fun' can either be a string which is the name
of a function in the object adding the command, or a function pointer.

Functions called by a user command will get the rest of the command line
as a string. It must then return 0 if it was the wrong command, otherwise 1.
If 1 is returned, no further parsing is done; if 0 is returned, other
commands will be checked (possibly the same command added by a different
object).  If no command is found, the default error message will be sent
to the player (traditionally, 'What?' but see also notify_fail())

For functions which can be called by more than one command, check query_verb()
to see which command was used.

Note: add_action() does not add commands globally; it only adds commands to
this_user(), and the object must be 'close' to the user it is adding commands
to.

Usually add_action() is called only from an init() routine. The object that
defines commands must be 'close' to the user, either being the user,
being carried by the user, being the room around the user, or being an
object in the same room as the user.

Since init() is called when a user moves 'close' to an object, it is a
convenient time to add such commands.  The commands are removed when the
user moves out of range (or the object does).

If argument 'flag' is 1, then only the leading characters of the command has
to match the verb 'cmd' and the entire verb is returned by query_verb().  If 
argument 'flag' is 2, then again, only the leading characters must match,
but query_verb() will only return the characters following 'cmd'.

See also:
 query_verb,
 remove_action,
 init

back to top

command - execute a command as if given by the object

int command( string str );

This efun is only available if NO_ADD_ACTION isn't defined.

Execute 'str' for the object this_object() as a command (matching against
add_actions and such).  The object must have called enable_commands() for
this to have any effect.
In case of failure, 0 is returned, otherwise a numeric value is returned,
which is the LPC "evaluation cost" of the command.  Bigger numbers mean
higher cost, but the whole scale is subjective and unreliable.

See also:
 add_action,
 enable_commands

back to top

commands - returns some information about actions the user can take

array commands();

This efun is only available if NO_ADD_ACTION is not defined.

Returns an array of an array of 4 items describing the actions that
are available to this_object().  The first item is the command
itself (as passed to add_action()).  The second is the set of
flags (passed to add_action as the third argument, often defaulted
to 0).  The third is the object that defined the action.  The fourth
is the function to be called ("<function>" if it is a function pointer).

See also:
 add_action,
 enable_commands,
 disable_commands

back to top

disable_commands - makes a living object non-living

void disable_commands();

This efun is only available if NO_ADD_ACTION is not defined.

Causes the current object to no longer be able to execute commands.

See also:
 enable_commands

back to top

disable_wizard - remove wizard priveleges from an object

void disable_wizard();

This efun is only available if NO_WIZARDS is not defined.

The opposite of enable_wizard().  Disables wizard privileges from the
current object.

See also:
 enable_wizard,
 wizardp

back to top

ed - edit a file

This efun is only available if OLD_ED is defined.

void ed( string file, string exit_fn, int restricted );

void ed( string file, string write_fn, string exit_fn, int restricted );

This is a funny function. It will start a local editor on an optional
file.  This editor is almost UNIX ed compatible.  When in the editor
type 'h' for help.

The 'write_fn' function allows the mudlib to handle file locks and
administrative logging of files modified.  When the editor writes to a
file, the driver will callback the 'write_fn' function twice.  The first
time, the function is called before the
write takes place -- 'flag' will be 0.  If the function returns 1,
the write will continue,
otherwise it will abort.  The second time, the function is called
after the write has completed -- 'flag' will be non-zero.
This callback function should have the form:

int write_fn(string fname, int flag)

When the editor is exited, the driver will callback the 'exit_fn'
function.  This function allows the mudlib to clean up.  This 
callback function has the form:

void exit_fn()

The optional 'restricted' flag limits the editor's
capabilities, such as inserting a file, and saving using an alternate
file name.

See also:
 regexp,
 valid_read,
 valid_write,
 get_save_file_name

back to top

ed_cmd - perform an 'ed' command

This efun is only available if OLD_ED is not defined.

string ed_cmd(string cmd);

Performs the ed command 'cmd'.  The result of the command is returned.
Ed must have been started with ed_start() in order to call this efun.

See also:
 ed_start

back to top

ed_start - start up 'ed'

This efun is only available if OLD_ED is not defined.

string ed_start(string file, int flag);

string ed_start(string file);

string ed_start();

If 'flag' is nonzero, ed is started in restricted mode.  See the documentation
for the old efun for information.  'file' is the name of the file to open;
if none is given then no file becomes active.

ed_start() may not be called when another ed session for the current
object is already active.  Any messages generated while starting up ed
are returned by this efun.

See also:
 ed,
 ed_cmd,
 query_ed_mode

back to top

enable_commands - allow object to use 'player' commands

void enable_commands();

This efun is only available if NO_ADD_ACTION is not defined.

enable_commands() marks this_object() as a living object, and allows
it to use commands added with add_action() (by using command()).
When enable_commands() is called, the driver also looks for the
local function catch_tell(), and if found, it will call it every time
a message (via say() for example) is given to the object.

See also:
 living,
 add_action,
 command,
 catch_tell,
 say

back to top

enable_wizard - give wizard priveleges to an object

void enable_wizard();

Available only if NO_WIZARDS isn't defined.

Any interactive object that calls enable_wizard() will cause wizardp()
to return true if called on that object.  enable_wizard() gives three
privileges to the interactive object in question:

* ability to use restricted modes of ed when the RESTRICTED_ED option is compiled into the driver. * privilege of receiving descriptive runtime error messages. * privilege of using the trace() and traceprefix() efuns.
If you don't use this, ed() must be explicitly restricted when necessary, an error_handler should be implemented to give appropriate messages if you don't want all users to get descriptive error traces, and trace() and traceprefix() should be restricted via simul_efuns, if necessary. See also: disable_wizard, wizardp Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

exec - switches a user (interactive) connection from one object to another

int exec( object to, object from );

This efunction allows the interactive link to a given object to be
moved to another object.  That is, after a successful exec(to, from)
call, interactive(to) will return 1 and interactive(from) will return 0.
The player that was controlling 'from' will begin controlling 'to' following
the exec() call.  Note that this is a powerful function and its use must
be restricted if you wish to attempt to have a secure mud.  The proper
way to restrict the use of exec() is to make a simul_efun of the same name
and then use valid_override() to restrict the use of a simul_efun override
(i.e. efun::exec()).  The exec() function returns 1 if the switch is
successful (and 0 otherwise).

See also:
 interactive,
 valid_override

back to top

find_player - find a player by name

object find_player( string str );

This efun is only available when NO_ADD_ACTION is not defined.

Similar to find_living(), but only searches through objects that are
interactive, or were once interactive.

See also:
 find_living,
 livings,
 users,
 set_living_name

back to top

get_char - causes next character of input to be sent to a specified function

varargs void get_char( string | function fun, int flag, ... );

Enable next character of user input to be sent to the function `fun' as
an argument. The input character will not be parsed by the driver.

Note that get_char is non-blocking which means that the object calling
get_char does not pause waiting for input.  Instead the object continues
to execute any statements following the get_char.  The specified function
`fun' will not be called until the user input has been collected.

If "get_char()" is called more than once in the same execution, only the
first call has any effect.

If optional argument `flag' is non-zero, the char given by the player will
not be echoed, and is not seen if snooped (this is useful for collecting
passwords).

The function `fun' will be called with the user input as its first argument
(a string). Any additional arguments supplied to get_char will be passed on to
`fun' as arguments following the user input.

See also:
 call_out,
 input_to

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

in_edit() - determine if a player is in the editor

string in_edit();

string in_edit(object ob);

If the given object is in the editor, the file being edited is
returned, else zero.  If no object is given, this_object() is used.

See also:
 ed,
 in_input

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

in_input() - determines if a player is inputting to an input_to

int in_input();

int in_input(object ob);

Returns 1 if the object is currently inputting to an input_to or get_char.
If no object is specified, this_object() is assumed.

See also:
 get_char,
 input_to

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

input_to - causes next line of input to be sent to a specified function

varargs void input_to( string | function fun, int flag, ... );

Enable next line of user input to be sent to the local function 'fun' as
an argument. The input line will not be parsed by the driver.

Note that input_to is non-blocking which means that the object calling
input_to does not pause waiting for input.  Instead the object continues
to execute any statements following the input_to.  The specified function
'fun' will not be called until the user input has been collected.

If "input_to()" is called more than once in the same execution, only the
first call has any effect.

If optional argument 'flag' has the 1 bit set, the line given by the player
will not be echoed, and is not seen if snooped (this is useful for collecting
passwords).

If 'flag' has the 2 bit set, the input_to cannot be bypassed by beginning the
command with '!'.  Otherwise, lines which start with '!' drop through to
the normal input handler.

The function 'fun' will be called with the user input as its first argument
(a string). Any additional arguments supplied to input_to will be passed on to
'fun' as arguments following the user input.

See also:
 call_other,
 call_out,
 get_char

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

interactive - detects whether or not a given object is an interactive

int interactive( object ob );

Return non-zero if 'ob' is an interactive player. 0 will be returned
if he is link dead.

See also:
 query_ip_number,
 query_ip_name,
 enable_commands

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

message - deliver messages to "living" objects

void message( mixed class, mixed message, mixed target, mixed exclude );

message() calls receive_message(mixed class, mixed message) in all objects
in the target list excluding those in the exclude list. This basically
tells the object the message.

Class is the type of message (used for clients and such). An example
would be 'combat', 'shout', 'emergency' etc.  Any LPC value can be
passed, though.

Message is usually a string containing the text to send, though it
can also be any value.

Target is a list of objects to be sent the message. This can be either a 
single object string or object pointer, or may be an array of either.
If a target is non-living all objects in its environment will receive
the message.

Exclude is a list of objects that should not receive the message. This
can either be one object or an array of objects.

See also:
 receive_message,
 say,
 write,
 shout,
 tell_object,
 tell_room

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

notify_fail - set the default error message to a specified string

int notify_fail( string | function str );

This efun is only available if NO_ADD_ACTION is not compiled in.

Store `str' as the error message to be returned instead of the default message
`What?'.  The message will be displayed if a 0 is returned from all actions
setup via add_action().  This is the preferred way to display error messages
since it allows other objects a chance to respond to the same verb (command).
Do not use write() to display the error message since this will require you
to return a 1 (unless you want to see the result of the write() in addition to
the 'What?' message).  However, if you do return a 1, then no other objects
will get a chance to respond to the user command.

Note: Getting this right in the presence of multiple failures is tricky,
to say the least.  One can use a function pointer instead, and have the
routine resolve the collisions.

If a function is passed instead of a string, the function is called
instead of printing a message.  If the function returns a string, that
string is used as the failure message.  Also, this_player() is set
correctly, so write() can be used.

If "notify_fail()" is called more than once, only the last call will have
an effect.

The idea behind this function is to allow better error messages than
`What?'.

As a side note, notify_fail() always returns zero, so return notify_fail(...)
works as expected.

 add_action

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

printf - formatted output conversion

void printf( string format, ... );

The output is sent to this_user(), in the same manner as the write() efun.
Implemented by Lynscar (Sean A Reith).

This version supports the following as modifiers:
* " " - pad positive integers with a space. * "+" - pad positive integers with a plus sign. * "-" - left adjusted within field size. Note: std (s)printf() defaults to right justification, which is unnatural in the context of a mainly string based language but has been retained for "compatability". * "|" - centered within field size. * "=" - column mode if strings are greater than field size. This is only meaningful with strings, all other types ignore this. Columns are auto-magically word wrapped. * "#" - table mode, print a list of '\\n' separated 'words' in a table within the field size. only meaningful with strings. * a number - specifies the field size, a '*' specifies to use the corresponding arg as the field size. If n is prepended with a zero, then is padded zeros, else it is padded with spaces (or specified pad string). * "." followed by a number - precision of n, simple strings truncate after this (if precision is greater than field size, then field size = precision), tables use precision to specify the number of columns (if precision not specified then tables calculate a best fit), all other types ignore this. * ":" followed by a number - n specifies the fs _and_ the precision, if n is prepended by a zero then it is padded with zeros instead of spaces. * "@" - the argument is an array. the corresponding format_info (minus the "@") is applyed to each element of the array. * "'X'" - The char(s) between the single-quotes are used to pad to field size (defaults to space) (if both a zero (in front of field size) and a pad string are specified, the one specified second overrules). NOTE: to include "'" in the pad string, you must use "\'" (as the backslash has to be escaped past the interpreter), similarly, to include "\" requires "\\\\".
The following are the possible type specifiers.
* % - in which case no arguments are interpreted, and a "%" is inserted, and all modifiers are ignored. * O - the argument is an LPC datatype. The format is suitable for printing any type (useful for debugging) * s - the argument is a string. * d or i - the integer arg is printed in decimal. * c - the integer arg is to be printed as a character. * o - the integer arg is printed in octal. * x - the integer arg is printed in hex. * X - the integer arg is printed in hex (with A-F in capitals). * f - floating point number
See also: sscanf, sprintf Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_ed_mode - return which mode ed is in

This efun is only available if OLD_ED is not defined.

int query_ed_mode();

Return value should be interpreted as follows:

0 = normal ed prompt

-1 = not in ed

-2 = more prompt for help

positive number = prompt for input for line n

See also:
 ed,
 ed_start

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_host_name - return the host name

string query_host_name();

query_host_name() returns the name of the host.

See also:
 resolve,
 socket_address,
 query_ip_name,
 query_ip_number

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_idle - determine how many seconds an interactive player has been idle

int query_idle( object ob );

Query how many seconds a player object (ob) has been idling.

See also:
 in_edit,
 in_input

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_ip_name - return the ip name of a given player object.

string query_ip_name( object ob );

Return the IP address for player `ob'.  An asynchronous process `addr_server'
is used to find out these name in parallel.  If there are any failures to
find the ip-name, then the ip-number is returned instead.

See also:
 query_ip_number,
 query_host_name,
 resolve,
 socket_address

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_ip_number - return the ip number for a player object

string query_ip_number( object ob );

Return the ip-number (dotted decimal form) for player `ob'.

See also:
 query_ip_name,
 query_host_name,
 resolve,
 socket_address

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_ip_port - return the ip port of a given player object.

int query_ip_port(object | void);

Returns the local port that the argument object used to connect to
the mud.  If the argument is void, return the local port that
this_player() used to connect to the mud.  Calling this on 
non-interactive objects will return 0.

This function requires PACKAGE_CONTRIB to be defined in the options file.

See also:
 query_ip_name,
 query_host_name,
 resolve,
 socket_address

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_notify_fail - Query if an interactive object has a pending notify_fail()

mixed query_notify_fail(void);

This function returns whatever this_player()'s notify_fail value
has been set to. This is either a string, or a function, depending
on what it has been set to by the most recent call to notify_fail()
that applied to this_player().

This function requires PACKAGE_CONTRIB to be defined in the options file.
This function also requires that the NO_ADD_ACTION option NOT be defined.

See also:
 add_action,
 notify_fail

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_snoop - return the snooper of an interactive object

object query_snoop( object ob );

If `ob' (an interactive object) is being snooped by another interactive object,
the snooping object is returned.  Otherwise, 0 is returned.

See also:
 snoop,
 query_snooping

back to top

query_snooping - return the object than an object is snooping

object query_snooping( object ob );

If `ob' (an interactive object) is snooping another interactive object, the
snooped object is returned.  Otherwise, 0 is returned.

See also:
 snoop,
 query_snoop

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

receive - displays a message to the current object

int receive( string message );

This efun is an interface to the add_message() function in the driver.
Its purpose is to display a message to the current object.  It returns 1
if the current object is interactive, 0 otherwise.  Often, receive() is
called from within catch_tell() or receive_message().

See also:
 catch_tell,
 receive_message,
 message

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

remove_action - unbind a command verb from a local function

int remove_action( string fun, string cmd );

This efun is only available if NO_ADD_ACTION is not compiled in.

remove_action() unbinds a verb cmd from an object function fun. Basically,
remove_action() is the complement to add_action(). When a
verb is no longer required, it can be unbound with remove_action().

remove_action() returns 1 on success and 0 on failure.

See also:
 add_action,
 query_verb,
 init

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

remove_interactive - disconnect an interactive object.

int remove_interactive(object);

If the argument object is interactive, and not destructed, cause it to
be disconnected. (i.e lose it's interactive status).  Returns 1 if 
the operation succeeded, or 0 if it didn't ( object destructed, or not
interactive)

This function requires PACKAGE_CONTRIB to be defined in the options file.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

resolve - resolve an internet address to domain name

int resolve( string address, string callback_func );

resolve() resolves `address', which should be an internet address in the form
"127.0.0.1" or a domain name, into its domain name, or internet address.
When the resolve is complete, `callback_func' will be called in the
current object.  The form of the callback is:

void callback(string address, string resolved, int key);

`key' will match up with the number that the call to resolve() returned.
`address' will be the domain name of the host, and `resolved' the dotted
decimal ip address.  The unknown value will be 0 if the lookup failed.

See also:
 query_host_name,
 socket_address,
 query_ip_name,
 query_ip_number

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

say - send a message to all users in the same environment

varargs void say( string str, object | object array );

Sends a message to the environment of the originator, all items in the
same environment, and all items inside of the originator.  The originator
is this_player(), unless this_player() == 0, in which case, the originator
is this_object().

The second argument is optional.  If second argument `obj' is specified,
the message is sent to all except `obj'.  If `obj' is not an object, but
an array of objects, all those objects are excluded from receiving the
message.

See also:
 message,
 write,
 shout,
 tell_object,
 tell_room

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_this_player - change the value of the current command giver.

void set_this_player(object);

This function changes the value of what this_player() returns during the
current execution. If the argument is an object, this_player() will return
the argument object. If it is an int, this_player() will return 0.

This function requires the NO_ADD_ACTION option be defined in the
options file.

See also:
 this_player

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

shout - sends a message to all living objects

void shout( string str );

Sends the string `str' to all living objects except this_player().

See also:
 message,
 write,
 tell_object,
 tell_room,
 say

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

snoop - snoop an interactive user

varargs object snoop( object snooper, object snoopee );

When both arguments are used, begins snooping of `snoopee' by
`snooper'.  If the second argument is omitted, turns off all snooping
by `snoopee'.  Security for snoop() is normally controlled by a
simul_efun.  snoop() returns `snoopee' if successful in the
two-argument case, and `snooper' if it was successful in the
single-argument case.  A return of 0 indicates failure.
The 'snoopee' must be an interactive object; the snooper can be any
object.  However, snooping with a non-interactive object is useless
unless the RECEIVE_SNOOP option is enabled, and the object defines
a RECEIVE_SNOOP function.

See also:
 query_snoop,
 query_snooping

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

this_interactive - return the object representing the current player

object this_interactive();

Return the object representing the player that caused the calling function
to be called.  This returns what this_player() was originally even if
it changed later due to enable_commands() or command()

See also:
 this_player

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

this_player - return the object representing the current player

object this_player( int flag );

this_player() is exactly the same as this_user().

See also:
 this_user

back to top

this_user - return the object representing the current interactive

Return the object representing the user that caused the calling function
to be called.  Note that this_user() may return a different value than
this_object() even when called from within a user object.  If this_user
is called as this_user(1) then the returned value will be the interactive
that caused the calling function to be called.  this_user(1) may return
a different value than this_user() in certain cases (such as when command()
is used by an admin to force a user to perform some command).

See also:
 this_object

back to top

userp - determine if a given object was once interactive

int userp( object );

Returns 1 if the arg was once interactive.

See also:
 interactive,
 users,
 living

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

users - return an array of objects containing all interactive players

object array users();

Return an array of objects, containing all interactive players.

See also:
 livings,
 children,
 objects

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

wizardp - determines if a given object had enable_wizard() performed in it

int wizardp( object );

This efun is only available if NO_WIZARDS is not compiled in.

Returns 1 if the arg had enable_wizard() performed on it.

See also:
 disable_wizard,
 enable_wizard

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

write() - send a message to current player

void write( mixed str );

Write a message `str' to current player. `str' can also be a number, which
will be translated to a string.

See also:
 message,
 tell_object,
 tell_room,
 shout,
 say

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

cache_stats - report various driver and mudlib statistics

string cache_stats();

This efun is only available if CACHE_STATS is defined in options.h at
driver build time.  This efun returns a string containing a summary
of the statstics on the call_other() cache hit rate.

See also:
 opcprof,
 mud_status

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

debug_info - display debug information

string debug_info( int operation, ... );

string debug_info( 0, object ob );

string debug_info( 1, object ob );

string debug_info( 2, object ob );

This efun is only available if PACKAGE_DEVELOP is compiled into the driver.

debug_info() is a general-purpose facility which may be used to debug the
MudOS driver.  The debugging information requested is determined by the
first argument.  Successive arguments are determine by the operation selected.

The existing operations (0 , 1 and 2) require a second object type argument,
and may be used to display the various fields of the MudOS object structure.

The following LPC code was used to generate the sample output:


create() {
    write(debug_info(0, this_object()));
}

gives:

O_HEART_BEAT      : FALSE
O_IS_WIZARD       : FALSE
O_ENABLE_COMMANDS : FALSE
O_CLONE           : FALSE
O_DESTRUCTED      : FALSE
O_SWAPPED         : FALSE
O_ONCE_INTERACTIVE: FALSE
O_RESET_STATE     : FALSE
O_WILL_CLEAN_UP   : FALSE
O_WILL_RESET: TRUE
total light : 0
next_reset  : 720300560
time_of_ref : 720299416
ref         : 2
swap_num    : -1
name        : 'u/c/cynosure/di0'
next_all    : OBJ(bin/dev/_update)
This object is the head of the object list.


create() {
    write(debug_info(1, this_object()));
}

gives:

program ref's 1
Name u/c/cynosure/di1.c
program size 10
num func's 1 (16) 
num strings 0
num vars 0 (0)
num inherits 0 (0)
total size 104


create() {
    write(debug_info(2, this_object()));
}

gives:

x: "foo"

See also:
dump_file_descriptors,
dump_socket_status

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

debugmalloc - dumps information on malloc'd memory to a file

void debugmalloc(string filename, int mask);

This efun is only available when PACKAGE_DEVELOP, DEBUGMALLOC and DEBUGMALLOC_EXTENSIONS are
both defined in options.h at driver build time.  The debugmalloc() efun
will dump information on those chunks of memory allocated by DMALLOC() and
related macros if the bitwise and (&) with the tag supplied by the macro
(i.e. (mask & tag)) is non-zero.  Read md.c and config.h in the
driver source for more information.

See also:
 set_malloc_mask

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

dump_file_descriptors - dump the MudOS process file descriptor table

string dump_file_descriptors();

This function is provided to assist in debugging the MudOS driver and
helps overcome deficiencies in some UN*X implementations which do not
provide equivalent or superior debugging facilities as part of the
operating system itself.  The interpretation of the output is very
system-dependent.  Each file descriptor is checked to determine whether
it refers to an open file.  If so, information is displayed from the
"stat structure" returned by the fstat() system call.

The following output was produced on Lambda Realms running on a Sequent
DYNIX/ptx system:

Fd  Device Number  Inode   Mode    Uid    Gid      Size
--  -------------  -----  ------  -----  -----  ----------
 0     3      2    10319  c  666      0      3           0
 1    79      7   164598  f  644   2862      1      789522
 2    79      7   164598  f  644   2862      1      789522
 3    40    33b     6925  c    0   2862      1           0
 4    40    2a4     6943  c    0   2862      1           0
 5    79      7   164599  f  600   2862      1       44784
 6    40    2e2   145996  c    0   2862      1           0
 7    79      7   164601  f  644   2862      1         506

See also:
dump_socket_status

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

dump_prog - dump/disassemble an LPC object

void dump_prog( object ob, int flags, string file );

This efun is only available when PACKAGE_DEVELOP is compiled into the driver.

dump_prog() dumps information about the program of `obj' to a file,
`file', or "/PROG_DUMP" if `file' is not given.  If the current object
does not have write access to the file, it fails.  

Flags can be a combination of the following values:
* 1 - include a disassembly of the i-code * 2 - include line number information
See also: debug_info, dumpallobj Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

dump_socket_status - display the status of each LPC socket

string dump_socket_status();

This efun is only available when PACKAGE_SOCKETS is compiled into the driver.

dump_socket_status() is a diagnostic facility which displays the current
status of all LPC sockets configured into the MudOS driver.  It is useful
for debugging LPC sockets applications.  Each row in the output corresponds
to a single LPC socket.  The first row corresponds to LPC socket descriptor 0,
the second row, 1, etc.  The total number of sockets is configured when the
driver is built.

The first column "Fd" is the operating system file descriptor associated
with the LPC socket.  "State" is the current operational state of the LPC
socket.  "Mode" is the socket mode, which is passed as an argument to
socket_create().  The local and remote addresses are the Internet address
and port numbers in Internet dot notations.  '*' indicates an address or
which is 0.  N.B. LPC sockets that are in the CLOSED state are not
currently in use; therefore the data displayed for that socket may be
idiosyncratic.

The following output was generated on Portals, where the only socket
application running at the time was MWHOD.  It indicates that two
sockets are current in use, one is listening for connection requests
on a STREAM mode socket.  The other is waiting for incoming data on
a DATAGRAM mode socket.

Fd    State      Mode      Local Address      Remote Address
--  ---------  --------  -----------------  ------------------
13   LISTEN     STREAM   *.6889             *.*
14    BOUND    DATAGRAM  *.6888             *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*
-1    CLOSED      MUD    *.*                *.*

See also:
debug_info,
dump_file_descriptors

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

dumpallobj - report various statistics on all objects that have been loaded

void dumpallobj();

void dumpallobj( string );

This function dumps a list of statistics on all objects that have been loaded.
If no argument is specified, then the information will be dumped to a file
named /OBJ_DUMP.  If an argument is specified, then that name is used as
the filename for the dump.

See also:
 mud_status,
 debug_info

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

get_config - query various driver config settings

mixed get_config( int );

This efun is used to query the driver's various config
settings.  Please refer to the "runtime_config.h"
include file for a list of currently recognized options.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

malloc_status - report various statistics related to memory usage.

string malloc_status();

This function returns memory usage statistics in a string.
This function replaces the hardcoded 'malloc' command in vanilla 3.1.2.
Note that the output produced by malloc_status() depends upon which
memory management package is chosen in options.h when building the driver.

See also:
 mud_status,
 dumpallobj,
 memory_info

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

memory_info - obtain info on object/overall memory usage

varargs int memory_info( object ob );

If optional argument `ob' is given, memory_info() returns the approximate
amount of memory that `ob' is using.  If no argument is given, memory_info()
returns the approximate amount of memory that the entire mud is using.  Note
that the amount of memory the mud is using does not necessarily correspond
to the amount of memory actually allocated by the mud from the system, and
that total memory used by all the objects is not additive due to sharing of
certain structures.

See also:
 debug_info,
 malloc_status,
 mud_status

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

mud_status - report various driver and mudlib statistics

string mud_status( int extra );

This function returns a string containing driver and mudlib statistics.
If extra is non-zero, then additional information about various internal
tables is included as well.  This efun replaces the hardcoded 'status'
and 'status tables' commands in vanilla 3.1.2.

See also:
 debug_info,
 dumpallobj,
 memory_info,
 uptime

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

opcprof - reports statistics on calling frequencies of various efuns

void opcprof();

void opcprof( string );

This function dumps a list of statistics on each efunction and eoperator.
If no argument is specified, then the information will be dumped to files
named /OPCPROF.efun and /OPCPROF.eoper.  If an argument is specified, then
that name is used as the filename for the dump.

See also:
 function_profile

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_load_average - forces an error to occur in an object

string query_load_average();

This function returns a string which reports two things: 1) user commands
per second, and 2) compiled lines per second.

See also:
 rusage

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

refs - return the number of references to a data structure

int refs( mixed data );

This efun is only available if PACKAGE_DEVELOP is compiled in.

The number of references to `data' will be returned by refs().  This is 
useful for deciding whether or not to make a copy of a data structure
before returning it.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

rusage - reports information gathered by the getrusage() system call

mapping rusage();

This efun collects information gathered via the getrusage() system
call.  Read the getrusage() man page for more information on what information
will be collected.  Some systems do not have the getrusage() system call
but do have the times() system call.  On those systems, only "utime"
and "stime" will be available.  Times are reported in milliseconds.

Here is an example usage of rusage():

  void
  create()
  {
      mapping info;

      info = rusage();
      write("user time = " + info["utime"] + "ms\\n");
      write("system time = " + info["stime"] + "ms\\n");
  }

The available fields are:
utime, stime, maxrss, ixrss, idrss, isrss, minflt, majflt, nswap, inblock,
oublock, msgsnd, msgrcv, nsignals, nvcsw, nivcsw.

See also:
time_expression,
function_profile,
time,
uptime

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_debug_level - sets the debug level used by the driver's debug() macro

void set_debug_level( int level );

This efun is only available when the driver is compiled with -DDEBUG_MACRO.
The purpose of this efun is to allow the amount and type of debugging
information produced to be controlled from within the mud (while the
driver is running).

For more information, read the file debug.h which is included with the
driver source.

See also:
 set_malloc_mask

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_malloc_mask - sets the mask controlling display of malloc debug info

void set_malloc_mask( int mask );

This efun is only available when PACKAGE_DEVELOP, DEBUGMALLOC and DEBUGMALLOC_EXTENSIONS are
both defined in options.h at driver build time.  The mask controls what
memory-related debugging information is displayed as the driver allocates
and deallocates memory.  Read md.c in the driver source for more information.

See also:
 debugmalloc

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

swap - swap out a file explicitly

void swap( object );

This efun is only available if the driver is compiled with -DDEBUG.

This efun should be reserved for debugging only.  It
allows an object to be explicitly swapped out.  If
enabled, it is strongly recommended that a simul_efun
override (for this efun) be used to prevent abuse.

Note: objects which have been destructed, already
swapped out, contain a heart beat, cloned, inherited,
or interactive, cannot be swapped out.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

time_expression - return the amount of real time that an expression took

int time_expression( mixed expr );

int time_expression { ... } 

Evaluate  or the specified block of code.  The amount of real time
that passes during the evaluation of , in microseconds, is returned.
The precision of the value is
not necessarily 1 microsecond; in fact, it probably is much less precise.

See also:
 rusage,
 function_profile,
 time

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

trace - sets trace flags and returns the old ones

int trace( int traceflags );

This efun is only available if TRACE and PACKAGE_DEVELOP are compiled in.

Sets the trace flags and returns the old trace flags.
When tracing is on a lot of information is printed during execution.

The trace bits are:
* 1 - Trace all function calls to lfuns. * 2 - Trace all calls to "call_other". * 4 - Trace all function returns. * 8 - Print arguments at function calls and return values. * 16 - Print all executed stack machine instructions (produces a lot of output!). * 32 - Enable trace in heart beat functions. * 64 - Trace calls to apply. * 128 - Show object name in tracing.
See also: traceprefix Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

traceprefix - sets the prefix determining which objects to trace

string traceprefix( string prefix );

This efun is only available if TRACE and PACKAGE_DEVELOP are compiled in.

If the the traceprefix is set (i.e. not 0) tracing will only occur in objects
having a name with the set prefix.

The old value is returned.

See also:
 trace

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

allocate_mapping - pre-allocate space for a mapping

mapping allocate_mapping( int size );

Returns a mapping with space for 'size' elements preallocated.

For example:

mapping x;
int y = 200;

x = allocate_mapping(y);

where y is the initial size of the mapping. Using allocate_mapping is
the preferred way to initalize the mapping if you have some idea of how
many elements the map will contain (200 in this case). The reason is that
allocating storage all at once is slightly more efficient. Thus if
you are using mappings to store a soul with 200 entries, the above
initialization would be quite appropriate. Note, that the
above initialization does not restrict you to 200 entries.

See also:
map_delete

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

filter_mapping - return a selective sub-mapping

mapping filter_mapping(mapping map, string fun, object ob, mixed extra, ...);

mapping filter_array(mapping map, function f, mixed extra, ...);

filter_mapping() is really the same as the filter() efun.

See also:
 filter

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

keys - return an array of the keys from the (key, value) pairs in a mapping

array keys( mapping m );

keys() returns an array of keys (indices) corresponding to the keys in
the (key, value) pairs stored in the mapping m.

For example, if:

mapping m;
m = (["hp" : 35, "sp" : 42, "mass" : 100]);

then

keys(m) == ({"hp", "sp", "mass"})

Note: the keys will not be returned in any apparent order. However, they
will be returned in the same order as the corresponding values (returned
by the values() efun).

See also:
values

back to top

m_delete - remove a key from a mapping

mapping m_delete(mapping m, mixed element);

This efun is only available if COMPAT_32 is defined.

It behaves exactly like map_delete(), except that it returns its first
argument.  

Note: the 3.2 version actually returns a copy of the mapping,
so for strict compatibility the following simul is suggested:

mapping m_delete(mapping m, mixed element) 
{
    mapping ret = copy(m);
    map_delete(ret, element);
    return ret;
}

However, this version is significantly faster as it avoids the copy.

See also:
map_delete

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

m_indices - return the keys of a mapping

array m_indices(mapping);

This efun is only available if COMPAT_32 is defined.  It behaves exactly
the same as keys().

See also:
 keys

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

m_values - return the values of a mapping

array m_values(mapping);

This efun is only available if COMPAT_32 is defined.  It behaves exactly
the same as values().

See also:
 values

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

map_delete - remove a (key, value) pair from a mapping based on the key

void map_delete( mapping m, mixed element );

map_delete removes the (key, value) from the mapping m that has key equal
to element.

For example, given:

mapping names;

names = ([]);
names["truilkan"] = "john";
names["wayfarer"] = "erik";
names["jacques"] = "dwayne";

Then:

map_delete(names,"truilkan");

causes the mapping 'names' to be equal to:

(["wayfarer" : "erik", "jacques" : "dwayne"])

keys(names) will not contain "truilkan" after map_delete(names,"truilkan")
is called [unless ("truilkan", *) is subsequently added back to the mapping].

See also:
allocate_mapping

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

map_mapping - modify an mapping of elements via application of a function

mapping map_mapping( mapping map, string fun, object ob, ... );

mapping map_mapping( mapping map, function f, ... );

Returns an mapping with the same keys as map whose items have been
mapped throught 'ob->fun()' or 'f'.  The function is called for each
(key, value) pair in 'map' and the returned mapping has the return value
of the function as its value for each key.
The extra arguments are passed as parameters to the function
after the key and the value.

See also:
 filter_array,
 filter,
 sort_array,
 map_array,
 map

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

match_path - search a mapping for a path

mixed match_path( mapping m, string str );

match_path() searches a mapping for a path.  Each key is assumed to be a 
string.  The value is completely arbitrary.  The efun finds the largest 
matching path in the mapping.  Keys ended in '/' are assumed to match paths 
with character that follow the '/', i.e. / is a wildcard for anything below 
this directory.  

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

unique_mapping - partition an array into groups

mapping unique_mapping(array arr, string fun, object ob, ...);

mapping unique_mapping(array arr, function f, ...);

unique_mapping() evaluates the function 'f' with each element of the
array 'arr', and constructs a mapping with the return values as keys,
and subarrays of elements that returned value value as values.

See also:
 unique_array

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

values - return an array of the values from the (key, value) pairs in a mapping

array values( mapping m );

values() returns an array of values corresponding to the value elements
in the (key, value) pairs stored in the mapping m.

For example, if:

mapping m;

m = (["hp" : 35, "sp" : 42, "mass" : 100]);

then

values(m) == ({35, 42, 100})

Note: the values will be returned in the same order as the corresponding
keys.

See also:
keys

back to top

arrayp - determine whether or not a given variable is an array

int arrayp( mixed arg );

Return 1 if `arg' is an array, zero otherwise.

See also:
 typeof

back to top

bufferp - determine whether or not a given variable is a buffer

int bufferp( mixed arg );

Return 1 if `arg' is a buffer value and zero otherwise.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

classp - determine whether or not a given variable is a class

int classp(mixed);

Return 1 if the argument is a class.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

floatp - determine whether or not a given variable is a float

int floatp( mixed arg );

Return 1 if `arg' is a float number and zero (0) otherwise.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

functionp - determine whether or not a given variable is a function
pointer

int functionp( mixed arg );

Return nonzero if `arg' is a function pointer and zero (0) otherwise.
Function pointers are variables of type 'function' as indicated in the
documentation for the type 'function', for example:

f = (: call_other, obj, func :);

The return value indicates the type of function pointer using the
values given in the driver include file "include/function.h".

* FP_LOCAL - lfun pointer * FP_EFUN - efun pointer * FP_SIMUL - simul pointer * FP_FUNCTIONAL - functional
These values are bit values; the following flags may be added as well:
* FP_HAS_ARGUMENTS - arguments were included in the definition * FP_OWNER_DESTED - the owner of this function pointer has been destructed * FP_NOT_BINDABLE - it isn't possible to rebind this function pointer
To test if a function variable is an efun pointer: if (functionp(f) & FP_EFUN) ... to test if it is an efun or simul_efun: if (functionp(f) & (FP_EFUN | FP_SIMUL)) ... Try (very hard) to call the function:
if (functionp(f) & FP_OWNER_DESTED) {
   if (functionp(f) & FP_NOT_BINDABLE)
       error("Function could not be rebound.\n");
   f = bind(f, this_object());
}
evaluate(f);

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

intp - determine whether or not a given variable is an integer

int intp( mixed arg );

Return 1 if 'arg' is an integer number and zero (0) otherwise.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

mapp - determine whether or not a given variable is a mapping

int mapp( mixed arg );

Return 1 if `arg' is a mapping.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

nullp - determine whether or not a given variable is null

int nullp( mixed arg );

Exactly the same as undefinedp().  Exists for compatibility.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

objectp - determine whether or not a given variable is an object

int objectp( mixed arg );

Return 1 if `arg' is an object.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

pointerp - determine whether or not a given variable is an array

int pointerp( mixed arg );

pointerp() is provided for compatibility; it is the same as the arrayp() efun.

See also:
 arrayp

back to top

stringp - determine whether or not a given variable is a string

int stringp( mixed arg );

Returns 1 if 'arg' is a string, and zero if not.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

undefinedp - determine whether or not a given value is undefined.

int undefinedp( mixed arg );

Return 1 if `arg' is undefined.  'arg' will be undefined in the following
cases:

* it is a variable set equal to the return value of a call_other to a non-existent method (e.g. arg = call_other(obj, "???")). * it is a variable set equal to the return value of an access of an element in a mapping that doesn't exist (e.g. arg = map[not_there]). * it has not yet been initialized. * it points to a destructed object. * it is a function (formal) parameter that corresponds to a missing actual argument.
Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

author_stats - returns statistics gathered on authors

mapping author_stats( string domain);

This efun is only avaiable if PACKAGE_MUDLIB_STATS is compiled in.

Both domain_stats() and author_stats() return information stored in a
mapping.  If no argument is specified, then information is returned on
all domains (or on all authors) with one map entry per domain or author.
If an argument is specified, then a map is returned that corresponds to
that domain or author with keys: moves, cost, errors, heart_beats,
array_size, and objects.  Each of these map to integer values.
Moves is the number of objects that have moved into objects in the
given domain.  Cost is the number of evaluations (eval_cost) accumulated
by objects with the given domain (or author).  Errors is the number of errors
incurred by objects with the given domain.  Heart_beats is the number of
heartbeat calls made on objects having the given domain.
Array_size is the size (in bytes) of the arrays allocated by the domain.
Objects is the number of objects created by the given domain.  When called
with no arguments, the returned mapping has a form like this:

([ domain0 : info0, domain1 : info1, ... ])

while info0 has the form:

([ "moves" : moves, "cost" : cost, "errors" : errors,
   "heart_beats" : heart_beats, "worth" : worth,
   "array_size" : array_size, "objects" : objects ])

When called with an argument, the returned mapping will have the form of
info0.

See also:
domain_file,
author_file,
set_author

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

domain_stats - returns statistics gathered on domains

mapping domain_stats( string domain );

This efun is only available if PACKAGE_MUDLIB_STATS is compiled into the driver.

Both domain_stats() and author_stats() return information stored in a
mapping.  If no argument is specified, then information is returned on
all domains (or on all authors) with one map entry per domain or author.
If an argument is specified, then a map is returned that corresponds to
that domain or author with keys: moves, cost, errors, heart_beats,
array_size, and objects.  Each of these map to integer values.
Moves is the number of objects that have moved into objects in the
given domain.  Cost is the number of evaluations (eval_cost) accumulated
by objects with the given domain (or author).  Errors is the number of errors
incurred by objects with the given domain.  Heart_beats is the number of
heartbeat calls made on objects having the given domain.
Array_size is the size (in bytes) of the arrays allocated by the domain.
Objects is the number of objects created by the given domain.  When called
with no arguments, the returned mapping has a form like this:

([ domain0 : info0, domain1 : info1, ... ])

while info0 has the form:

([ "moves" : moves, "cost" : cost, "errors" : errors,
   "heart_beats" : heart_beats, "worth" : worth,
   "array_size" : array_size, "objects" : objects ])

When called with an argument, the returned mapping will have the form of
info0.

See also:
domain_file,
author_file,
set_author

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

export_uid - set the uid of another object

int export_uid( object ob );

This efun is only available if PACKAGE_UIDS is compiled in.

Set the uid of 'ob' to the effective uid of this_object(). It is
only possible when 'ob' has an effective uid of 0.

See also:
 seteuid,
 getuid,
 geteuid,
 valid_seteuid

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

find_living - find a living object matching a given id

object find_living( string str );

This efun is only available if NO_ADD_ACTION is not compiled in.

Find first the object that is marked as living, and answers to the
id 'str'.  A living object is an object that has called
enable_commands().  The object must have set a name with
set_living_name(), so its name will be entered into the hash table
used to speed up the search for living objects.

See also:
 living,
 livings,
 users,
 disable_commands,
 enable_commands,
 set_living_name

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

geteuid - return the effective user id of an object or function

string geteuid( object|function );

This efun is only available if PACKAGE_UIDS is compiled into the driver.

If given an object argument, geteuid returns the effective user id (euid)
of the object.  If given an argument of type 'function', it returns the
euid of the object that created that 'function' variable.  If the object,
at the time of the function variable's construction, had no euid, the
object's uid is stored instead.

See also:
 seteuid,
 getuid,
 export_uid,
 valid_seteuid

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

getuid - return the user id (uid) of an object

string getuid( object ob );

This efun is only available if PACKAGE_UIDS is compiled into the driver.

Returns the user id of an object.  The uid of an object is determined at
object creation by the creator_file() function.

See also:
 seteuid,
 geteuid,
 export_uid,
 valid_seteuid,
 creator_file

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

living - detects whether or not a given object is "living"

int living( object ob );

This efun is only available if NO_ADD_ACTION is not compiled in.

Return true if `ob' is a living object (that is, if "enable_commands()" has
been called by `ob').

See also:
 enable_commands

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

livings - return an array of all living objects

object array livings();

This efun is only available if NO_ADD_ACTION is not compiled in.

Returns an array of pointers to all living objects (objects that have
had enable_commands() called in them).

See also:
 enable_commands,
 find_living,
 users

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_privs - return the privs string for an object

string query_privs( object ob );

Returns the privs string for an object.  The privs string is determined
at compile time via a call to privs_file() in the master object, and changeable
via the set_privs() efun.

This efun is only available if PRIVS is defined at driver compile time.

See also:
 privs_file,
 set_privs

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_author - set the author associated with an object

void set_author( string author );

Every object has both an author and a domain associated with it for
the purposes of tracking statistics for authors and domains.  Domains
may only be set in the master object function domain_file(), however
authors are different.  They can be initialized to some default value
by author_file() in the master object, but can also be changed using
the set_author efun.

set_author changes the author of the object that it is called within.
That author will get credit for all future actions of that object that
affect mudlib statistics.

See also:
 author_file,
 domain_file,
 author_stats,
 set_author,
 domain_stats

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_light - update or query an object's light level

int set_light( int light_level_adjustment );

This efun is only available if NO_LIGHT is not compiled in.

Passing 'light_level_adjustment' as 0 queries the object's current
light level.  A positive number will increase the light level, while
a negative number will decrease the light level.

Note that the object's current light level includes the light it sees from
other objects.

This efun is provided mostly for backwards compatibility; it really should
be handled by the mudlib.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_living_name - set a living name for a living object

void set_living_name( string name );

This efun is only available if NO_ADD_ACTION is not compiled in.

Set a living name on an object that is living. After this has been done, the
object can be found with "find_living()".

See also:
 enable_commands,
 find_living,
 find_player

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_privs - set the privs string for an object

void set_privs( object ob, string privs );

This efun is only available when PRIVS is compiled in.

Sets the privs string for 'ob' to 'privs'.

This efun is only available if PRIVS is defined at driver compile time.

See also:
 privs_file,
 query_privs

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

seteuid - set the effective user id (euid) of an object

int seteuid( string str );

This efun is only available if PACKAGE_UIDS is compiled in.

Set effective uid to 'str'.  valid_seteuid() in master.c controls which
values the euid of an object may be set to.

When this value is 0, then the current object's uid can be changed by
export_uid(), and only then.

But, when the value is 0, no objects can be loaded or cloned by this object.

See also:
 export_uid,
 getuid,
 geteuid,
 valid_seteuid

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

random - return a pseudo-random number

int random( int n );

Return a pseudo-random number from the range [0 .. (n -1)] (inclusive).

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

to_float - convert an int to a float

float to_float( int i );

The to_float() call returns the number of type 'float' that is equivalent to
the int 'i'.

See also:
 to_int,
 read_buffer,
 sprintf,
 sscanf

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

all_inventory - return the inventory of an object

object array all_inventory( object ob );

This efun is only available if NO_ENVIRONMENT is not compiled into the driver.

Returns an array of the objects contained inside of 'ob'.  If 'ob' is
omitted, this_object() is used.

See also:
 deep_inventory,
 environment

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

children - returns an array of objects cloned from a given file 

object array children( string name );

This efun returns an array of objects that have been loaded or cloned from
the file named by 'name' (including the object 'name' itself, if loaded).

See also:
 deep_inherit_list,
 inherit_list,
 objects

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

clone_object - load a copy of an object

object clone_object( string name, ... );

object new( string name, ... );

Create a new object from the file 'name', and give it a new unique
name (by adding #xxx on to the end of the name).  Returns the new object.
The object shares the program of the object 'name', but has its own
set of variables.  The second and following arguments are passed to
create()

See also:
 destruct,
 move_object,
 new

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

clonep - determine whether or not a given variable points to a cloned object

int clonep();

int clonep(mixed arg);

Returns true (1) iff the argument is objectp() and the O_CLONE flag is set.
The driver sets the O_CLONE flag for those objects created via new()
(clone_object()).  The clonep() efun will not return true when called on
objects that are the blueprint copy (those that are loaded via call_other()
or load_object()).

Note that if clonep() returns true, then file_name() will return a string
containing a '#'.  clonep() defaults to this_object().

See also:
 objectp,
 new,
 clone_object,
 call_other,
 file_name

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

deep_inventory - return the nested inventory of an object

object array deep_inventory( object ob );

This efun is only available when NO_ENVIRONMENT is not compiled into the
driver.

Returns an array of the objects contained in the inventory of 'ob' and
also all the objects contained in the inventories of those objects and so on.

See also:
 all_inventory

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

destruct - remove an object

void destruct( object ob );

Completely destroy and remove object 'ob'. After the call to destruct().
If 'ob' is this_object(), execution will continue, but it is best to return
a value immediately.  All pointers to the object in any variable or structure
will immediately become zero.  move_or_destruct() is called in all the
objects inside of the object being destructed.

See also:
 clone_object,
 new,
 move_or_destruct

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

environment - return the environment of an object

object environment( object ob );

This efun is only available if NO_ENVIRONMENT is not compiled in.

Return the containing object (environment) of 'ob'. If no argument
is given, 'ob' defaults to this_object().  If the object is not
inside anything, zero is returned.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

file_name - get the file name of an object

string file_name( object ob );

file_name() returns the name of the file from which 'ob' was loaded.
If the object is a cloned object, then file_name() will not be an
actual file on disk, but will be the name of the file from which the
object was originally cloned, appended with an octothorpe (#) and the
object instance number.  Object instance numbers start at 0 when the
game is booted, and increase by one for each object cloned, hence the
number is unique for each cloned object.  'ob' defaults to this_object()
if not specified.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

find_object - find an object by file name

object find_object( string str );

Find the object with the file name 'str'.  If the object is a
cloned object, then it can be found using the file name which
would by returned if file_name() was called with it as the
argument.

See also:
 file_name

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

first_inventory - return the first item in an object's inventory

object first_inventory( mixed ob );

This efun is only available if NO_ENVIRONMENT is not compiled in.

Return the first object in the inventory of 'ob', where 'ob' is
either an object or the file name of an object.

See also:
 file_name,
 next_inventory,
 all_inventory,
 deep_inventory

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

heart_beat_info - return an array of objects with active heartbeats

object array heart_beat_info();

Returns an array of all the objects with active heart_beats.  This efun
is only available if COMPAT_32 is defined.

See also:
 heart_beats.html

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

heart_beats - return an array of objects with active heartbeats

object array heart_beats();

Returns an array of all the objects with active heart_beats.  This efun
is only available if PACKAGE_CONTRIB is defined.

See also:
 heart_beat,
 set_heart_beat,
 query_heart_beat

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

load_object - find or load an object by file name

object load_object( string str );

Find the object with the file name 'str'.  If the object is already
loaded, it is returned (just like find_object()).  If the file exists
and the object hasn't been loaded yet, it is loaded first, then the
new object is returned.  Otherwise zero is returned.  An error is
thrown only if the object has compile errors.

See also:
 file_name,
 find_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

master - returns the master object

object master();

Returns a pointer to the master object.

See also:
 find_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

move_object - move current object to another environment

void move_object( mixed dest );

Move the current object into the object `dest'.  dest should either be
a filename or an object.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

new

object x = new( string name, ...);
class foo x = new(class foo);

If given a string, it behaves like clone object.  If given a class type,
it creates a new instance of the class type.

See also:
 clone_object,
 destruct,
 move_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

next_inventory - return the next object in the same inventory

object next_inventory( object ob );

This efun is only available if NO_ENVIRONMENT is not compiled in.

Return the next object in the same inventory as 'ob'.

See also:
 first_inventory,
 all_inventory,
 deep_inventory

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

objects - return an array of all loaded objects

object array objects();

object array objects( string func, object ob );

object array objects( function f);

An array of every object loaded on the mud is returned by objects().  Note
that if the system's maximum array size is set too low, objects() will
truncate its array, in which case it might not be too useful.

If the optional `func' and `ob' parameters are given, then ob->func()
is called with each loaded object as an argument.  If the function returns
nonzero, then that object is returned by objects(), otherwise it isn't.

If 'f' is given, it will be called on all the objects as above.  For
example, objects( (: clonep :) ) returns a list of all the clones in
existence.

See also:
 livings,
 users

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

present - find an object by id

object present( mixed str);

object present( mixed str, object ob );

This efun is only available if NO_ENVIRONMENT is not compiled in.

If an object for which id(str) returns true exists, return it.

`str' can also be an object, in 'str' is searched for, instead of calling
the function id().

If `ob' is given, then the search is done in the inventory of `ob', otherwise
the object is searched for in the inventory of the current object, and
in the inventory of the environment of the current object.

See also:
 move_object,
 environment

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_heart_beat() - query the status of an object's heartbeat

int query_heart_beat( object );

Returns the value with which set_heart_beat() has been called with on
'object'.  If object is not given, it defaults to the current object.  If
the object has no heart beat, 0 will be returned.

See also:
 heart_beat,
 set_heart_beat

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

reload_object - return an object to its just-loaded state

void reload_object( object ob );

When reload_object() is called on `ob', all the driver-maintained properties
are re-initialized (heart_beat, call_outs, light, shadows, etc), all 
variables are re-initialized, and create() is called.  It has a similar
effect to destructing/reloading the object, however, no disk access or
parsing is performed.

See also:
 new,
 clone_object,
 destruct

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

restore_object - restore values of variables from a file into an object

int restore_object( string name, int flag );

Restore values of variables for current object from file `name'. If the 
optional second argument is 1, then all of the non-static variables are not 
zeroed out prior to restore (normally, they are).

In the case of an error, the affected variable will be left untouched
and an error given.

See also:
 save_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

save_object - save the values of variables in an object into a file

int save_object( string name, int flag );

Save all values of non-static variables in this object in the file 'name'.
valid_write() in the master object determines whether this is allowed.
If the optional second argument is 1, then variables that are zero (0) are also
saved (normally, they aren't).  Object variables and function pointers
always save as 0.  save_object() returns 1 for success, 0 for failure.

See also:
 restore_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_heart_beat - enable or disable an object's heartbeat

int set_heart_beat( int flag );

Passing 'flag' as 0 disables the object's heart beat.  Passing a 'flag' of
1 will cause heart_beat() to be called in the object once each heart beat
(a variable number defined by your local administrator, usually 2 seconds).
Passing a 'flag' of greater than 1 will usually set the number of heart beats
in between calls to heart_beat(), however your local administrator may have
the system configured to treat any 'flag' above 1 as 1.

See also:
 heart_beat,
 query_heart_beat

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_hide - set the hide flag on a hidable object

void set_hide( int flag );

Sets the hidden flag of an object to `flag', which should be 0 or 1
(hide disable, or hide enable, respectively).  Only objects for which
`master()->valid_hide(ob)' returns true may make themselves hidden.
When the object is hidden, only other hidable objects will be able to
find the object with find_object(), or multiple-object returning efuns such
as users(), children(), all_inventory(), etc.

See also:
 valid_hide

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

tell_object - send a message to an object

void tell_object( object ob, string str );

Send a message 'str' to object 'ob'. If it is an interactive object (a player),
then the message will go to him, otherwise it will go to the local
function "catch_tell()".

See also:
 write,
 shout,
 say,
 tell_room,
 catch_tell

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

tell_room - send a message to all objects in a room

void tell_room( mixed ob, string str, object array exclude );

Send a message 'str' to object all objects in the room 'ob'.  'ob' can also 
be the filename of the room (string).  If 'exclude' is specified, all
objects in the exclude array will not receive the message.

See also:
 write,
 shout,
 say,
 tell_object,
 catch_tell

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

virtualp - determine whether or not a given variable points to a virtual object

int virtualp( object arg );

Returns true (1) if the argument is objectp() and the O_VIRTUAL flag is set.
The driver sets the O_VIRTUAL flag for those objects created via the
'compile_object' function in the master object.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_verb - return the name of the command currently being executed

string query_verb();

This efun is only available if NO_ADD_ACTION is not compiled in.

Give the name of the current command, or 0 if not executing from a command.
This function is useful when several commands (verbs) may cause the same
function to execute and it is necessary to determine which verb it was
that invoked the function.

See also:
 add_action

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

query_ip_port(void|object) [PACKAGE_CONTRIB]
mixed query_notify_fail() [!NO_ADD_ACTION] [PACKAGE_CONTRIB]
int remove_interactive(object) [PACKAGE_CONTRIB]
int remove_shadow(object ob) [!NO_SHADOWS] [PACKAGE_CONTRIB]
int replaceable(object, void | string array) [PACKAGE_CONTRIB]
float array rotate_x(float array, float) [PACKAGE_MATRIX]
float array rotate_y(float array, float) [PACKAGE_MATRIX]
float array rotate_z(float array, float) [PACKAGE_MATRIX]
float array scale(float array, float) [PACKAGE_MATRIX]
void set_this_player(object | int) [NO_ADD_ACTION]
void store_variable(string, mixed) [PACKAGE_CONTRIB]
string terminal_colour(string, mapping) [PACKAGE_CONTRIB]
float array translate(float array, float, float, float) [PACKAGE_MATRIX]
mapping unique_mapping(array, string|function, ...)
string upper_case(string) [PACKAGE_CONTRIB]
string array variables(object, int default: 0); [PACKAGE_CONTRIB]

back to top

socket_accept - accept a connection on a socket

int socket_accept( int s, string | function read_callback, string | function write_callback );

This efun is only available if PACKAGE_SOCKETS is compiled in.

The argument s is a socket that has been created with socket_create(),
bound to an address with socket_bind(), and is listening for connections
after a socket_listen(). socket_accept() extracts the first connection
on the queue of pending connections, creates a new socket with the same
properties of s and allocates a new file descriptor for the socket. If no
pending connections are present on the queue, socket_accept() returns an
error as described below. The accepted socket is used to read and write data
to and from the socket which connected to this one; it is not used to accept
more connections. The original socket s remains open for accepting further
connections.

The argument read_callback is the function or name of a function
for the driver to call when the new socket (not the accepting socket)
receives data.

The write callback should follow this format:

void read_callback(int fd)

Where fd is the socket which is ready to accept data.

The argument write_callback is the name of a function for the driver to
call when the new socket (not the accepting socket) is ready to be
written to. The write callback should follow this format:

void write_callback(int fd)

Where fd is the socket which is ready to be written to.

Note: The close_callback of the accepting socket (not the new socket)
is called if the new socket closes unexpectedly, i.e. not as the result
of a socket_close() call. The close callback should follow this format:

void close_callback(int fd)

Where fd is the socket which has closed.

socket_accept() returns a non-negative descriptor for the accepted
socket on success. On failure, it returns a negative value. socket_error()
can be used on the return value to get a text description of the error.

ERRORS - these definitions are in socket_err.h


* EEFDRANGE Descriptor out of range.
* EEBADF Descriptor is invalid.
* EESECURITY Security violation attempted.
* EEMODENOTSUPP Socket mode not supported.
* EENOTLISTN Socket not listening.
* EEWOULDBLOCK Operation would block.
* EEINTR Interrupted system call.
* EEACCEPT Problem with accept.
* EENOSOCKS No more available efun sockets.

See also:
socket_bind,
socket_connect,
socket_create,
socket_listen

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_acquire - assume ownership of a socket

int socket_acquire( int socket, string | function read_callback,
             string | function write_callback,
                    string | function close_callback );

This efun is only available if PACKAGE_SOCKETS is compiled in.

socket_acquire() is called to complete the handshake begun by socket_release()
for transferring ownership (and control) of a socket to a new object.
socket_release() calls the release callback function within the new owner
object to notify the object that it wishes to pass control of the socket
on.  It is the responsibility of the new owner socket to decide whether
it wishes to accept the socket.  It it does, then socket_acquire() is
called to complete the transfer.  If not, then the callback simply returns
without completing the handshake.

In the former case the handshake is completed and the new object
becomes the socket owner.  The read, write and close callback function
parameters refer to functions within the new object.  These are specified
so that the MudOS driver will know which functions to call within the new
object.  Decling to acquire the socket will cause socket_release() to
return EESOCKNOTRLSD so the owner can perform appropriate clean-up.
EESOCKNOTRLSD is in "socket_err.h".

socket_acquire() may only be called within the context of thr release
callback function and only with the socket specified.

See also:
 socket_release

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_address - return the remote address for an efun socket

string socket_address( int s | object ob );

This efun is only available if PACKAGE_SOCKETS is compiled in.

socket_address() returns the remote address for an efun socket s, or for
an interactive object ob.

The returned address is of the form:

"127.0.0.1 23".

socket_address() returns:

a string format address on success.

an empty string on failure.

See also:
 socket_connect,
 socket_create,
 resolve,
 query_host_name,
 query_ip_number

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_bind - bind a name to a socket

int socket_bind( int s, int port );

This efun is only available if PACKAGE_SOCKETS is compiled in.

socket_bind() assigns a name to an unnamed socket. When a socket is
created with socket_create() it exists in a name space (address family)
but has no name assigned. socket_bind() requests that the port be assigned
to the socket s.

socket_bind() returns:

EESUCCESS on success.

a negative value indicated below on error.

ERRORS - These errors are in "socket_err.h"

* EEFDRANGE Descriptor out of range. * EEBADF Descriptor is invalid. * EESECURITY Security violation attempted. * EEISBOUND Socket is already bound. * EEADDRINUSE Address already in use. * EEBIND Problem with bind. * EEGETSOCKNAME Problem with getsockname.
See also: socket_connect. socket_create, socket_listen Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_close - close a socket

int socket_close( int s );

This efun is only available if PACKAGE_SOCKETS is compiled in.

socket_close() closes socket s. This frees a socket efun slot for use.

socket_close() returns:

EESUCCESS on success.

a negative value indicated below on error.

ERRORS - "socket_err.h"

* EEFDRANGE Descriptor out of range. * EEBADF Descriptor is invalid. * EESECURITY Security violation attempted.
See also: socket_accept, socket_create Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_connect - initiate a connection on a socket

int socket_connect( int s, string address,
                    string read_callback,
                    string write_callback );

This efun is only available if PACKAGE_SOCKETS is compiled in.

The argument s is a socket. s must be either a STREAM mode or a MUD mode
socket. address is the address to which the socket will attempt to connect.
address is of the form: "127.0.0.1 23"

The argument read_callback is the name of a function for the driver to
call when the socket gets data from its peer. The read callback should follow
this format:

void read_callback(int fd, mixed message)

Where fd is the socket which received the data, and message is the data
which was received.

The argument write_callback is the name of a function for the driver to
call when the socket is ready to be written to. The write callback should
follow this format:

void write_callback(int fd)

Where fd is the socket which is ready to be written to.

socket_connect() returns:

EESUCCESS on success.

a negative value indicated below on error.

ERRORS - these are in "socket_err.h"


* EEFDRANGE Descriptor out of range.
* EEBADF Descriptor is invalid.
* EESECURITY Security violation attempted.
* EEMODENOTSUPP Socket mode not supported.
* EEISLISTEN Socket is listening.
* EEISCONN Socket is already connected.
* EEBADADDR Problem with address format.
* EEINTR Interrupted system call.
* EEADDRINUSE Address already in use.
* EEALREADY Operation already in progress.
* EECONNREFUSED Connection refused.
* EECONNECT Problem with connect.

See also:
socket_accept,
socket_close,
socket_create

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_create - create an efun socket

int socket_create( int mode, string | function read_callback);

int socket_create( int mode, string | function read_callback, string | function close_callback );

This efun is only available if PACKAGE_SOCKETS is compiled in.

socket_create() creates an efun socket. mode determines which type of
socket is created. Currently supported socket modes are:

* MUD for sending LPC data types using TCP protocol. * STREAM for sending raw data using TCP protocol. * DATAGRAM for using UDP protocol.
The argument read_callback is the name of a function for the driver to call when the socket gets data from its peer. The read callback should follow this format:
void read_callback(int fd, mixed message)

Where fd is the socket which received the data, and message is the data
which was received.

The argument close_callback is the name of a function for the driver to
call if the socket closes unexpectedly, i.e. not as the result of a
socket_close() call. The close callback should follow this format:

void close_callback(int fd)

Where fd is the socket which has closed.
NOTE: close_callback is not used with DATAGRAM mode sockets.

socket_create() returns:

a non-negative descriptor on success.

a negative value indicated below on error.

ERRORS - these are in "socket_err.h"


* EEMODENOTSUPP Socket mode not supported.
* EESOCKET Problem creating socket.
* EESETSOCKOPT Problem with setsockopt.
* EENONBLOCK Problem setting non-blocking mode.
* EENOSOCKS No more available efun sockets.
* EESECURITY Security violation attempted.

See also:
socket_accept,
socket_bind,
socket_close,
socket_connect,
socket_listen,
socket_write

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_error - return a text description of a socket error

string socket_error( int error );

This efun is only available if PACKAGE_SOCKETS is compiled in.

socket_error() returns a string describing the error signified by error.

socket_error() returns:

a string describing the error on success.

"socket_error: invalid error number" on bad input.

See also:
 socket_create,
 socket_connect

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top


back to top

socket_listen - listen for connections on a socket

int socket_listen( int s, string listen_callback );

This efun is only available if PACKAGE_SOCKETS is compiled in.

To accept connections, a socket is first created with socket_create(),
the socket is them put into listening mode with socket_listen(), and
the connections are accepted with socket_accept(). The socket_listen() call
applies only to sockets of type STREAM or MUD.

The argument listen_callback is the name of a function for the driver to
call when a connection is requested on the listening socket. The listen
callback should follow this format:

void listen_callback(int fd)

Where fd is the listening socket.

socket_listen() returns:

EESUCCESS on success.

a negative value indicated below on error.

ERRORS - these are in "socket_err.h"


* EEFDRANGE Descriptor out of range.
* EEBADF Descriptor is invalid.
* EESECURITY Security violation attempted.
* EEMODENOTSUPP Socket mode not supported.
* EENOADDR Socket not bound to an address.
* EEISCONN Socket is already connected.
* EELISTEN Problem with listen.

See also:
socket_accept,
socket_connect,
socket_create

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_release - release ownership of a socket to another object

int socket_release( int socket, object ob,
                    string release_callback );

This efun is only available if PACKAGE_SOCKETS is compiled in.

socket_release() is used to change ownership (and control) of a socket
to another object.  It is useful in daemon objects (like inetd) which
handle connection set-up and then transfer a connected socket to another
object for further processing.

Socket ownership transfer involves a handshake between the current owner
object and the socket to which the current owner wishes to transfer the
socket.  The handshake is initiated when socket_release() is called.
socket_release() does appropriate security/integrity checking and then
calls the release_callback function in object ob.  This function is used
to notify ob that socket ownership is being transferred to it.  It is
then ob's responsibility to call socket_acquire() within the release
callback function.  If socket_acquire() is called then the handshake is
complete and socket ownership has been successfully transferred to ob.
ob may decline to accept responsibility for the socket by not calling
socket_acquire(), in which case ownership does not change and the
current socket owner must decide how to respond to this.

If the socket owner is successfully transfered then socket_release()
returns EESUCCESS.  If ob does not accept ownership for the socket then
EESOCKNOTRLSD is returned (both in "socket_err.h").  Other errors can be returned based on
security violation, bad socket descriptor vbalues, etc.

See also:
 socket_acquire

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

socket_write - send a message from a socket

int socket_write( int s, mixed message,
                    void | string address );

This efun is only available if PACKAGE_SOCKETS is compiled in.

socket_write() sends a message on a socket s. If the socket s is of type
STREAM or MUD, the socket must already be connected and the address is not
specified. If the socket is of type DATAGRAM, the address must be specified.
The address is of the form: "127.0.0.1 23".

socket_write() returns:

EESUCCESS on success.

a negative value indicated below on error.

ERRORS - these are in "socket_err.h"

* EEFDRANGE Descriptor out of range. * EEBADF Descriptor is invalid. * EESECURITY Security violation attempted. * EENOADDR Socket not bound to an address. * EEBADADDR Problem with address format. * EENOTCONN Socket not connected. * EEALREADY Operation already in progress. * EETYPENOTSUPP Object type not supported. * EEBADDATA Sending data with too many nested levels. * EESENDTO Problem with sendto. * EEMODENOTSUPP Socket mode not supported. * EEWOULDBLOCK Operation would block. * EESEND Problem with send. * EECALLBACK Wait for callback.
See also: socket_connect, socket_create Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

capitalize - capitalize a string

string capitalize( string str );

Convert the first character in 'str' to upper case, and return the
new string.

See also:
 lower_case

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

clear_bit - zero a bit in a bit string

string clear_bit( string str, int n );

Return the new string where bit 'n' is cleared in string 'str'. Note that
the old string 'str' is not modified.  See set_bit() for information on
the format of the string.

See also:
 set_bit,
 test_bit

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

crypt - encrypt a string

string crypt( string str, string seed );

Crypt the string 'str' using the first two characters from 'seed' as
a seed. If 'seed' is 0, then random seed is used.

The result has the first two characters as the seed.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

explode - break up a string

string array explode( string str, string del );

explode() returns an array of strings, created when the string 'str'
is split into pieces as divided by the delimiter 'del'.

EXAMPLE:

explode(str," ") will return as an array all of the words (separated
by spaces) in the string 'str'.

See also:
 implode,
 sscanf,
 replace_string,
 strsrch

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

implode - concatenate strings

string implode( array arr, string del );

mixed implode( array arr, function f);

mixed implode( array arr, function f, mixed start);

Concatenate all strings found in array 'arr', with the string 'del' between
each element. Only strings are used from the array.  Elements that are not
strings are ignored.

The second version takes the first and second values of arr and passes them
to f, then passes that result and the third arg to f, et cetera.  It returns
the last result of the call to f.

In the third case, the first call is f(start, arr[0]), then things proceed
as above.

See also:
 explode,
 sprintf

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

lower_case - return the lowercase version of a given string

string lower_case( string str );

Return the lowercase version of a given string (original string remains
unchanged).

See also:
 capitalize

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

next_bit - find the next bit set in a bitstring

int next_bit( string str, int n );

next_bit() returns the next bit set in a bitstring after 'n', or -1 if
'n' is the last set bit.

See also:
 set_bit,
 test_bit

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

pluralize - returns the plural of a given string

string pluralize( string str );

Returns the plural of 'str'.  Handles most of the oddities of the English
language.

This efun is only available if PACKAGE_CONTRIB is defined.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

reg_assoc - A regular pattern substring extractor

array reg_assoc(string str, string array pat_arr, array tok_arr);

array reg_assoc(string str, string array pat_arr, array tok_arr, mixed def);

reg_assoc() takes a string and explodes it into substrings matching 
the regular expression pattern strings given in pat_arr and associates
them with tokens given in tok_arr. If def (default 0) is given, it
is associated with a non-match. The return value is an array of
two arrays, the 1st being an array of the form 
    ({ non-match1, match1, non-match2, match2, ..., 
       non-match n, match n, non-match n+1 }) 

and the 2nd holds the tokens corresponding to the matches in order:

    ({ def, token corresponding to match1, ...., def, 
       token corresponding to match n, def }).

pat_arr and tok_arr must be of the same sizes, the ith element in
tok_arr being the corresponding token to the ith element of pat_arr.
pat_arr can only hold strings.

If pat_arr (and hence tok_arr) has size 0 then the return value is
simply ({ ({ str }), ({ def }) }).

EXAMPLE

 #define STRING_PAT "\e"(\e\e\e\e.|[^\e\e\e"])*\e""
 #define NUM_PAT "[0\-9]+"

 #define F_STRING 1
 #define F_NUM 2

 reg_assoc("Blah \e"blah\e" test 203 hhh j 308 \e"bacdcd\eb\e"acb",
  ({ STRING_PAT, NUM_PAT }), ({ F_STRING, F_NUM }), "no-match")

will return

({ ({ "Blah ", "\e"blah\e"", " test ", "203", " hhh j ", "308", " ",
      "\e"bacdcd\eb\e"", "acb" }),
   ({ "no-match", F_STRING, "no-match", F_NUM, "no-match", F_NUM, 
      "no-match", F_STRING, "no-match" }) })

See also:

regexp [for regular expression syntax]

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

regexp - regular expression handler

int regexp( string str, string pattern);

string array regexp( string array lines, string pattern);

string array regexp( string array lines, string pattern, int flag);

In the first version, regexp() returns true (1) if the string str contains
a substring which matches the regular expression 'pattern'.  If a complete
match is wanted, the pattern should begin with ^ and end with $.

When presented with an array of lines of text and a regular 
expression, regexp() returns an array containing those lines which 
match the pattern specified by the regular expression. If the (flag & 2)
is nonzero, (flag defaults to zero), then non-matches will be returned
instead of matches. If (flag & 1) is nonzero, the array returned will be of 
the form ({ index1 + 1, match1, ..., indexn + 1, matchn }) where indexn
is the index of nth match/non match in the array lines.

REGULAR EXPRESSION SYNTAX

A regular expression is zero or more branches, separated by '|'.
It matches anything that matches one of the branches.

A branch is zero or more pieces, concatenated.
It matches a match for the first, followed by a match for the second, etc.

A piece is an atom possibly followed by '*', '+', or '?'.
An atom followed by '*' matches a sequence of 0 or more matches of the atom.
An atom followed by '+' matches a sequence of 1 or more matches of the atom.
An atom followed by '?' matches a match of the atom, or the null string.

An atom is a regular expression in parentheses (matching a match for the
regular expression), a range (see below), '.'
(matching any single character), '^' (matching the null string at the
beginning of the input string), '$' (matching the null string at the
end of the input string), a '\e' followed by a single character (matching
that character), or a single character with no other significance
(matching that character).

A range is a sequence of characters enclosed in '[]'.
It normally matches any single character from the sequence.
If the sequence begins with '^',
it matches any single character not from the rest of the sequence.
If two characters in the sequence are separated by '-', this is shorthand
for the full list of ASCII characters between them
(e.g. '[0-9]' matches any decimal digit).
To include a literal ']' in the sequence, make it the first character
(following a possible '^').
To include a literal '-', make it the first or last character.

AMBIGUITY

If a regular expression could match two different parts of the input string,
it will match the one which begins earliest.
If both begin in the same place but match different lengths, or match
the same length in different ways, life gets messier, as follows.

In general, the possibilities in a list of branches are considered in
left-to-right order, the possibilities for '*', '+', and '?' are
considered longest-first, nested constructs are considered from the
outermost in, and concatenated constructs are considered leftmost-first.
The match that will be chosen is the one that uses the earliest
possibility in the first choice that has to be made.
If there is more than one choice, the next will be made in the same manner
(earliest possibility) subject to the decision on the first choice.
And so forth.

For example, '(ab|a)b*c' could match 'abc' in one of two ways.
The first choice is between 'ab' and 'a'; since 'ab' is earlier, and does
lead to a successful overall match, it is chosen.
Since the 'b' is already spoken for,
the 'b*' must match its last possibility (the empty string) since
it must respect the earlier choice.

In the particular case where no '|'s are present and there is only one
'*', '+', or '?', the net effect is that the longest possible
match will be chosen.
So 'ab*', presented with 'xabbbby', will match 'abbbb'.
Note that if 'ab*' is tried against 'xabyabbbz', it
will match 'ab' just after 'x', due to the begins-earliest rule.
(In effect, the decision on where to start the match is the first choice
to be made, hence subsequent choices must respect it even if this leads them
to less-preferred alternatives.)

See also:

 sscanf,
 explode,
 strsrch

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

repeat_string - repeat a string a specified number of times.

string repeat_string(string, int);

repeat_string returns a string that consists of its first argument
repeated n times, where 'n' is repeat_string's second argument.
So repeat_string("foo", 3) would return "foofoofoo".

This function requires PACKAGE_CONTRIB to be defined in the options file.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

replace_string - replace all instances of a string within a string

string replace_string( string str, string pattern, string replace );

string replace_string( string str, string pattern, string replace, int max );

string replace_string( string str, string pattern, string replace, int first, int last );

replace_string() returns 'str' with all instances of 'pattern' replaced with
'replace'.  If 'pattern' has zero length then str is returned unmodified.
If the resultant string would exceed the maximum string length then
replace_string() returns an undefinedp(), non-stringp() value.

replace_string() can be used to remove characters from a string by
specifying a pattern and a zero-length replace parameter.  For example,
replace_string(" 1 2 3 ", " ", "") would return "123".  replace_string()
executes faster this way then explode()/implode().

The 4th and 5th arguments are optional (to retain backward compatibility.)
The extra arguments have the following effect:

With 4 args:

The 4th argument specifies the maximum number of replacements
to make (the count starts at 1). A value of 0 implies 'replace all', and
thus, acts as replace_string() with 3 arguments would. E.g.,
replace_string("xyxx", "x", "z", 2) would return "zyzx".

With 5 args:

The 4th and 5th arguments specify the range of matches to replace
between, with the following constraints:

* first max_matches : change all to end * first > last : return the unmodified array.
E.g., replace_string("xyxxy", "x", "z", 2, 3) returns "xyzzy". See also: sscanf, explode, strsrch Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_bit - set a bit in a bitstring 
string set_bit( string str, int n ); 

Return the new string where bit 'n' is set in string 'str'. Note that the old string 'str' is not modified. 

The maximum value of 'n' is limited by the value of the 'maximum bits in a bitfield' entry in the driver config file. 

The new string will automatically be extended if needed. 

Bits are packed 6 per byte in printable strings. 

See also: clear_bit , test_bit 

Tim Hollebeek 
Beek @ZorkMUD, Lima Bean, IdeaExchange, TMI-2, and elsewhere 

back to top

sprintf - formatted output conversion

string sprintf( string format, ... );

An implementation of sprintf() for LPC, with quite a few extensions
Originally implemented by Lynscar (Sean A Reith).

This version supports the following as modifiers:
* " " - pad positive integers with a space. * "+" - pad positive integers with a plus sign. * "-" - left adjusted within field size. Note: sprintf() defaults to right justification, which is unnatural in the context of a mainly string based language but has been retained for "compatability". * "|" - centered within field size. * "=" - column mode if width is greater than field size. This is only meaningful with strings, all other types ignore this. Columns are auto-magically word wrapped. * "#" - table mode, print a list of '\\n' separated 'words' in a table within the field size. only meaningful with strings. * a number - specifies the field size, a '*' specifies to use the corresponding arg as the field size. If n is prepended with a zero, then the field is padded zeros, otherwise it is padded with spaces (or specified pad string; see below). * "." then a number - precision of n, simple strings truncate after this (if precision is greater than field size, then field size = precision), tables use precision to specify the number of columns (if precision not specified then tables calculate a best fit), all other types ignore this. * ":" then a number - n specifies the fs _and_ the precision, if n is prepended by a zero then the field is padded with zeros instead of spaces. * "@" - the argument is an array. the corresponding format_info (minus the "@") is applied to each element of the array. * "'X'" - The char(s) between the single-quotes are used to pad to field size (defaults to space) (if both a zero (in front of field size) and a pad string are specified, the one specified second overrules). NOTE: to include "'" in the pad string, you must use "\'" (as the backslash has to be escaped past the interpreter), similarly, to include "\" requires "\\\\".
The following are the possible type specifiers.
* % - in which case no arguments are interpreted, and a "%" is inserted, and all modifiers are ignored. * O - the argument is an LPC datatype. * s - the argument is a string. * d, i - the integer arg is printed in decimal. * c - the integer arg is to be printed as a character. * o - the integer arg is printed in octal. * x - the integer arg is printed in hex. * X - the integer arg is printed in hex (with A-F in capitals). * f - floating point number
See also: sscanf Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

sscanf - match substrings in a string

int sscanf( string str, string fmt, mixed var1, mixed var2, ... );

Parse a string 'str' using the format 'fmt'.  The format 'fmt'
consists of text to match against 'str', separated by patterns which
begin with '%'.  The following patterns are supported:

* '%%' - matches '%' * '%x' - matches a hexidecimal number * '%d' - matches a decimal number * '%f' - matches a floating point number * '%(regexp)' - matches anything that matches the regular expression 'regexp' (see the regexp() efun for details) * '%s' - matches a string; see below
Note that the third and following arguments are NOT expressions; they must be valid lvalues (locations which can be assigned to). As matches are encountered in the string, the corresponding values are put directly into the third and following arguments. If a problem is encountered (either some of the text between patterns doesn't match, or a pattern can't be matched to the corresponding input) the number of matches so far is returned, and the remaining arguments are left unchanged. If a '*' comes immediately after the '%' in the format, then that pattern is matched, but not assigned to a variable. It is counted in the return value. '%s' is handled as follows. If it is followed by text, '%s' matches up the the next ocurrence of the text. For example, the format "%sxy%s" will match "fox" to the first %s when used on the string "foxxybarxyz". If the %s occurs at the end of the string, the remainder of the string is matched. If it is followed immediately by another pattern, then %s matches up to the first valid match for the following pattern. "%s%s" is illegal. See also: explode, replace_string, strsrch Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

strcmp - determines the lexical relationship between two strings

int strcmp( string one, string two );

This implementatin of strcmp() is identical to the one found in C libraries.
If string one lexically precedes string two, then strcmp() returns a number
less than 0.  If the two strings have the same value, strcmp() returns 0.
If string two lexically precedes string one, then strcmp() returns a number
greater than 0.  This efunction is particularly useful in the compare
functions needed by sort_array().

Note that relational operators (<, >, etc) can also be used to compare
strings.

See also:
 sort_array

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

strlen - returns the length of a string

int strlen( string str );

strlen() returns the number of characters in the string 'str'.

See also:
 sizeof

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

strsrch - search for substrings in a string

int strsrch( string str, string substr | int char, int flag );

strsrch() searches for the first occurance of the string 'substr' in the 
string 'str'.  The last occurance of 'substr' can be found by passing '-1' 
as the 3rd argument (which is optional).  If the second argument is an 
integer, that character is found (like C's strchr()/strrchr().)  The empty 
string or null value cannot be searched for.

The integer offset of the first (last) match is returned.  -1 is returned
if there was no match, or an error occurred (bad args, etc).

See also:
 sscanf,
 replace_string,
 regexp

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

terminal_colour - replaces codes in a string

string terminal_colour(string str, mapping m, int wrap, int indent);

terminal_colour() replaces each occurrence of %^key%^ in str with 'value',
where 'key' and 'value' are the elements in the mapping m.

'wrap' is the optional column number to wrap at, and 'indent' is the
amount to indent the second and following lines.  Codes are assumed to
change the mode of the terminal and not generate any printable
characters for the purposes of wrapping.

This efun is only available if PACKAGE_CONTRIB is defined.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

test_bit - test a bit in a bitstring

int test_bit( string str, int n );

Returns 1 if bit 'n' was set in string 'str', and zero otherwise.

See also:
 set_bit,
 clear_bit

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

upper_case - return the uppercase version of a given string

string upper_case(string);

Return the uppercase version of a given string (original string remains
unchanged).

This function requires PACKAGE_CONTRIB to be defined in the options file.

See also:
 capitalize,
 lower_case

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

all_previous_objects - returns an array of objects that called the current function

object array all_previous_objects();

Returns an array of objects that called current function.
Note that local function calls do not set previous_object() to the current
object, but leave it unchanged.

The first element of the array is previous_object(), followed by
previous_object(1), etc ...

See also:
 call_other,
 origin,
 previous_object

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

call_out_info - get pending call_out() information

array call_out_info();

Get information about all pending call outs. An array is returned,
where every item in the array consists 3 elements: the object,
the function, and the remaining delay.

Note: due to security concerns, and the fact that call_outs may now
have an arbitrary number of arguments, the 4th element of the return
value was returned.  The security concerns stem from the fact that if
the arguments where types which can be modified (arrays, mappings,
etc), obtaining them would allow them to be modified before the
function was called.  It is possible this will be fixed in the
future if there is enough interest.

See also:
 call_out,
 remove_call_out

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

check_memory - check all allocated blocks

string check_memory(int flag)

returns a string describing possible memory allocation problems.  If the
optional flag is 1, a summary of allocated memory is printed at the
end.

This efun is only available if PACKAGE_DEVELOP, DEBUGMALLOC, and
DEBUGMALLOC_EXTENSIONS are defined.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

ctime - return a time string

string ctime( int clock );

Gives a nice string with current date and time, with the argument 'clock'
that is the number of seconds since 1970.

See also:
 time,
 localtime,
 uptime

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

debug_message - send a message to the driver's stdout

void debug_message(string);

The string argument is printed on the driver's stdout, as well as being added
to the debug.log file.

See also:
 ctime

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

deep_inherit_list - get a list of ancestors of an object

string array deep_inherit_list( object obj );

Returns an array of filenames of all objects inherited (directly and
indirectly) by obj.

See also:
 inherit_list,
 inherits

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

error - generate a run-time error

void error( string err );

A run-time error 'err' will be generated when error() is called.  Execution
of the current thread will halt, and the trace will be recorded to the
debug log.

See also:
 catch,
 throw,
 error_handler

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

eval_cost - returns the evaluation cost remaining

void eval_cost()

eval_cost() returns the number of instructions that can be executed
before the driver decides it is in an infinite loop.

See also:
 set_eval_limit,
 reset_eval_cost

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

external_start - start an external command

int external_start(int which, string args, mixed read_cb, mixed write_cb, mixed close_cb);

'which' specifies which of the 5 external commands specified in
the config file to run.  'args' are the arguments to pass to the
command.  The driver then starts up the specified command, and sets up
an LPC socket to communicate with the input and output of the command.
The file descriptor of the LPC socket is returned.

See also:
 time,
 ctime,
 localtime

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

find_call_out - find a call out scheduled to be called next

int find_call_out( string func );

Find the first call out due to be executed for function 'func' in the
current object, or the call_out() which returned the integer 'handle',
and return the time left. If it is not found, then return -1.

See also:
 call_out,
 remove_call_out,
 set_heart_beat

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

flush_messages - send all pending messages to a user

int flush_messages();

int flush_messages(object user);

Normally, messages are queued, then sent all at once to minimize the
number of packets required.  This efun forces all pending messages to
be written immediately.  If no user is specified, messages for ALL users
are flushed.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

function_exists - find the file containing a given function in an object

string function_exists( string str, object ob, int flag );

Return the file name of the object that defines the function 'str' in
object 'ob'. The returned value can be other than 'file_name(ob)' if the
function is defined by an inherited object.

0 is returned if the function was not defined.

Note that function_exists() does not check shadows.

If flag is omitted or zero functions that cannot be called are not returned
(e.g. the function is returned only if call_other(ob, str) would succeed).
If the flag is nonzero, static and private functions are returned too.

See also:
 call_other

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

function_profile - get function profiling information for an object

array function_profile( object ob );

Returns function profiling information for 'ob', or this_object() if 'ob'
is not specified.  This is only available if the driver was compiled
with PROFILE_FUNCTIONS defined.

An array of mappings is returned, one for each function in 'ob'.  The format 
of the mapping is:
       ([ "name"     : name_of_the_function,
          "calls"    : number_of_calls,

          "self"     : cpu_time_spent_in self,
          "children" : cpu_time_spent_in_children
       ])

The usefulness of this is tied to the resolution of the CPU clock--even
though the units are microseconds, the CPU timer resolution is often much
less.

See also:
rusage,
time_expression

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

functions - list all the functions in a given object.

string array functions(object, int default: 0);

functions() can return two different things. If the second argument is
0 (which it is by default) it will return an array containing the names
of all the functions in the object passed as the first argument. If the
second argument is non-zero, more information about each function is
given. For a non-zero second argument, each array element contains
the following:

({ function_name, number_of_arguments, return_type, ... }). 

Where the fourth and following elements are the argument types.  If
the save_types pragma was not in effect when the function was compiled,
number_of_arguments will be correct, but no types will be available.

This efun is only available if PACKAGE_CONTRIB is defined in the
options file.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

inherit_list - get a list of parents of an object

string array inherit_list( object obj );

Returns an array of filenames of objects inherited by obj.
If COMPAT_32 was compiled in, this behaves like deep_inherit_list(),
otherwise it behaves like shallow_inherit_list().

See also:
 deep_inherit_list,
 shallow_inherit_list,
 inherits

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

inherits - determine if an object inherits a given file

int inherits( string file, object obj );

inherits() returns 0 if obj does not inherit file, 1 if it inherits the
most recent copy of file, and 2 if it inherits an old copy of file.

See also:
 deep_inherit_list,
 inherit_list

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

localtime - convert to local time

array localtime( int time );

localtime() converts a time value (as returned by time()) into an array
of values which represents the time locally.  In the past time() was used
to get the time in GMT (UTC), and then local definitions were used to
determine the local offset from GMT.  This roundabout approach is no
longer necessary.  localtime() returns the seconds, minutes and hours,
the day, month and year, day of the week, day of the year,
the name of the local timezone and how far the MUD is from GMT.  This
information is retrieved directly from the operating system and made
available to the driver without the use of MUD-specific configuration
files.

localtime() returns an array containing the values specified above.
The index for each value is defined symbolically in localtime.h.  The
following table summarizes the array returned by localtime().
    int    LT_SEC        Seconds after the minute (0..59)
    int    LT_MIN        Minutes after the hour (0..59)
    int    LT_HOUR        Hour since midnight (0..23)
    int    LT_MDAY        Day of the month (1..31)
    int    LT_MON        Months since January (0..11)
    int    LT_YEAR        Year (guarenteed to be >= 1900)
    int    LT_WDAY        Days since Sunday (0..6)
    int    LT_YDAY        Days since January 1 (0..365)
    int    LT_GMTOFF    Seconds after GMT (UTC)
    string    LT_ZONE        Timezone name

See also:
ctime,
time,
time_expression,
uptime

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

lpc_info - return information about LPC->C compiled objects

string lpc_info();

lpc_info() returns a string describing which LPC->C programs are available,
which are loaded, and which are out of date with respect to their source.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

max_eval_cost - returns the maximum evaluation cost

void max_eval_cost()

max_eval_cost() returns the number of instructions that can be executed
before the driver decides it is in an infinite loop.

See also:
 set_eval_limit,
 reset_eval_cost

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

memory_summary - return a summary of memory usage

mapping memory_summary();

memory_summary() returns a mapping of the form:

PRE(
([ 
  program name : ([
    var name : mem usage,
    ...
  ])
  ...
])
)

the memory usage is the memory required to store the value divided by the
number of variables pointing to that particular value.  [Due to sharing
of values, giving an exact number for the memory usage of any
value is impossible]

This efun is only available if PACKAGE_CONTRIB is defined.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

named_livings - return all living objects with names

mapping named_livings();

named_livings() returns all objects that have called both set_living_name()
and enable_commands().  It is significantly more efficient than livings().

named_livings() is available if PACKAGE_CONTRIB is defined, and NO_ADD_ACTION
is not.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

program_info - returns information about program memory usage

string program_info();

string program_info(object ob);

Returns a summary of the memory usage of the program for a given object.
If no program is specified, a summary of the memory usage of all loaded
programs is returned.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

reclaim_objects - reclaim any lingering objects

int reclaim_objects();

Cycles through all objects that are loaded, and frees any lingering objects
that it can.  This could result in a sizable amount of memory being freed up,
depending on how the mud is coded.  Objects are typically left lingering
when a global variable in more than one object contains a pointer to it,
and the object gets destructed, but the values containing pointers to the
object are never accessed again.  This efun returns the number of destructed
objects encountered in variables.

See also:
 destruct

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

replace_program - replaces the program in this_object()

void replace_program( string str );

replace_program() replaces the program in this_object() with that of an 
object it inherits.  The string argument is the filename of the object 
whose program is to be used.  Once the replacement takes place, the current 
object effectively becomes a clone of that other object, but with its 
current filename and global variable values. The program is not actually 
replaced until the current execution is completed.

Note that one effect of this is that all functions defined in the object
no longer exist, being replaced by the functions in the inherited program,
so this routine should not be called if one of those functions might be
called later (and in particular, create() needs to exist if you intend to
clone from the object).

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

replaceable - determine whether any functions are defined in at this level

int replaceable(object ob);

int replaceable(object ob, string array fnames);

In the second form, return 0 if the program for object ob defines any
functions explicitly, as opposed to simply inheriting.  Function names
in the array fnames are ignored.  If no such functions are defined, 1
is returned.  If the second argument is omitted, it defaults to
({ "create" }).  The purpose of this efun is to assist in making
automatic decisions on whether to call replace_program().  Note that
the default version ignores create(), so it is only safe to replace a
object for which replaceable() returns true if you never intend to
clone from that object.

See also:
 replace_program,
 functions,
 function_exists,
 inherit_list

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

reset_eval_cost - resets the evaluation cost remaining

void reset_eval_cost();

reset_eval_cost() resets the evaluation cost remaining to the maximum
evaluation cost.

See also:
 eval_cost,
 set_eval_limit

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_eval_limit - set the maximum evaluation cost

void set_eval_limit( int );

set_eval_limit(), with a nonzero argument, sets the maximum evaluation
cost that is allowed for any one thread before a runtime error occurs.
With a zero argument, it sets the current evaluation counter to zero,
and the maximum cost is returned.  set_eval_limit(-1) returns the
remaining evaluation cost.

See also:
 eval_cost

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

set_reset - modify the time until reset on an object

varargs void set_reset( object ob, int time );

This efun is only available if NO_RESETS is not compiled in.

Sets the time until reset on 'ob' to 'time' seconds from now.  If 'time'
is omitted, the driver's normal reset time setting formula is applied
to 'ob', that is,
reset time = current_time + reset_time / 2 + random(reset_time / 2)

See also:
reset

Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

shallow_inherit_list - get a list of parents of an object

string array shallow_inherit_list( object obj );

Returns an array of filenames of objects inherited by obj.  Only directly
inherited files are returned.  E.g. if A inherits B which inherits C,
inherit_list(A) will return an array with B, but not C.

See also:
 deep_inherit_list,
 inherit_list,
 inherits

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

shutdown - shutdown the driver

void shutdown( int how );

This function shuts down the driver in a controlled fashion (as opposed to
how a crash would shut it down).  The 'how' argument specifes what integer
value that driver should pass to exit().  The convention is to pass 'how'
as -1 when the script that restarts the driver should die as well.  Thus
a reboot command would use shutdown() while a halt command would use
shutdown(-1).  The script must explicitly check the return value to see
if it is -1 if you wish to use this convention.  Obviously, shutdown()
is a sensitive function and should be secured.  As with exec(), the way
to make it secure is to add a simul_efun of the same name which does
the appropriate security checks.  Be sure to set valid_override() up
(in master.c) to protect against efun::shutdown().

See also:
 crash,
 slow_shutdown,
 valid_override

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

time - return the number of seconds since January 1 1970

int time( void );

Return the number of seconds since midnight (GMT) January 1, 1970.

See also:
 ctime,
 localtime,
 time_expression,
 uptime

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

uptime - return the number of seconds elapsed since the last driver reboot

int uptime();

This function returns the number of seconds since the last driver reboot.

See also:
 time,
 ctime,
 localtime,
 time_expression

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

variables - list all the variables in a given object.

string array variables(object, int default: 0);

variables() can return two different things. If the second argument is
0 (which it is by default) it will return an array containing the names
of all the variables in the object passed as the first argument. If the
second argument is non-zero, more information about each variable is
given. For a non-zero second argument, each array element contains
the following:

({ variable_name, variable_type }). 

Where variable_name is the name of the given variable, and variable_type
is the type of the variable, such as "string" or "private int" etc.

This efun is only available if PACKAGE_CONTRIB is defined in the
options file.

 Tim Hollebeek  Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

Predefined preprocessor #defines

Note: additional predefines may be added from the command line using the -D
flag.  Also, anything defined in either options.h will be available surrounded
by __; e.g if FOO is defined in options.h, the __FOO__ will be defined in all
objects.

The following identifiers may be defined:

* MUDOS: always defined * "2.7.2": a string representing the version of MudOS being run * __PORT__: archaic; the port number of the first (previously, the only) external port * __ARCH__: the name of the architecture of the machine * __COMPILER__: the compiler MudOS was compiled with * __OPTIMIZATION__: the optimization used * MUD_NAME: the MUD name from the config file * HAS_ED: defined if the ed() efun is available * HAS_PRINTF: defined if the printf() efun is available * HAS_RUSAGE: defined if the rusage() efun is available * HAS_DEBUG_LEVEL: defined if the debug_level() efun is available * "doc/concepts/defines.c": the file being compiled * __DIR__: the directory the file is in (with the trailing /)
Tim Hollebeek Beek@ZorkMUD, Lima Bean, IdeaExchange, and elsewhere

back to top

What is LPC?

LPC is the language in which MudOS (and LPmud) objects are written.
LPC stands for Lars Pensj| C.  As one might surmise from the name,
LPC is based on the syntax of C.  LPC provides the C while loop, for loop,
if statement, switch statement, a variant of sscanf, and integer data type,
(LPC also provides other data types not in C such as the object and the
mapping).  LPC uses C's syntax for defining and calling functions and for
declaring variables.  Note that LPC's version of the string datatype is
much different from that provided by C.  See the LPC tutorial on syntax
and language constructs for more information.

Here are some differences between LPC and C:

There is no need for a function named "main" in LPC objects (although there
is one called "create").

The efuns (or system calls) provided by the gamedriver are different than
those typically found in the C library (libc.a).

There is no malloc().  However, there is an allocate(int value) efun that
lets space be allocated for arrays.  Note that the argument to 'allocate'
is not in units of bytes, but rather in units of elements.

Memory is never explicitly deallocated.  The gamedriver keeps track of
how many times a given piece of data has been referenced.  When the
reference count goes to zero (when no object has a copy of that variable),
then the space used by the variable is reclaimed (garbage collected).

The string data type in LPC is closer to that provided by BASIC than that
provided by C.  Strings are not declared as arrays of characters but rather
as a basic intrinsic type.  Strings may be concatenated using the '+' operator.

For example, the LPC statements:

string ack;

ack = foo + bar;

are equivalent to the C statements:

char *ack;

ack = (char *)malloc(strlen(foo) + 1);
strcpy(ack,foo);
ack = (char *)realloc(strlen(ack) + strlen(bar) + 1);
strcat(ack,bar);

LPC is an interpreted language (however it is compiled into an internal
compact tokenized form before being interpreted).

sscanf does not work in the same way as in C. arguments to sscanf need not
be pointers (since LPC does not have the explicit pointer data type). Also,
sscanf(arg,"%s %s",str1,str2) does not operate as the C programmer would
expect. In C, the first word of arg would be copied into str1 and the
second word of arg into str2. In LPC, the first word is copied into str1
and the _remainder_ of arg is copied into str2.

back to top

message

message is a new efun in MudOS designed to make communication efuns more 
generic and to provide a standard way of talking to clients intelligently.

See the message() efun doc for details on how the efun works.

Probably the most important element of this function is the "class".
If used properly, you could use this field to implement a very simple
version of earmuffs, or to communicate intelligently with a custom
client.  The class defines the type of message that the string
contains.  Initial simple implementations would have the classes
"shout", "say", "write", "tell_object" (which would be generated by
simul_efuns of the same name that replace the more traditional efuns).

Given this, let's say that you wanted to implment a quick and easy
earmuff ability. (the ability to mask shouts) In your user (player)
object, you would have the function receive_message.  Here's the
simplest implementation possible:

void receive_message (string msg, mixed class)
{
    receive(msg);
}

This simply takes all messages generated by the message efun and
displays them to the user. However, you could imagine a simple
earmuffs implementation on top of this:

string *muffle = ({});

int muffle_class (string arg)
{
    muffle += ({arg});
}

void receive_message (string msg, string class)
{
    if (member_array(class,string) == -1)
        receive(msg);
}

Now you can see, that if a particular class is muffled (say, "shout"
for example), the text never gets displayed, but in other cases it
does.

However, not all uses of the shout() efun are really shouts, in the
traditional mud sense. For example, let's say that the admin of the
mud wants to send a message to all users telling them that the system
is going to be shut down in 5 minutes. To do this, they might use
echo, which in turn uses the shout() efun. So all users who had
"shout" muffled would miss this important message. This means that a
broader number of classes is really needed to make message() truly
useful. For the example given, let's say we make a new "broadcast"
class. This message class would be used for important announcements
that everyone should hear. Perhaps a restriction could even be made
so that muffle prohibited blocking this class.

Let's look at another example. What if you're tired of all of the
millions of emotes (soul commands) that clutter your screen? Wouldn't
it be nice to just muffle those? Well, obviously a new "emote" class
is needed that all soul functions use. Now you might be thinking to
yourself "hey... I don't want to have to use this really complex
message() efun every time I write a soul command. write() and say()
are very simple, and I like using those." Well, I couldn't agree with
you more. To combat that problem, I make a simul_efun for each type
of commonly used message class. Like emote for example. I made a new
simul_efun called emote() that in fact made writing soul commands
easier, and used message() with the "emote" class. I won't show you
the code for the emote simul_efun, but here's the basic idea:

varargs int emote (object emoter, string self_message, string
    other_message, mixed emotee, string target_message, string modifier);

emoter - the object doing the emoting
self_message - the message displayed to the emoter
other_message - the message displayed to the whole room
emotee - the target of the emote (i.e. kick huthar)
target_message - the message displayed to the emotee
string modifier - any extra modifier to tack on to the end of the
    emote string. (i.e. adverbs: smiles happily, cheerfully, etc.) - only
    really complex soul commands need this (if they want to be able to
    control multiple modifiers to a single soul command)

At this point, some might be thinking, "ok... so you can do very
powerful selective muffling, big deal. this seems like a lot of work
for nothing." Good point. Muffling was just a simple neat thing you
could do with message now. Most of the real advantages from message
will come a bit down the line when someone gets around to writing a
smart client program. Here's how that will work.

Basically the idea is to separate all of the messages sent to a user
by the content. So you have a "combat" class, and a "stat" class, and
a "room_description" class, and a "help" class as some examples.
Before I get started, let's write a new version of receive_message().

int has_smart_client;

void receive_message (string msg, string class)
{
    if (member_array(class,muffle) == -1) {
        if (has_smart_client) 
            receive (class + " : " + msg);
        else
            receive (msg);
    }
}

Ok. Let's look at what this does. If the user object has defined
has_smart_client to be > 0, then it prepends all messages with the
class name as well. So if you were to write a smart client that
parsed messages like that, you could make it redirect room
descriptions into one window, conversation into another, combat into
yet another area, etc. You could make a status line that always kept
your current room name (since it got passed as class "room_name" when
you enetered the room). You could make the heart_beat, pass a class
"status" message which gives a constant readout of your hit points in
your status line. All of this would be transparent to the end user.
It would just work.

In addition, you could do a simply graphical client using the same
technique. The BSX graphical mud / client could easily be implemented
on top of MudOS using message(). Or you could pass around small
bitmaps rather than the polygon-based line drawings of BSX. The
possibilities are pretty wide open.

There is at least one major flaw with this argument so far. Since
everyone has to implement this message protocol themselves, and since
nobody has written a smart client to take advantage of the protocol,
then when a client comes out, what's to guarantee that your mudlib
will even work with it? Well, that's actually most of the point to
this document. I'd like to outline a simple protocol that I hope
everyone will adopt, so that when a client finally comes out, it will
work with all mudlibs that adhere to this protocol.

(Note: It's now several years later, and AFAIK noone uses this protocol.
AMCP also exists and is supported by some mudlibs, but the only client is
very minimal. -Beek)

The protocol:

all messages sent to the smart client are in the form

"class:msg_length:msg"

msg_len is the length of the msg string. This is put in so that the
client can always know when it has received the entire message, and
when one starts and ends.

The following list of classes should be used and a client should be
able to parse and use any messages using these classes.

say            use of the "say" command or its equivalent
shout            use of the "shout" command or its equivalent
tell            use of the "tell" command or its equivalent
emote            a soul command or emote
broadcast        a broadcast message to everyone on the mud
combat            generic combat messages
combat_self        combat messages generated by the user's own attack
combat_other        combat messages generated by others
combat_*        all other specific combat messages
room_description    a long description of a room or location
room_name        a short name for a room or location
inventory        what you're carrying
item_description    a long description of the item
status            generic status messages
status_hp        current hit points
status_sp        current spell points
status_sobriety        current state of drunkeness
status_*        all other specific status messages
score            generic score messages
score_exp        experience points
score_money        the amount of coins or other money
developer        a broadcast message to all wizards/developers
class_fighter        a message to all fighters
class_mage        a message to all mages
class_thief        a message to all thieves
class_priest        a message to all priests
class_*            a message to the class specified
race_human        a message to all humans
race_elf        a message to all elves
race_dwarf        a message to all dwarves
race_*            a message to the race specified

*** optional classes to implement ***
bitmap            a generic bitmap message
bitmap_*        a specific type of bitmap
drawing            a generic drawing message
drawing_*        a specific type of drawing

back to top

What is the MudOS driver?

The MudOS driver is the program (written in C) which
provides the lowlevel support that makes a mud possible.  The driver
does many things including:

* accepts connections from remote machines (via a communications port) and attaches those connections to the login object (/adm/login.c on TMI). * provides a set of external functions (efuns) that may be called from within LPC objects. * compiles files into a compact internal tokenized form via the new(filename) (or clone_object(filename)) efun. * interprets (executes) objects represented in the tokenized form. The two main ways in which code gets executed are as follows:
  • a) the driver calls functions in objects based on input received from users (via the communications port). The specific functions that get called depend on what associations the objects of the mud have specified between player-typed commands and functions (via the add_action(function_name,command_name) efun). The driver also calls functions in LPC objects from within certain efuns (such as "init", "create", "clean_up", etc.).
  • b) objects can cause the driver to execute code in other objects via the call_other(object,function_name,args,...) efun. An alternate form of the call_other efun is object->function_name(args,...).

back to top

objects

What is an object?

An object consists of a collection of functions (also called 'methods')
and data (variables) on which the functions operate.  The only way to
manipulate the data contained in an object is via one of the functions
defined by the object.

Every single thing in a mud is an object.  Rooms are objects.  Weapons
are objects.  Even your character is an object (a special kind of object
called "interactive" but still an object in most every respect).  Each
object (except possibly virtual objects) in the mud is associated with
some file written in LPC (in the mud's directory structure) that describes
how the object is to interact with the gamedriver and the rest of the objects
in the mud.

back to top

OOP

OOP stands for "Object-Oriented Programming"

If you know how to code in C or Pascal or even one of the modern BASICs
(with procedures), then you already have many of the skills you will need
to program effectively in LPC.  The main thing you need is a skill in
translating your ideas into a sequential flow of steps (that a computer
can perform).  However, LPC is also an object-oriented language.
To effectively use LPC, you would benefit from a knowledge of OOP principles
and concepts.  Following are some of the principles of object-oriented
programming (note that LPC doesn't necessarily provide mechanisms
supporting all of these principles):

* systems are modularized on the basis of their data structures. * objects should be described as implementations of abstract data types. * unused objects should be deallocated by the underlying language system, without programmer intervention. * every non-simple type is a module, and every high-level module is a type. * a class may be defined as an extension or restriction of another. * program entities should be allowed to refer to objects of more than one class, and operations should be permitted to have different realizations in different classes. * it should be possible to declare a class as heir to more than one class, and more than once to the same class.
[These seven principles were taken from the "Object-oriented Software Construction" book by Bertrand Meyer]

back to top

LPC Preprocessor Manual

The preprocessor is a front end to the LPC compiler that provides such
handy features as:

* sharing definitions and code (#include) * macros (#define, #undef) * conditional compilation (#if, #ifdef, #ifndef, #else, #elif, #endif) * debugging (#echo) * compiler specific (#pragma) * text formatting short cuts (@, @@)
The first three are identical to C usage, so those already familiar with C may want to just skim the last few sections of this document. Note: For those directives that begin with '#' (such as #include), the '#' symbol must start in the first column (of the line). Sharing Definitions and Code This facility is provided through the #include directive. Syntax 1: #include Syntax 2: #include "file.h" Notes: The '#include ' form looks for the file, 'file.h' in the system's standard include directories. (On TMI this is just '/include'.) The '#include "file.h"' form looks for the file, 'file.h' in the same directory as the file that is including it. The #include statement is a way to textually include one file into another. Putting a statement such as '#include "file.h"' in a file gives the same effect as if the contents of file.h had been directly entered into the file at the point where the #include statement occurred. Included files are recompiled each time the object that include's them is recompiled. If the included file contains variables or functions of the same name as variables in the file doing the including, then a duplicate-name error will occur at compile time (in the same way that the error would occur if you simply typed in file.h rather than using #include). Macros Macro definitions are used to replace subsequent instances of a given word with a different sequence of text. Reasons for doing so include hiding implementation details, reducing the number of keystrokes, and ease in changing constants. Syntax 1: #define identifier token_sequence Syntax 2: #define identifier(id_list) token_sequence Notes: As a matter of convention, identifiers are usually capitalized to emphasize their presence in the code, and defined close to the start of program, or in a separate header file which you #include. The second case allows identifiers in the id_list to be substituted back into the token_sequence. Example:
    // Create a 40 cell array of integers and initialize each cell
    // to its cell number times 2,
    //   i.e. stack[0] = 0, stack[1] = 2, stack[2] = 4, etc

    #define STACKSIZE 40
    #define INITCELL(x) 2*x

    int *stack;

    create() {
        int i;

        stack = allocate(STACKSIZE);

        for (i = 0; i < STACKSIZE; i++)
            stack[i] = INITCELL(i);
    }

Lastly, it's sometimes useful to undefine (i.e. make the compiler forget
about) a macro. The following directive is then used:

Syntax: #undef identifier

Note:
It's perfectly acceptable to undefine an identifier that hasn't been
defined yet.

Conditional Compilation

These directives can add flexibility to your code. Based on whether an
identifier is defined (or not defined), variations of the code can be
produced for different effects. Applications include selective admin
logging and support for multiple drivers (or versions of the same driver).

    Syntax:     #ifdef 
                #ifndef 
                #if 
                #elif 
                #else
                #endif

Note:
refers to an identifier that has been (or could be) defined
by your program, a file you have included, or a symbol predefined by
the driver.

is a constant expression that evaluates to a boolean
condition. The expression may contain any legal combination of the
following:

operators: ||, &&, >>, <<,
+, -, *, /, %,
&, |, ^, !, ~,
==, !=, , =, ?:

parentheses for grouping: (, )
calls of the form: defined(identifier)
and identifiers

#ifdef identifier
can be considered shorthand for:
#if defined(identifier)

#ifndef identifier
can be considered shorthand for:
#if !defined(identifier)

#elif expression
can be considered shorthand for the sequence:
#else
# if expression
# endif

Example 1:

    // Using #if 0 allows you to comment out a block of code that
    // contains comments.  One reason to do so may be to keep a copy
    // of the old code around in case the new code doesn't work.
    #if 0
        // In this case, the constant expression evaluates
        // (or is) 0, so the code here is not compiled

        write(user_name + " has " + total_coins + " coins\n");
    #else
        // This is the alternate case (non-zero), so the code
        // here _is_ compiled

        printf("%s has %d coins\n", user_name, total_coins);
    #endif

Example 2:

// This example is derived from TMI’s /adm/simul_efun/system.c
#ifdef __VERSION
string version() { return “2.7.2”; }
#elif defined(MUDOS_VERSION)
string version() { return MUDOS_VERSION; }
#else
# if defined(VERSION)
string version() { return VERSION; }
# else
string version() { return -1; }
# endif
#endif

Debugging

The ‘#echo’ directive allows you to print messages to the driver’s stderr
(STanDard ERRor) stream. This facility is useful for diagnostics and
debugging.

Syntax: #echo This is a message

Note:
The rest of the line (or end-of-file, which ever comes first) is the
message, and is printed verbatim. It’s not necessary to enclose text
with quotes.

Compiler Specific

This facility performs implementation-dependent actions.

Syntax: #pragma keyword

At this time the following control keywords are recognized:


* strict_types
* save_binary
* save_types
* warnings
* optimize
* show_error_context

Notes:
‘strict_types’ informs the compiler that extensive type checking should
be done

‘save_binary’ informs the compiler to save the binary object;
loading will go faster after a reboot/shutdown since object has been
precompiled

‘save_types’ is saves the types of function arguments for type checking
in objects that inherit this program

‘warnings’ enables the printing of warnings about things the driver thinks
are dangerous or likely to be incorrect.

‘optimize’ directs the compiler to spend a little extra time generating
better code

‘show_error_context’ adds information about where on the line an error
occured to error messages

Text Formatting Shortcuts

This facility makes it easier to format text for help messages, room
descriptions, etc.

    Syntax 1:   @marker
                  
                marker
    
    Syntax 2:   @@marker
                  
                marker

Notes:

    @   - produces a string suitable for write()

    @@  - produces an array of strings, suitable for the body pager

These are used by prepending ‘@’ (or ‘@@’) before an end marker word. This
is followed by your formatted text, as you would have it appear to the user.
The text block is terminated by the end marker word, without the ‘@’
(or ‘@@’). With ‘@’, the text block is processed as if it were a single
string surrounded by quotes and ‘\n’ (newlines) in between the lines.
With ‘@@’, the text block is processed as it were an array of strings,
with each line being a string surrounded by quotes.

Example 1:

        int help() {
            write( @ENDHELP
        This is the help text.
        It's hopelessly inadequate.
        ENDHELP
              );
            return 1;
        }

Is equivalent to:

        int help() {
            write( "This is the help text\nIt's hopelessly inadequate.\n" );
            return 1;
        }

Example 2:

        int help() {
            this_player()->more( @@ENDHELP
        This is the help text.
        It's hopelessly inadequate.
        ENDHELP
              , 1);
            return 1;
        }

Is equivalent to:

        int help() {
            this_player()->more( ({ "This is the help text.",
                  "It's hopelessly inadequate." }), 1);
            return 1;
        }

back to top

Simulated efunctions

There is a mechanism to allow the mudlib to simulate efunctions.  All
simulated efuns must be defined in a special file (the name and location
of which are to be specified in the config file).

When compiling an object and a function call (not a call_other) is found that
has not been defined in the object then the driver
will search for that function in the list of simulated efuns.  If the
function is found in that list, then the driver sets up a call to
that function (as defined in the simulated efun file).

Simulated efuns have many uses.  One is that it is now possible to make major
changes (and even removals) to the behavior of efuns without modifying
the driver (by making a simul_efun having the same name as an efun).  Suppose
you wish to modify the behavior of the move_object() efun.  You could do
so by defining a simulated efun having the same name.  The simulate efun
could perform various restrictive checks and then call efun::move_object().
The efun:: prefix is necessary so that the driver will know you wish to call
the move_object efun and not recursively call the simulate_efun within which
the call to move_object is contained.  [Note that valid_override() in master.c
can be used to conrol which simul_efuns may be overridden via the efun::
prefix].  Simulated efuns are also useful for adding functions that many
different objects may need to call but which aren't appropriate for
inclusion in an inherited file.

Any function in the simulated efun file that is declared static, will
not be callable by functions outside the simulated efun file.

back to top

MudOS LPC Sockets Tutorial
1992 October 20
by Cynosure (Dave Richards)

Minor update 1994 Sept 16 by Robocoder (Anthon Pang)

Note: It is now possible to pass a function pointer anywhere a string
      function name is mentioned in the following.

One of the enhancements added to MudOS between 0.8.14 and 0.9.0 was the
inclusion of Internet sockets in LPC.  It has been an ongoing dream of
the MudOS and TMI researchers to provide more tightly integrated MUDs
communicating over the Internet.  Socket efuns (or LPC sockets) provide
the first level of MUD integration by allowing LPC developers to write
Internet sockets-based applications.  For example, LPC objects already
exist for telnet, remote MUD finger, remote MUD tell, inter-MUD mail
delivery, and participation in the MUDWHO system.

This document is intended as a tutorial on how to use LPC sockets to
write network-based intercommunicating objects.  It is intended for
intermediate to advanced LPC programmers, who already understand the
fundementals of LPC programming, and wish to write network-based LPC
services.

Socket Modes

There are five different modes of communication, or socket modes:
MUD, STREAM, DATAGRAM, STREAM_BINARY, and DATAGRAM_BINARY.  Definitions
for these modes can be obtained by including "socket.h" from the mudlib.

MUD Mode

MUD mode is a connection-oriented communication mode where LPC data types
may be passed across the network to another MUD.  For example, in MUD mode
one could send structured data, like arrays or mappings, across the network
to another MUD which is using a MUD mode socket.  All LPC data types _except_
"objects" and "functions" may be sent and received using MUD mode.

STREAM Mode

STREAM mode is also a connection-oriented communication mode.  It differs from
MUD mode however, in that all data is sent and received as strings.  So,
using STREAM mode one can send streams of data across the network to other
MUDs.  STREAM mode sockets are less powerful in that they do not
transparently send and receive all LPC data types.  However, many
applications like telnet, for example, do not need to send data as
integers, or arrays.  Instead, telnet views data as a stream of characters
going in each direction.

MUD mode sockets are effectively implemented as STREAM mode sockets with
special code to send and receive LPC data types.  Therefore, it behooves
one to only use MUD mode if the application requires this extra data
abstraction.  MUD mode is inherently slower and uses more memory buffer
space than STREAM mode.  Note that when using STREAM mode, there is
no guarantee that the string being sent will arrive all at once;
instead, it may arrive in pieces which the receiving side may then have
to reassemble (the pieces will arrive in order).

DATAGRAM Mode

Unlike MUD and STREAM modes, DATAGRAM mode is connectionless.  No connection
is established between MUDs to transfer data.  Instead, each piece of data
is sent to the destination MUD in a message called a datagram.

Because no connection is estsblished in DATAGRAM mode, it is possible that
the network could lose the DATAGRAM and neither MUD would realize it!  For
example, if TMI sent a datagram to Portals using DATAGRAM mode and the network
lost the datagram, Portals would never receive the datagram and would be
ignorant of the datagram ever being sent at all.  And TMI won't realize the
datagram was lost because no error is received if the datagram is lost.

TCP and UDP

In MUD and STREAM mode, a TCP connection is established between the two MUDs.
TCP is a protocol that will re-transmit data if it detects that data has been
lost.  It uses algorithms that send data, measure how long it takes to get a
reply, wait that long and re-transmit the data until an acknowledgement is
received.  TCP also guarantees that the data packets arrive in order and
are not spuriously duplicated.  (This is a very superficial description of
TCP, but does indicate the sort of work involved in making data transfer
reliable).

DATAGRAM sockets, on the other hand, use a datagram oriented protocol called
UDP.  UDPs send datagrams between MUDs without the overhead of connections,
retransmission, etc.   Now, since DATAGRAM mode is unreliable why would one
want to use it?  Clearly TCP is better because it guarantees that data is
retransmitted if it doesn't arrive, and it deals with all the ugliness that
a network can throw at it.  Simply stated, some applications really don't
care if all data arrives at the other end.  Then why send it?  Okay, okay.
This is a good question, but now is too soon to talk about it.  Just take
it on faith that there is a need for DATAGRAM mode and we can fill in the
details a bit later.

Creating Sockets

Ok, so let's start off by creating a MUD mode socket.  We can write an
object to do this:

    #include "socket.h"

    void
    create()
    {
        int s;

        s = socket_create(MUD, "close_callback");
        if (s < 0) {
            write("socket_create: " + socket_error(s) + "\n");
            return;
        }

        write("Created socket descriptor " + s + "\n");

        socket_close(s);
    }

    void
    close_callback(int s)
    {
        write("socket " + s + " has closed\n");
    }

Let's analyze this object to see how a socket is created. Be forewarned,
we have a long way to go before we can send data on a socket, and creation is
only one step along this trail. So be patient and be sure to understand
each example before moving.

The first thing we do is #include "socket.h". All socket definitions
are contained in socket.h, remember? #defines exist, for example, for
MUD, STREAM and DATAGRAM. Although each name maps to a number, a well
written application will use this name instead; partly because the
you mean to do.

We declare an integer variable s. In many sockets applocations s is used
as an abbreviation for socket. Then we call socket_create() with two
arguments. The first argument is the socket mode (which we discussed above),
and note that we use the synbolic name MUD for MUD mode. The second argument
in the above example is called the close callback function. It is the name
of a function within the object that MudOS will call when the connection is
closed. Callbacks are used often in LPC sockets efuns to notify the
object when important network events occur. Note, by the way, that we could
have passed STREAM or DATAGRAM to socket_create() to create STREAM or
DATAGRAM sockets.

All socket efuns return an exit status or return value. This value indicates
the completion status of the function. By convention all values less than 0
indicate errors or warnings. When an error is returned the application must
decide how to respond to it. In many cases there is no possibility for
success unless the MUD administrator makes changes to local config file or
the MudOS driver itself, so in many cases the application may decide to
just return on failure. In the above example, if an error is returned
(s is less than 0) then we use the socket efun socket_error() to write
an error message on the screen. This is useful during debegging, but should
probably be converted to log_file() calls eventually so the errors can be
logged and fixed.

If socket_create() succeeds, it returns an integer greater than or equal to
0. This integer is known as a socket, a socket descriptor or a file
descriptor. All three names have their origins in UNIX terminology. If
socket_create() returns a value less than 0 then an error has occurred and
no socket has been created. There really aren't any good reasons for
getting an error. The most common errors would be specifiying an incorrect
socket mode (which should not happen if you use the socket mode definitions
in socket.h) and out of sockets. The MUD administrator can configure the
number of LPC sockets that can be used by MudOS. By default, this number
is 16, but should be changed to fit the MUD's requirements. Increasing this
number will make more LPC sockets available. Note, that each active LPC
socket takes away one socket that could be used to handle a player login
or an open file. If the mud needs to handle many players and many open
sockets simultaneously, the machine adminstrator may need to be convinced
to increase the maximum number of open file descriptors allowed to a process.

All socket objects should be careful not to "lose" sockets. Sockets
are not like other LPC objects, there are only a finite number of them.
So in the above example, if we were able to create a socket, we close it
afterwards. Losing track of a researce is called "leaking". Socket
leaks occur when object create sockets, use them for a while and then
stop using them without closing them so that they can be used by other
objects. When an object is destructed, all LPC sockets are automatically
closed. One other thought about sockets: each socket in MudOS has it's own
unique socket descriptor (or socket number). So if one object created a
socket, and another created a second socket, neither object would receive
the same socket descriptor. Object may use this knowledge to their advantage.
It is common, for example, to use the socket descriptor as an index into
a mapping that notes various information for each open socket. Remember,
however, that once the socket is closed, it becomes available for re-use
by other socket_create() calls.

Client/Server Model

Before continuing with the rest of the socket efuns now is probably a good
time to stop and review some basic networking concepts. Connection-oriented
communication is normally described in terms of the client/server model. In
this model each connection has a client and a server. The client is the
subject that initiates the connection and solicits some sort of service.
The server on the other hand waits for connection requests from a client,
and when they arrive provides the service requested. Ftp, for example,
operates this way. A user initiates a request by connecting to a server.
The server than acts on the requests of the client. A server
is unlike a client however in that is may be serving more than one client
at any point in time.

MUD and STREAM mode sockets use the client/server model. The client and
server each using slightly different calls to establish a connection.
Later we will discuss the peer-to-peer model when discussing DATAGRAMS,
which is slightly different than the client/server model and uses an
again slightly different method for establishing communication.

It is possible to have many different services available. Each service is
identified by a "well-known port". A port is simply an integer in the
range 1 to 65535. Most MUDs, however, can only use the range 1025 to
65535 because the first 1023 are reserved for applications like telnet,
ftp, etc that are standardized. In order for a client and server to
cummunicate the server my first create a socket, bind to a well-known port
and listen for connection requests. The client on the other hand must
create a socket and connect to the well-known port. The client connects
to the same port as the server has bound and listened on. That is why
it is called a "well-known" port. Because clients know the port a priori
and can therefore connect to it. In the Internet Request for Comments
documentation, for example, the port number is actually specified with
the text of the standard.

We will continue our discussion then in the order that socket efun
calls would normally be executed to establish a connection between the
client and server. The server must do some preperation before the
client can initiate a request, so we will start with the server.

Binding to a Port

After the server has created a socket with socket_create() (and has verified
that the return value is greater than or equal to 0) the next logical step
is to bind to a port. This is done with socket_bind(). Let's add some more
code to the example above. First let's declare a new integer variable
called error, which is used to hold the return value from socket_bind().

    int error;

// Now let's add a call to socket_bind():

    error = socket_bind(s, 12345);
    if (error != EESUCCESS) {
        write("socket_bind: " + socket_error(error) + "\n");
        socket_close(s);
        return;
    }

This should be added above socket_close(s). What does it do? Well
the first argument is no suprise, it's just the socket descriptor we
got back from socket_create(). We will have to pass s into every socket
call from now on so that MudOS knows which socket we are referring to.
Remember servers can and often do service more than one client socket at
one time, so we need to be able to keep them straight. The second argument is
simply the port number. Recall, it should be in the range 1024 to 65535.
(Actually 0 is legal too, but 0 will be discussed a bit later.)

After calling socket_bind() we check the return value to see if an error
occurred. In this case, however, we compare against EESUCCESS. In most
cases (excluding socket_create()) EESUCCESS indicates that the socket efun
completed successfully. Like socket_create() above, if an error is returned
we call socket_error() to display the error as a string. After writing the
error we simply return, right? Wrong! We discussed leaks above. If we
were to return, then an object would exist that is no longer using a socket
but stops others from using it. If we decided we cannot use the socket
anymore CLOSE IT so others can. Once socket_create() has been called and
until socket_close() has been called the socket remains open. So remember
to be a good socket citizen and close sockets when you are finished.

socket_bind() is notorious for returning EEADDRINUSE. What does it mean?
If one socket binds to port 12345 and another socket attempts to bind to the
same port (i.e. 12345) the second socket will fail to bind. This is simple
enough to understand. Once a socket binds to a port that socket owns that
port. Other attempts to bind to the same port will fail with EEADDRINUSE.
This is a very common error and can occur if two folks attempt to run the
same server demo, for example. The correct resolution to this problem is
to 1) determine if the same service is being started twice, in which case,
DON'T, once is fine, or 2) more than one developer has chosen the same
port number for multiple services. This won't work. One way to avoid this
is to have one port administrator that assign ports. Unfortunately, since
networks are generally not isolated, this port assignment must be agreed
upon by all MUDs that you intend to communicate with.

Security

Before going on and to satiate those with crimical intent we should answer
a few questions about invalid sockets descriptors. What happens if we were
to pass in a bad socket descriptor value, just to be mean? Don't worry MudOS
will catch you doing it and tell you so. For example, if you passed in
a value that was less then 0 or greater or equal to the total number of
possible sockets in the driver, then MudOS would know you were lying though
your teeth and would return EEFDRANGE. Now if you were more sneaky you
might try to pass in a legal socket descriptor but one that was not
currently is use. MudOS would catch you again and would return EBADF. Ok
sneak that you are, you found out about a socket that in use by some other
object. What then? Well there is a 2-level security system built into
LPC sockets.

The first level of security uses the master object to validate which
objects can and cannot use sockets. It might make sense on some MUDs, for
example, for some developers to have access to LPC sockets and some others
not too. Or perhaps one developer is abusive of network priviledges and
should be banned from socket use. (In the latter case such a developer
should probably asked to leave.) To enforce such a policy, MudOS invokes
a function called valid_socket(). valid_socket() should return 0 or 1
indicating whether the requested socket operation should be allowed.
If no valid_socket() function exists, then the value 0 is assumed and all
LPC socket access is *denied*. On most MUDs however master.c would
contain the following valid_socket().

   int
   valid_socket(object eff_user, string fun, mixed *info)
   {
       return 1;
   }

The 2nd level of security is more rigid and is used to stop one
object from interfering with another object. When a socket is created
the socket becomes "owned" by the object that called socket_create().
Each time a socket efun is called the calling object is compared to the
owner object. If they are not the same, then the socket efun call is
aborted. Thus, heinous code like:

    int s;

    for (s = 0; s < 100; s++)
        socket_close(s);

will not succeed in closing all sockets on the MUD. It will close all
sockets owned by that calling object, but all other sockets are
protected by tge 2nd-level security policy.

In either case if the 1st or 2nd level security policy is violated, then
EESECURITY is returned to the caller indicating that the socket efun was
aborted because of such a violation. If you encounter this error when
writing LPC socket code the mostly like reason would be that you passed in
the incorrect socket descriptor. This happens.

Listening for Connections

Once a socket has been created and a port has been bound, a server must
begin listening for connections. This is done with socket_listen().
Like socket_bind() the first argument is the socket on which to listen.
The second argument is the "listen callback" function. Recall the
close callback function from socket_create()? socket_listen() specifies
a function within the object that will be called when a connection
request is received from a client. Within the listen callback function
a server can either accept the connection from the client or close it.
In most servers there is really no good reason for ever just closing a
connection. It is considered rude and should be avoided. If the
client and server implement some sort of authentication protocol
(i.e. password checking) the server should return some indication as
to why the socket is being closed. This is more a question of style,
of course, but it is difficult to debug a problem with a client or server
when a connection is made then dropped immediately. If you must do this,
be sure to log some indication as to why in a logfile so that an administrator
or developers can determine the cause and resolve the problem.

The following code starts listening for connection requests on a socket
that has been created and bound to a port.

    error = socket_listen(s, "listen_callback");
    if (error != EESUCCESS) {
        write("socket_listen: " + socket_error(error) + "\n");
        socket_close(s);
        return;
    }

It is really just more of the same code, right? We call the socket_listen()
efun, check the return value for success, if an error occurs write an
error message out which includes a description of the specific error,
close the socket because we're done with it and return. In reality much
of the code necessary in sockets applications follow this pattern.

Now obviously the next thing to do is discuss the listen_callback function,
right? Right. But we won't. Instead we'll change gears here and look at
the client code for a bit. The reason for this is simple. Before a client
can initiate a connection to a server the steps we have discussed now for
the server must have occured. Until the client *does* initiate a connection
though, no more code will be executed within the server. So it makes sense
to digress and discuss the client for a moment.

Clients

So far we have discussed a connection from the server's perspective. Now
let's back up and walk through the client. Just like the server a client
must call socket_create() to create a socket. Since a client does not
intend that another client connect to it there is no need to bind the
port to socket. Does this mean that it cannot do so? No. It is possible
for either a client or server to bind to a port.

But why would a client wish to do so? Well the truth of the matter is this,
every socket must be bound before a connection can be established. Every one.
However, since clients don't really care what port they are bound to, a
special bind is used. It was alluded to above, we're just catching up to it
now. If a client calls socket_bind() with a second argument of 0, this
indicates that the caller doesn't care what port is selected, just pick
any one that is available. And this makes it easy for a client. If the
caller did bind to a specific port, what happens if another client is already
bound to it? The bind fails. So why not let the system do the work of
choosing the port?

Now there is one more trick up our sleeve, however. The operating system
is pretty smart. It knows whether a sosket is bound or not. It knows when
you do a connect (It knows when you've been bad or good). So, seeing how
common it would be for a client to wish to connect to a server the designers
of the 4.2/4.3BSD networking system put in a neat feature. If you connect
on a socket, and the socket is not yet bound, the system will do a
socket_bind(s, 0) for you automatically! In fact if you read BSD networking
applications you will notice that almost no sockets that are used to
initiate connect requests on ever bother doing the bind call. Laziness is
bliss.

Initiating a Connect

Once a client has created a socket with socket_create() and optionally
bound to a port with socket_bind(), can then called socket_connect() to
initiate a connection request. socket_connect() requires four parameter:
1. the socket on which the connection to be performed, 2. the address and
port to connection to, 3. the read callback function, and 4. the write callback
function. There are several new concepts we need to cover so let's go
slowly and review each argument in tern.

The first argument is old hat by now. It is just the socket or (socket
descriptor) that was returned from socket_create(). The second argument,
however, is new and exciting. It is a string representating of the address
and port to which we want to connect. Rather than waste your time talking
about Internet standard dot notation, and address classes, etc, lets just
say this about Internet (or IP) addresses. You have probably seem them
before. They are 4-byte addresses, with each byte being separated by a ".".
For example, the Internet address for eng3.sequent.com is 138.96.19.14.
There are many ways to find the IP address for a machine. The mud list
supplies the host name and IP address for the MUD machine (which do change
from time to time). The UNIX ping and nslookup commands can be used, as well.
From this point on, we will just assume you can determine the IP address
for a destination machine. One thing to think about though is that in
general most applications to not embed IP addresses within the code. It is
more common that the user would provide tha address as an argument to the
application, so don't panic.

We discussed ports above when we talked about binding. The port that
you specify to socket_connect() is the same "well-known" port number that
the server bound to above. That's the whole point, by the way, of binding.
The server and client rendezvous so to speak at the port. So how should
the second argument appear? Let's assume we wanted to connect to
eng3.sequent.com port 12345. We would write the following additional code:

    string address;

    address = "138.95.19.14 12345";
    error = socket_connect(s, address, "read_callback", "write_callback");
    if (error != EESUCCESS) {
        write("socket_connect: " + socket_error(error) + "\n");
        socket_close(s);
        return;
    }

Notice the address variable. It is a string and we asssign it the
Internet address and port number with a space in between to seperate
them. This is the format that socket_connect() expects addresses and
ports to be specified.

So what are the read and write callback functions? Well we have already
talked about callbacks in general. MudOS calls these function when some
network event occurs. In these cases, MudOS calls the applications when
data becomes available to read (i.e. read callback) or that it is now
okay to write data (write callback). We will discuss how these callbacks
should work in just a bit.

The point is, once socket_connect() is called, the client initiates a
connect request to the server. Because of the way MudOS works this is
all we can do for now. The network has work to do. We have just requested
the network to send a connect request to a remote machine. That remote
machine will then inform the application that a connect request has
been received and that application will decided what to do about it. The
point is, all of this takes time. And while all this is going on MudOS
has other work to do. So rather than stop MudOS from doing useful work,
MudOS simply return EESUCCESS. Does this mean that the connection has
been made? No. Does it mean the remote machine will connect with us?
No. Do we even know if the remote machine is up? No. Do we know
anything? Yes, a little. We know that three possible things can happen
in the near future. 1. the read callback function could be called
indicating the arrival of data from the remote application, 2. the write
callback could be called indicating that it is okay to send data, or 3. the
close callback function (that was provided way back in socket_create())
could be closed indicating that the remote machine did not accept of
connection request.

Before going one step further though, make sure this is all clear.
socket_connect() tells TCP to start a connection request. When
socket_connect() returns we don't know anything about the state of
the connection as of yet. MudOS will eventually call back one of the
functions so we know what happened. This sort of programming is called
asynchronuous programming. It's opposite is known as synchronous
programming. In synchronous programming your application would wait
until the connection is either accepted or closed before returning.
But we do not have the leisure of synchronous programming in MUDs because
while we wait for the network, other things are being ignored which should
not be. So to be fair to everyone we use this asynchronous model. Which is
not really that complicated once you get the hang of it.

Of course, in the above discussion we assume you check the return value
from socket_connect() for EESUCCESS. If socket_connect() does not return
EESUCCESS then the connection request failed and no callbacks will be
called. A common mistake is to forget to check the return value and assume
one of the callbacks will eventually be called. Be careful. As in all cases
above if the connection request fails then be write an error message out to
the display, close the socket so it can be re-used and return.

Now we wait. Some time in the future either the read, write or close
callback will be called...

Accepting a Connection

Meanwhile (back at the server) a connection request is received from the
client. When this occurs our listen callback function will be called.
This function was specified in the socket_listen() function, remember?
MudOS calls the listen callback with a single argument, that being the
socket descriptor of the socket that, socket_create(), socket_bind() and
socket_listen() was done on. This is useful if an object is listening
on multiple sockets at the same time.

The responsibility of the listen callback function is too either
accept the connection or close it. In general though, as was mentioned
above, we always accept incoming connection requests. The following
code accepts an incoming connection request:

    void
    listen_callback(int s)
    {
        int ns;

        ns = socket_accept(s, "read_callback", "write_callback");
        if (ns < 0 && ns != EENOSOCKS) {
            write("socket_connect: " + socket_error(error) + "\n");
            return;
        }
    }

Okay, we know what s is, right? It was passed as an argument to us.
It is the socket on which the connection indication came in on. So what
is ns? Aha! ns is an abbreviation for new socket. When a connection is
established a new socket is created for that connection. So what is s used
for? It is used to accept connections on. s will never be used, for
example, to actually send or receive data. Instead, it is used to tell
the socket application when connection requests arrive. ns, however, is
a socket that can communicate with the client. The server can send and
receive data on it etc. Make sense?

Now if you recall, we passed read and write callback function names to
the socket_connect() efun. We are doing the same thing here.
We haven't discussed them yet so don't worry, we'll get there. For now
just realize that the read and write callbacks are used for the same
purpose for socket_accept() as they are for socket_connect(). And don't
get too impatient we are almost ready to discuss them in gory detail.

It's important to note that our error handling is different here than in
other cases. If socket_accept() returns a value greater than or equal to
0 then the efun succeeded just like socket_create(). This means that the
connection has been established! This is major progress. However if it
did not succeed there is one case that is worth making an exception for.
Recall from way, way back that there are a limited number of sockets that
MudOS can use? Well, what would happen if all sockets are in use when a
connection request arrived? Well simple, stated the connection could not
be accepted because there are no sockets to accept it on. This is a shame
but it can happen. If it does EENOSOCKS is returned. This is more of
a warning than a really bad error. Sure the connection was closed because
not sockets were available, but if some other socket becomes free a new
connection could be established in the future, so this is an example of
a temporary error. In this case, it may make sense to just return.
However, in all other cases, the listen socket is closed. This means that
no new connections can be accepted, until the server is restarted. As
a result be sure to display an error message so an administrator knows
to restart the server!


Flow Control

Before talking about data transfer which is sort of the climactic
section anyway, we need to discuss another paradigm. If we were
to look at networking technology today networks run at several orders
of magnitude of difference in performance. FDDI, for example, which is the
fiber opitc network standard of today runs at around 80 million bits per
second, IBM Token Ring runs around 16 million bits per second, Ethernet
around 10 millions bits per second, high-speed syncronous serial runs at
about 56 thousand bits per second and finally consumer asynchronous
modems run from 1.2 thousand to 14.4 thousand bits per second. These are
raw data rates, and one certainly cannot expect to use the entire
bandwidth of the various media. The point is this, if you ever expected
to find a hetrogeneous operating environment, networking is it. The same
protocols operate correctly at various data rates, and with different network
technologies. This is what the Internet model is all about.

Because of the variety in networks today it is difficult to make assumption
about how long things might take on networks. Recall from about that when
we initiated a connect request from a client we checked to be sure that
socket_connect() return EESUCCESS and then just returned and waited? This
was not just a cute metaphor. In reality we were. On an Ethernet we
probably waited about 3/1000s of a second for a reply, not really all that
long. So short in fact, we could have probably just hung around for the
response and delayed further processing within MudOS. But what if the
reply were to take several seconds, which is is likely to do on a SLIP or
Point-to-Point link? We don't know a priori how long things will take and
so must be prepared for the worst when dealing with networks.

There really is a point to all of this discussion. Computers are pretty
fast and are getting faster. Desktop computer can runs millions of
instructions per second. At best a similarly priced modem for such a
computer could run at around 19.2 thousand bits per second. That works
out to less than 2 thousand bytes per second. So if we compare the computer
speed to the network speed we find a vast difference in speed. The
conclusion one should reach is this: A computer can generate data much
faster than a network can send it. Therefore I could write a program
that sat in a loop and pounded the network with data, and it's very likely
that I would eventually run into a case where I had data ready to send and
the network is not ready to accept it. What should we do in this situation?
Well if we follow our previous example (i.e. socket_connect()) we would just
wait until the network is ready for more data. And so we do.

Realizing the difference in speed between computers and networks the
inventor of network software have designed the following kind of interface.
Each socket has a reasonably-sized memory buffer (typically around 4k
bytes of data) that is used to temporary hold data while is waits for the
network to send it. This temporary buffer will eventually fill, of course,
if we were to send data faster than the network can handle. When it does the
socket is said to be "flow controlled". This mean we are told that there is
no more room in this temporary buffer to hold any more data, so we should
stop sending more data. This flow controlled notion affects is directly
when writing sockets code. We have to be smart enough to send when we
can and wait when we cannot send. This may sound complicated; luckily
we can reduce this down to a few very simple rules.

Remember we said that socket_connect() generates a connection request and
returns immediately without waiting for the reply? This is true it does.
But what we didn't mention back then is that during the connection request
your application cannot send any data. This makes sense right? If the
connection has not been established then how can data be sent. This is
like dialing a phone number and starting to talk while the phone rings!
Well if we cannot send data after socket_connect(), when can we. We talked
about this before, remember? Once the connection is established then
either the read, write or close callback will be called.

So if we want to send data what should we do? Wait for the write callback
procedure! Simple enough, right? Let's forget about the close callback
for the moment because we know why it gets called and it not important any-
more. Let's just focus on the read and write callback functions. We said
when the connection has been established either the read or write callback
function will be called. Well gee, if we are waiting for the connection
to come up so we can send data and our read callack gets called what should
we do, send the data? No. Because no matter what, once the connection
comes up the write callback is guaranteed to be called at least once.
In other words, there are two directions of communcation the read direction
(data coming across the network towards us) and the write direction (data we
send out the network towards the other MUD). If we stick to our guns
and think of each direction as seperate we will avoid confusion.

Now remember the term flow-controlled? It means that we cannot send any
more data because we are waiting for the network to catch up. Well
after a connection request (i.e. socket_connect()) we are flow-
controlled. Once the connection has been accepted by the server then
our write callback function is called and we become, not flow-controlled!
This is our cue! Send data! Make sense?

Ok, so we take our chance and start sending data like mad. The network
sends this, and this, and this too. At some point the buffer inside is
going to fill up and we are going to become flow-controlled again. What do
we do then? Same as before. Wait for our write callback function to be
called again so we can start sending more data. Sending on a network is
like send bits of data in bursts. We send, we wait, we send some more.
A correctly written socket application then is one who keeps track
of whether it can or not. And only sends when MudOS says it can, and
waits when MudOS says it cannot.

Before you go off and get frustrated with LPC sockets, remember this: the
rules for flow control are not difficult to understand, but violating them
can end in disaster. Make sure you understand this flow control model. It
is fundamental to the asyncrhonous programming model. If it does not make
sense then please re-read this section or ask a sockets-savvy friend for
help, because this is very important.

Sending data

Okay, now that we understand the constraints within which we live, it's time
to discuss actually sending data. It's been a long time in coming, but we
have convered a lot of important information along the way.

After a client's write callback is called the client is no longer
flow-controlled, which means it can begin writing data. What about the
server? Is the server flow-controlled after doing socket_accept()? This
is a good question. The answer is no, it is not. This is another difference
between clients and server. The client must wait for a write callback
before it can begin sending data, the server can begin as soon as the
connection has been accepted. Ignoring this final detail though, there
is no difference between client and servers send and receiving data. Both
client and server use the same socket efuns in the same way.

So let's do it, let's send a number in MUD mode.

    error = socket_write(s, 0);

Incredibly enough that's all it takes to send the LPC integer 0 to
the other MUD. One could do:

    error = socket_write(s, "Hello you other MUD1");

to send a hello message as a string to the other MUD. In fact in MUD mode
you can send any LPC data type except objects. This means arrays, mappings,
integers, etc. This is very powerful indeed! Ok we sent it, but what happened
on the other side so they can receive it? Remember the read callback
function, we specified it in the socket_connect() and socket_accept()
efuns? The read callback function is called when the network delivers to
the data to the socket. For example:

    void
    read_callback(int s, mixed message)
    {
        write("Received " + message + "\n");
    }

would write the receive data! The read callback then is used by MudOS
to tell an object when new data arrives. In the above example we used
a second parameter of mixed. This is because in MUD mode any data type
can be sent across the network. It is the object's responsibility to make
sure the object type is correct. In fact, once you are able to send and
receive data correctly, you have solved the immediate problem of communication
and have opened up a whole new problem called protocol engineering. This
involves designing networking protocols that are reliable and can
interoperate with many type of computers, but that unfortunately is far
beyond the scope of the tutorial. Alas.

So have we finished with socket_write()? I hope you don't think so.
You should have noticed that we didn't check error after calling
socket_write(). Why is this? Well to be blunt, because there are four
different classes of return codes that socket_write() can return and I
figured we'd ease into the nitty gritty details. So here we go.

There are four things socket_write() can return. 1) because it sent
the data along and everything is just fine, 2) the data has been saved in
a buffer and will eventually be sent, but no more data can be accomodated
at the moment, 3) the data has not been saved in a buffer and will not
be sent since no more data can be accomodated at the moment, and
4) socket_write() is very confused and doesn't know what to do now. In the
first case, socket_write() has sent the data and is ready for more. It will
not call the write callback function because there is no need to, we are not
flow-controlled. In other words, we should remember that it is still okay
to send data. In the second case the data will be sent, it's sitting in a
memory buffer ready to be sent when the network can send it, but the buffer
is now full. Which means we are now flow-controlled. It would be
inappropriate for us to try to send more at this point, so we should remember
we cannot send any more right now. When the network empties the memory buffer
the write callback function will be called and we can then start sending data
again. In the third case, the data couldn't be sent at that moment,
possibly due to socket traffic or network congestion. We are not flow-
controlled so the write callback function must be called explicitly, to
attempt resending the data. A call_out() is a better choice here over
a direct function call since the delay gives the system a chance to recover,
reduces the possibility of max eval'ing, and better simulates a callback.
In the final case, some error has occurred either on the network connect or
within the operating system such that the write can not be performed. In
that case, however, it is likely nothing can be done to rectify the problem.
In general, the best thing to do is simply close the connection. In general,
this never happens.

Okay so much for the abstract, let's look at the specifics. socket_write()
returns EESUCCESS in case (1) above. This means that further writes to the
socket are still possible. If socket_write() returns EECALLBACK, this
indicates that the data has been buffered for output, but that further writes
should be suspended until the write callback function is called. Conversely,
if socket_write() returns EEWOULDBLOCK, this indicates that the data has
not been buffered for output, and that the write callback function must be
called again manually (to resend) before further writes are attempted.
EEALREADY means that the object has violated the flow control model,
i.e. a write was done while the socket was flow-controlled. In this event,
the data is *not* buffered and the caller should again wait for the write
callback function. Of course, well written application will not see
EEALREADY. Any other return value should probably be interpreted as a fatal
error and the socket closed.

int socket_write(int, mixed, string|void);
int socket_release(int, object, string);
int socket_acquire(int, string, string, string);
string socket_address(int);
void dump_socket_status(void);

back to top

* The LPC for loop:

The LPC for loop is also identical to that provided by C.  Syntax is as
follows:

for (expression0; expression1; expression2) {
    statements;
    ...;
}

Expression0 is evaluated once prior to the execution of the loop.  Expression1
is evaluated at the beginning of each iteration of the loop.  If expression1
evaluates to zero, then the loop terminates.  Expression2 is evaluated at
the end of each loop iteration.

A 'break' in the body of the loop will terminate the loop. A 'continue' will
continue the execution from the beginning of the loop (after evaluating
Expression2).

A typical usage of the for loop is to execute a body of code some
fixed number of times:

int i;

for (i = 0; i < 10; i++) {
    write("i == " + i + "\n");
    write("10 - i == " + (10 - i) + "\n");
}

back to top

* The LPC function (or method):

The LPC function is similar but not identical to that provided by C
(it is most similar to that provided by ANSI C).  The syntax is as follows:

return_type function_name(arg1_type arg1, arg2_type arg2, ...)
{
    variable_declarations;
    ...;

    statements;
    ...;
    return var0;
}

Note that var0 must be of return_type.

If a function doesn't need to return a value, then it should be declared
with a return_type of "void".  E.g.

void function_name(arg1_type arg1, ...)
{
    statements;
    ...;
}

Invoke a function as follows:

function_name(arg1, arg2, arg3, ...);

You may invoke a function in another object as follows:

object->function_name(arg1, arg2, arg3, ...);

or:

call_other(object, function_name, arg1, arg2, ...);

back to top

* The if else statement:

LPC's if statement is identical to that provided by C.  Syntax is as follows:

    if (expression)
        statement;

Alternately:

    if (expression) {
        statements;
    }

Alternately:

    if (expression0) {
        statements;
    } else {
        statements1;
    }

Alternately:

    if (expression0) {
        statements0;
    } else if (expression1) {
        statements1;
    }

The number of else clauses is not explicitly limited.

- - - - -

Another favorite programming construct is the ? : operator, which also
operates identical to C.  The syntax is:

    expression0 ? expression1_if_true : expression2_if_false

In some cases, ? : is an shorter way of expression constructs such as:

    if (expression0)
        var = expression1;
    else
        var = expression2;

which can be equivalently translated to:

    var = expression0 ? expression1 : expression;

back to top

The LPC #include directive:

Syntax: #include 
Alternate: #include "file.h"

Note: the '#include "file.h"' form looks for file.h in the current directory.
The '#include ' form looks for file.h in one of the standard
system include directories (on TMI these directories are /include and
/local/include).

For those that know C, the LPC #include statement is identical to C's
#include statement.  For those that don't know C, the #include statement
is a way to textually include one file into another.  Putting a statement
'#include "file.h" in a file gives the same effect as if you had simply
typed the contents of file.h directly into the file at the point where you
had the #include statement.  Included files are recompiled each time the
object that include's them is recompiled.  If the included file contains
variables or functions of the same name as variables in the file doing
the including, then a duplicate-name error will occur at compile time
(in the same way that the error would occur if you simply typed in file.h
rather than using #include).

back to top

The LPC inherit statement:

Syntax: inherit pathname;

where pathname is a full path delimited by quotes (e.g. "/std/Object").

The 'inherit' statement provides the inheritance capability (a concept from
object-oriented programming) to LPC objects.  Inheritance lets an object
inherit functions and variables from other objects.  Because the MudOSdriver
internally stores global data and compiled code separately, many different
objects can use inheritance to share the same piece of compiled code.  Each of
these objects will have its own local copy of any global variables defined
by the object.  Suppose that two object A and B inherit object C.  Recompiling
object either of A or B will not cause C to be recompiled.  However, it will
cause any global variables provided by C to lose whatever data they had
(remember that A and B each have their own copy of the global variables
provided by C.  Thus updating A will not effect the global variables of B
(even those provided by C) and vice versa).

Suppose object A inherits object B.  Object A may define variables and functions
having the same names as those defined by B.  If object A defines a function
of the same name as one defined by B, then the definition provided by A
overrides the definition provided by B.  If A wishes to access the definition
provided by B, then it may do so.  For example suppose that object A defines
its own function named query_long and yet wishes to call the query_long
function provided by the /std/Object.c object.  Then A may refer to the
query_long in Object.c as Object::query_long().  If A defines a variable
of the same name as a global variable defined in B, then the only way that A
can access that variable is via functions provided by B.  If B defines
a global variable that is not declared in A, then by default A may use that
global variable as if the global variable were defined in A (assuming B does
not choose to restrict access).  Note: if object B is recompiled, object A
will continue to use the old version of object B until object A is also
recompiled.

Multiple inheritance is allowed.  That is, an object may inherit more than
one other object.  Suppose special.c inherits weapon.c and armor.c and that
both weapon.c and armor.c each provide their own version of query_long().
We may assume that special.c wants to sometimes act like a weapon and
sometimes act like armor.  When special.c is to look like armor it
can use armor::query_long() and when it is to look like a weapon it
can use weapon::query_long().

See the tutorial named 'types/modifiers' for more information on how
inherited objects may hide data and function definitions from objects that
inherit them.

back to top

* The function prototype:

The LPC function prototype is very similar to that of ANSI C.  The
function prototype allows for better type checking and can serve as
a kind of 'forward' declaration.

return_type function_name(arg1_type arg1, arg2_type arg2, ...);

back to top

* The switch statement.  The LPC switch statement is nearly identical to
the C switch statement.  The only real difference is that the cases of
the LPC switch may be strings as well as integers.  Syntax is as follows:

switch (expression) {
    case constant0 : statements0;
        break;
    case constant1 : statements1;
        break;
    default : statements2;
        break;
}

The switch is a replacement for the chained if else if else if else
construct.  The above switch is equivalent to:

tmp = expression;
if (tmp == constant0) {
    statements0;
    ...;
} else if (tmp == constant1) {
    statements1;
    ...;
} else {
    statements2;
    ...;
}

The main difference between the switch and the if statement is that if
the "break;" statement is ommited from the end of a particular case,
then the statements in the next case will be executed as well.

back to top

The LPC while loop:

LPC's while loop is identical to that provided by C.  Syntax is as follows:

while (expression)
    statement;    

where statement may be replaced by a block of statements delimited by
matching curly brackets.  For example:

while (expression) {
    statement0;
    statement1;
}

The statements inside the body of the while loop will be executed
repeatedly for as long as the test expression evaluates to non-zero.
If the test expression is zero just prior to the execution of the loop,
then the body of the loop will not be executed.  A 'break;' statement
in the body of the loop will terminate the loop (skipping any statements
in the loop that remain to be executed).  A 'continue;' statement
in the body of the loop will continue the execution from the beginning
of the loop (skipping the remainder of the statements in the loop for
the current iteration).

int test(int limit)
{
    total = 0;
    j = 0;
    while (j < limit) {
        if ((j % 2) != 0)
            continue;
        total += j;
        j++;
    }
    return total;
}

The results of this code fragment will be to sum all of the even numbers
from 0 to to limit - 1. 

back to top

parse error
Variable  not declared !
Illegal LHS
Illegal RHS
Undefined function 
Wrong number of arguments to 
syntax error
Illegal character (hex 2e)
Illegal character (hex 5c)
Illegal character constant
Redeclaration of function 
End of file in string
Function  undefined
Newline in string
Illegal terminator
Text block exceeded maximum length
Bad arg 1 to 
Return type not matching: 
Cannot #include 
Could not load description for 
Indexing on illegal type
Bad type argument to .+ 16 4
Casts are only legal for type mixed, or when unknown: 
Redefinition of #define 
Bad argument number  to : 
Invalid simulated efunction 
Missing type for argument
Bad type for argument  (  vs  )
Illegal to redeclare local name
Bad argument 1 type to efun 
Illegal to redefine 'nomask' function 
Must return a value for a function declared: 
Too many arguments to buffer
Internal error in 
Divide by zero in constant

back to top

2D arrays can be done in LPC, quite simply.  Just treat them as an array of 
arrays.  For example,
 
   a = allocate(10);
   a[0] = allocate(10);
   a[1] = allocate(10);
   ...etc...
 
Then you can reference array 0, element 0, via
 
   a[0][0]
 
You can't declare an array of more than 1 dimension (using the type * 
notation, if you have type checking on), but you can have an array of more 
than one dimension.  If you have type checking on, you will probably have
to declare them as type mixed.
 
This also works:
 
   mixed a;
   a = ({ ({ 1, 2, 3 }), ({ 1, 2, 3 }) });
 
In the above example, a[0] would be ({ 1, 2, 3 }), and a[0][2] would be 3.
 
Or this:
 
  mixed a;  
  a = ({ 0, 0, 0, 0 });  /* just to get the array to size 4 */
  a[0] = ({ 1, 2, 3 });
  a[1] = ({ 1, 2, 3 });
  ...etc...
 
John Price a.k.a. Raistlin

back to top

'buffer' is a cross between the LPC array type and the LPC string type.  
'buffer' is intended as a way to conveniently manipulate binary data.  
'buffer' is not zero-terminated (that is, it has an associated length).  A 
'buffer' is an array of bytes that is implemented using one byte per 
element. buf[i] = x and x = buf[i] are allowed and do work.  sizeof(buf) 
works. bufferp(buf) is available.  buf[i..j] should work as well. buff = 
read_buffer(file_name, ...) (same args as read_bytes). also 'int 
write_buffer(string file, int start, mixed source)', buf = buf1 + buf2; 
buf += buf1, buf = allocate_buffer(size). The socket efuns have been 
modified to accept and return the 'buffer' type.   (STREAM_BINARY (3) and 
DATAGRAM_BINARY (4) modes.)

back to top

MudOS LPC now provides support for the floating point type.  Declare
variables like this:

float pi;

In general the same operations are supported for floats as are for integers.
Floating point constants may contain decimal points e.g.

pi = 3.14159265;

The LPC float type is based on the single precision floating point type
provided by C.  On most machines this will give about seven (7) digits
of precision (in base 10).

back to top

MudOS has a variable type named 'function'.  Variables of this type may
be used to point to (object, function) pairs.  Here is an example usage:

void
test(string arg)
{
    write(arg + "\n");
}

void
create()
{
    function f;

    f = (: this_object(), "test" :);
    (*f)("hello, world!");
    write("functionp(f) == " + functionp(f) + "\n");
}

Note, (*f)(args) is internally translated to obj->func(args) where
f == (: obj, func :).  In (: obj, func :), obj and func may be any
type allowed by call_other(obj, func).

(: "hi" :) makes a function pair that is equivalent to (: this_object(), "hi" :)

Note that:

f is the same as (: f[0], f[1] :)

Author: Truilkan, December 1992

back to top

Types can be used in four places:
 
 Declaring type of global variables.
 Declaring type of functions.
 Declaring type of arguments to functions.
 Declaring type of local variables in functions.
 
Normally, the type information is completely ignored, and can be regarded 
purely as documentation. However, when the basic type of a function is 
declared, then a more strict type checking will be enforced inside of that 
function.  That means that the type of all arguments must be defined, and the 
variables can only be used to store values of the declared type.  The 
function call_other() is defined to return an unknown type, as the compiler 
has no way of knowing the return type.  This value must be casted (when 
strict type checking is enabled).  Casting a type is done by putting the type 
name inside a pair of '(' and ')'.
 
An example when querying the short description of an object:
 
  (string)call_other(ob, "short");
  ...or...
  (string)ob->short();
 
When a function is compiled with strict type testing, it can only call other
functions that are already defined.  If they are not yet defined, prototypes 
must be used to allow the current function to call them.
 
An example of a prototype:
 
  string func(int arg);
 
Note the ';' instead of a body to the function.  All arguments must be given
by names, but do not have to have the same names as in the real definition. 
All types must of course be the same.
 
There are two kinds of types.  Basic types, and special types.  There can be 
at most one basic type, but any number of special types assigned to a 
variable/function.
 
The strict type checking is only used by the compiler, not at runtime.  So,
it is actually possible to store a number in a string variable even when 
strict type checking is enabled.
 
Why use strict type checking?  It is really recommended, because the compiler
will find many errors at compile time, which will save a lot of hard work. It
is in general much harder to trace an error occuring at run time. 
 
The basic types can be divided into groups.  Those that are referenced by 
value, and those that are referenced by address.  The types int, string,
and float are referenced by value.  The types mapping, function, object, 
and pointers (' *') are referenced by address.  If a value of this type 
is assigned to a variable or passed as argument, they will all point to the 
same actual data.  That means that if the value of an element in an array is 
changed, then it can modify all other variables pointing to the same array. 
Changing the size of the array will always allocate a new one though. The 
comparison operator, ==, will compare the actual value for the group of 
value-referenced types above.  But for arrays, mappings, etc, it will simply 
check if it is the same array, mapping, etc. That has the very important 
implication that the expression ({}) == ({}) will evaluate to false because
the array construction operator-pair, ({}) always generates a new array.
 
Basic types
 
int
 An integer number (32 bit).
 
float
 A floating point number (32 bit).
 
string
 An unlimited string of characters. 
 
object
 A pointer to an object.  
 
mapping
 A form of associative array, see separate documentation.
 
function
 A special type that points to (object, function name) pairs, see
 separate documentation.
 
Arrays
 Arrays are declared using a '*' following a basic type.  For example, 
 declaring an array of numbers: int *arr;.  Use the type mixed if you want an 
 array of arrays, or a mixed combination of types.
 
void
 This type is only usable for functions.  It means that the function will not
 return any value.  The compiler will complain (when type checking is enabled)
 if a return value is used.
 
mixed
 This type is special, in that it is valid to use in any context.  Thus, if 
 everything was declared mixed, then the compiler would never complain. This 
 is of course not the idea. It is really only supposed to be used when a 
 variable really is going to contain different types of values. This should
 be avoided if possible.  It is not good coding practice to allow a function,
 for example, to return different types.
 
Special types
 
There are some special types, which can be given before the basic type. These
special types can also be combined.  When using special type T before an 
inherit statement, all symbols defined by inheritance will also get the 
special type T.  The only special case is public--defined symbols, which can 
not be redefined as private in a private inheritance statement.
 
varargs
 A function of this type can be called with a variable number of arguments.
 Otherwise, the number of arguments is checked, and can generate an error.
 
private
 Can be given for both functions and variables. Functions that are private in
 object A can not be called through call_other() in another object.  They're
 also not accessable to any object that inherits A.
 
static
 This special type behaves different for variables and functions.  It is 
 similar to private for functions, in that they cannot be called from other 
 objects with call_other().  static variables will be neither saved nor 
 restored when using save_object() or restore_object().
 
public
 A function defined as public will always be accessible from other objects, 
 even if private inheritance is used.
 
nomask
 All symbols defined as nomask cannot be redefined by inheritance.  They can 
 still be used and accessed as usual.  nomask also blocks functions from
 being shadowed with shadow().

back to top

Mappings usage                                              1992 September 28

Documentation on MudOS's mapping datatype - written by Truilkan@TMI:

MudOS 0.9 provides a datatype calling the 'mapping'.  Mappings are
the equivalent of associative arrays found in other languages (e.g. Perl).
An associative array is similar to a regular array except that associative
arrays can be indexed by any type of data (string, object, int, array, etc)
rather than just integers.  In addition, associative arrays are sparse arrays
which means you can have a mapping which has a value for its 1,000,000th
element without having values for any other elements.  Two particularly
effective uses for mappings are: 1) databases, and 2) a substitute for the
aggregate type 'struct' (as used in the C language) by representing each
field of the C struct as a key in the mapping.

A mapping is declared like this:

mapping x;

A mapping can be initialized in one of two ways:

   x = ([key0 : value0, key1 : value1, ...]);

   (note: 'x = ([]);' can be used to create an empty mapping)

Note that a mapping _must_ be initialized before you may assign any elements
to it.  This restriction exists because of the way the gamedriver
initializes all variables (regardless of type) to zero (0).  If you do not
initialize the mapping, then you'll see an "Indexing on illegal type" error
when you try to assign an element to the mapping.

New (key, value) pairs may be added to the map in the following way:

x[key] = value;

The above statement causes the driver to search the mapping named 'x' for the
specified key.  If the mapping contains that key, then the associated value
(in the mapping) is replaced with the value on the right hand side of the
assignment.  If the mapping does not already contain that key, then
additional space is automatically allocated (dynamically) and the
(key, value) pair is inserted into the mapping.

An element of a mapping may be referenced as follows:

   write(x[key] + "\n");

An element of a mapping may be deleted as follows:

   map_delete(x, key);

this deletion will cause the following expression to evaluate to true (1):

   undefinedp(x[key])

so that you could write code such as this:

if (undefinedp(value = x["MudOS"])) {
    write("'MudOS' is not used as a key in the mapping 'x'\n");
} else {
    write("the value for the key 'MudOS' is " + value + "\n");
}

A list of the keys (indices) may be obtained using the keys() efun, for
example:

   mixed *idx;
   map x;

   x = ([ "x" : 3, "y" : 4]);
   idx = keys(x);  /* idx == ({"x", "y"}) or ({"y", "x"}) */

Note that keys() will return the list of indices in an apparently random
order (the order is a side effect of the implementation used to store
the mapping -- in this case, an extensible hash table).

A list of the values in a mapping may be obtained using the values()
efun, for example:

   idx = values(x);

causes idx to be equal to ({3, 4}) or ({4, 3}).  Note that values() will
return the values in the same order as keys() returns the corresponding
keys.

The (key, value) pairs in a mapping may be iterated over using the each()
efun.  each() returns a null vector when the end of the mapping is reached.
each() returns the (key, value) pairs in the same order as keys() and values()
do.  For example:

   mixed *pair;

   while ((pair = each(x)) != ({})) {
      write("key   = " + pair[0] + "\n");
      write("value = " + pair[1] + "\n");
   }

Mappings can be two-dimensional (or n-dimensional for that matter) in the same
sense that LPC arrays can be.

   mapping x, y;

   x = ([]);
   y = ([]);

   y["a"] = "c";
   x["b"] = y;

   And then x["b"]["a"]  == "c"

   Mappings can also be composed using the '*' operator (composed in the
   mathematical sense of the word):

   mapping r1, r2, a;

   r1 = ([]);
   r2 = ([]);

   r1["driver"] = "mudlib";
   r2["mudlib"] = "castle";

so:

   a = r1 * r2 

defines a to be a map with: a["driver"] == "castle";

You may also add two mappings.  The sum of two mappings is defined
as the union of the two mappings.

   a = r1 + r2

defines a to be a map with a["driver"] == "mudlib" and
a["mudlib"] == "castle"

The += operator is also supported.  Thus you could use:

   a += ([key : value]);

as a substitute for:

   a[key] = value;

However, the latter form (a[key] = value) is much more efficient since
the former (in the present implementation) involves the creation of a new
mapping while the latter does not.

The subtraction operator is not defined for mappings (use map_delete()).

The sizeof() efun may be used to determine how many (key, value) pairs
are in the mapping.  For example,

   write("The mapping 'x' contains " + sizeof(x) + " elements.\n");

the implementation:

MudOS's mappings are implemented using an extensible hash table.  The
size of the hash table is always a power of 2.  When a certain percentage
of the hash table buckets become full, the size of the hash table is
doubled in order to maintain the efficiency of accesses to the hash
table.

credits:

MudOS's mappings were originally implemented by Whiplash@TMI.  Parts of
the implementation were later rewritten by Truilkan@TMI (to use an
extensible hash table rather than a binary tree).

Parts of the data structure used to implement mappings are based on
the hash.c module from the Perl programming language by Larry Wall.
The Perl package is covered under the GNU Copyleft general public license.

back to top

Advertisements
  1. #1 by Devin Trotter on March 26, 2013 - 12:29 pm

    Best layout of the MudOS docs I have ever seen. Will come in handy as I start to learn more about the forked FluffOS driver. Cheers!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: