FuzzBall MUF Changes

I'm still in the process of hypertexting this document. Until I'm done, here's the flat ASCII version. -- Telzey


TinyMUCK2.2fb4.0 MUF documentation.
===================================

  There are now four levels of MUCKERs in fb4.0.  Level zero is a non-mucker.
    They cannot use the editor, and MUF programs owned by them run as if
    they were level 1 MUCKERs.
      Level one MUCKER's are apprentices.  Their powers are restricted as they
    cannot get information about any object that is not in the same room they
    are.  ie:  OWNER, NAME, LOCATION, etc all fail if the object isn't in the
    same room as the player.  Level one MUCKER programs always run as if they
    are set SETUID.  NOTIFY, NOTIFY_EXCEPT, and NOTIFY_EXCLUDE will refuse to
    send messages to rooms the user is not in.  Level one programs also cannot
    use ADDPENNIES.
      Level two MUCKERs are also called Journeymen.  Their permissions are
    equivalent to the permissions for a normal MUCKER under older versions
    of the server.
      Level three MUCKERs are referred to as Masters.  They can use the con-
    nection info primitives (ie: CONDBREF, ONLINE, etc.), read the EXITS list
    of any room, use NEXTOBJ on objects, can use NEWROOM, NEWOBJECT, NEWEXIT,
    and COPYOBJ without limitations, can use QUEUE and KILL, and can override
    the permissions restrictions of MOVETO.  You only give a player MUCKER
    level 3 if they are very trusted.
      A player who is wizbitted is effectively Mucker Level 4.  MUCKER level
    four is required for the RECYCLE primitive, the CONHOST primitive, the
    FORCE primitive, and the SETOWN primitive.  ML4 also allows overriding
    of permissions of the SET* primitives, and property permissions.  Props
    not listed by NEXTPROP with ML3 are listed with ML4.
      The MUCKER level permissions that a program runs at is the lesser of
    it's own MUCKER level and the MUCKER level of it's owner.
      If it is owned by a player who is MUCKER level 2, and it is MUCKER
    level 3, then it runs at Muckr level 2.  The one exception to this is
    programs owned by a Wizard player.  They run at Mucker level 2 if the
    program itself is not wizbit, and at Mucker level 4 if the program IS
    set wizbit.
      Mucker level is referred to in flags lists by M# where the # is the
    Mucker level.  Level zero objects don't show a flag for it.  Example:
    Revar(#37PM3)
      In verbose flags lists, Mucker levels greater than zero are shown
    by MUCKER# where # is the mucker level.
      To set a level on a player or program, use the level number as the
    flag name.  MUCKER is the same as 2, and !MUCKER is the same as 0.
    Example:  @set Revar=2
      A player may set the MUCKER level on a program they own to any level
    lower than or equal to their own level, and a wizard may set a program
    or player to any MUCKER level.  A program cannot be set to Mucker Level
    Zero, since it has no meaning for programs. (You expect them to use the
    MUF editor or something?)
      When a program is created, it is automatically set to the same MUCKER
    level as the creating player.  When a program is loaded from the db, if
    it is Mucker Level 0, it is upgraded to Mucker Level 2.



Compiler directives for MUF:
    $define <defname> <definition> $enddef
      Basically the same as C's #define <defname> <definition>
    $undef <defname>
      About the same as C's #undef <defname>
    $echo <string>
      Echos the given string to the screen of the person compiling the program.
      Runs at compile-time.
    __version
      A pre$defined macro that contains the current server version.
      Currently "Muck2.2fb3.4"
    $ifdef <condition> <compile this if true> $else <compile if false> $endif
    $ifndef <condition> <compile this if true> $else <compile if false> $endif
      where <condition> is either a $defined name, or a test that consists of
      a $defined name, a comparator (=, <, or >) and a test value, all in one
      word without space.  The $else clause is optional.  Compiler directives
      are nestable also.  Some examples:
      $ifndef __version>Muck2.2fb3.5 $define envprop .envprop $enddef $endif
      $define ploc $ifdef proplocs .proploc $else $endif $enddef
    $include <dbref|progreg>
      Sets a bunch of $defines from the properties in the /_defs/ propdir.
      For example, if object #345 had the following properties:
        /_defs/desc: "_/de" getpropstr
        /_defs/setpropstr: dup if 0 addprop else pop remove_prop then
        /_defs/setpropval: dup if "" swap addprop else pop remove_prop then
        /_defs/setprop: dup int? if setpropval else setpropstr then
      then if a program contained '$include #345' in it, then all subsequent
      references to 'desc', 'setpropstr', 'setpropval', and 'setprop' would
      be expanded to the string values of their respective programs. ie:
      'desc' would be replaced throughout the program with '"_/de" getpropstr'

  You can now escape a token in MUF so that it will be interpreted literally.
    ie:  \.pmatch will try to compile '.pmatch' without expanding it as a
    macro.  This lets you make special things with $defines such as:
    $define addprop over over or if \addprop else pop pop remove_prop $enddef
    so that all the 'addprop's in the program will be expanded to the
    definition, but the 'addprop' in the definition will not try to expand
    recursively.  It will call the actual addprop.



Multitasking:
  There are now 3 modes that a program can be in when running:  foreground,
    background, and preempt.  A program running in the foreground lets other
    users and programs have timeslices (ie multitasking), but blocks input
    from the program user.  Background mode allows the user to also go on and
    do other things and issue other commands, but will not allow the program
    to do READs.  Preempt mode means that the program runs to completion
    without multitasking, taking full control of the interpreter and not
    letting other users or progs have timeslices, but imposes an instruction
    count limit unless the program is a wizard program.
  Programs run by @locks, @descs, @succs, @fails, and @drops default to the
    preempt mode when they run.  Programs run by actions linked to them
    default to running in foreground mode.  QUEUEd program events, such as
    those set up by _listen, _connect, _disconnect, etc, and those QUEUEd by
    other programs default to running in background mode. (NOTE: these
    programs cannot be changed out of background mode)



New primitives:
  PUBLIC <functionname>  Declares a function to be public for execution by
                          other programs.  This is a compile-time directive,
                          not a run-time primitive.  To call a public
                          function, put the dbref of the program on the
                          stack, then put a string, containing the function
                          name, on the stack, then use CALL.  For example:
                          #888 "functionname" CALL

  LVAR <varname>   This declares a variable as a local variable, that is
                    local to a specific program.  If another program calls
                    this program, the values of the local variables will not
                    be changed in the calling program, even if the called
                    program changes them.

  LOCALVAR  (i -- l)    Takes an integer and returns the respective local
                          variable.  Similar to the 'variable' primitive.


  ABORT    (s -- )  Halts the interpreter with an error of the string given.

  SETLINK   (d d -- )   Takes an exit dbref and a destination dbref and sets
                         the exit link to that destination.  Note that if the
                         exit is already linked, it must be unlinked by doing
                         a setlink with #-1 as a destination.

  SETOWN    (d d -- )   Sets the ownership of the first object to the player
                         given in the second dbref. (wizbit only)

  NEWROOM   (d s -- d)  Takes dbref of the location, and the name in a string.
                          Returns the dbref of the room created.  Owner is
                          runner of the program. (Mucker Level 3)

  NEWOBJECT (d s -- d)  Takes location and name and returns new thing's dbref.
                          (Mucker Level 3)

  NEWEXIT   (d s -- d)  Takes location and name and returns new exit's dbref.
                          (Requires Mucker Level 3)

  RECYCLE   (d -- )    Recycles the given object d.  Will not recycle
                        players, the global environment, the player
                        starting room, or any currently running program.
                        (Can recycle objets owned by uid if running with
                        Mucker Level 3 permissions.  Can recycle other
                        people's items with wizbit)

  STATS (d -- 7 ints)  Takes a dbref and returns 7 integers, giving, in order,
                        The total number of objects owned by the given dbref,
                        the number of rooms owned, the number of exits owned,
                        the number of things owned, number of programs owned,
                        number of players, and number of garbage items owned.
                        If the given dbref was #-1, then the stats are the
                        totals for the entire database. (Needs Mucker Level 3)



  AWAKE?    (d -- i)    Returns whether the given player (dbref) is connected.
                         It returns how many times they are connected.

  ONLINE    ( -- d d..d i)  Returns the dbrefs of all the players logged in,
                         with the count of them on the top of the stack.
                         (Requires Mucker Level 3)

  CONCOUNT  ( -- i)     Returns how many connections to the server there are.
                         (Requires Mucker Level 3)

  CONDBREF  (i -- d)    Returns the dbref of the player connected to this
                         connection.  (Requires Mucker Level 3)

  CONTIME   (i -- i)    Returns how many seconds the given connection has been
                         connected to the server.  (Requires Mucker Level 3)

  CONIDLE   (i -- i)    Returns how many seconds the connection has been idle.
                         (Requires Mucker Level 3)

  CONDESCR  ( i -- i )  Takes a connection number and returns the descriptor
                         number associated with it.  (Requires Mucker Level 3)

  DESCRCON (i -- i)  Takes a descriptor and returns the associated connection
                      number, or 0 if no match was found.

  DESCRIPTORS (d -- ix...i1 i) Takes a player dbref, or #-1, and returns the
                                range of descriptor numbers associated with
                                that dbref (or all for #-1) with their count
                                on top.

  CONHOST   (i -- s)    Returns the hostname of the connection. (wizbit only)

  CONBOOT   (i -- )    Takes a connection number and disconnects that
                        connection from the server.  Basically @boot for
                        a specific connection. (wizbit only)

  CONNOTIFY (i s -- )  Sends a string to a specific connection to the
                        server.  (Requires Mucker Level 3)



  INT?      (? -- i)    Tells whether the top stack item is an integer.

  STRING?   (? -- i)    Tells whether the top stack item is a string.

  DBREF?    (? -- i)    Tells whether the top stack item is a dbref.



  NEXTPROP  (d s -- s)  This takes a dbref and a string that is the name of a
                         property and returns the next property name on that
                         dbref, or returns a null string if that was the last.
                         To *start* the search, give it a propdir, or a blank
                         string. For example, '#10 "/" NEXTPROP'  or
                         '#28 "/letters/" NEXTPROP'   A blank string is the
                         same as "/".  (Requires Mucker Level 3)

  The NEXTPROP primitive will skip over property names that the program
    and user would not have permissions to read.  Wizbit programs can see all
    of the properties on an object.  Otherwise, nextprop will skip over the
    props that are not readable by the uid the program is running under.


  PROPDIR?  (d s -- i)  Takes a dbref and a property name, and returns whether
                         that property is a propdir that contains other props.
                         (Requires Mucker Level 3)

  ENVPROPSTR (s d -- s d )  Takes a starting object dbref and a property name
                             and searches down the environment tree from that
                             object for a property with the given name.
                             If the property isn't found, it returns #-1 and
                             a null string.  If the property is found, it will
                             return the dbref of the object it was found on,
                             and the string value it contained.



  NOTIFY_EXCLUDE (d dn ... d1 n s -- )  Displays the message s to all the
                             players (or _listening objects), excluding the
                             n given players, in the given room.  Example:
                             #0 #1 #23 #7 3 "Hi!" notify_exclude
                             would send "Hi!" to everyone in room #0 except
                             for players (or objects) #1, #7, and #23.

  NOTIFY_EXCEPT has been removed and replaced by a $define to NOTIFY_EXCLUDE.
    It is effectively $define notify_except 1 swap notify_exclude $enddef

  NOTIFY and NOTIFY_EXCLUDE will not trigger _listen's that would run the
    current program.



  SYSTIME   ( -- i)     Returns the number of seconds since 1/1/79 00:00 GMT

  TIMEFMT   (s i -- s)  Takes a format string and a SYSTIME integer and returns
                         a string formatted with the time.  The format string
                         is ascii text with formatting commands:
                           %% -- "%"
                           %a -- abbreviated weekday name.
                           %A -- full weekday name.
                           %b -- abbreviated month name.
                           %B -- full month name.
                           %C -- "%A %B %e, %Y"
                           %c -- "%x %X"
                           %D -- "%m/%d/%y"
                           %d -- month day, "01" - "31"
                           %e -- month day, " 1" - "31"
                           %h -- "%b"
                           %H -- hour, "00" - "23"
                           %I -- hour, "01" - "12"
                           %j -- year day, "001" - "366"
                           %k -- hour, " 0" - "23"
                           %l -- hour, " 1" - "12"
                           %M -- minute, "00" - "59"
                           %m -- month, "01" - "12"
                           %p -- "AM" or "PM"
                           %R -- "%H:%M"
                           %r -- "%I:%M:%S %p"
                           %S -- seconds, "00" - "59"
                           %T -- "%H:%M:%S"
                           %U -- week number of the year. "00" - "52"
                           %w -- week day number, "0" - "6"
                           %W -- week# of year, starting on a monday,
                                   "00" - "52"
                           %X -- "%H:%M:%S"
                           %x -- "%m/%d/%y"
                           %y -- year, "00" - "99"
                           %Y -- year, "1900" - "2155"
                           %Z -- Time zone.  "GMT", "EDT", "PST", etc.

  TIMESPLIT (i -- i i i i i i i i)  Takes a systime integer, and splits it up
                         into second, minute, hour, dayofmonth, month, year,
                         dayofweek, and dayofyear.  1 == sunday for dayofweek.
                         Dayofyear is a number from 1 to 366.

  TIMESTAMPS ( d -- i i i i )   Takes the dbref of an object, and returns
                                 the four timestamp ints in the order of
                                 Created, Modified, Lastused, and Usecount
                                 where the three times are in systime
                                 notation.

  SLEEP   (i -- )     makes the program pause here for 'i' seconds.

  QUEUE     (i d s -- i) Takes a time in seconds, a program's dbref, and a
                          parameter string.  It will execute the given program
                          with the given string as the only string on the
                          stack, after a delay of the given number of second.
			  Returns pid of the queued process.  QUEUE'd
			  programs cannot use the READ primitive.  They are
			  writeonly.  When a QUEUEd program executes, it does
			  so with me @ set to the player who was running the
			  program that QUEUEd it, a loc @ of #-1, and a
			  trigger @ of #-1.
                          (Requires Mucker Level 3)

  FORK  ( -- i)  This primitive forks off a BACKGROUND (muf) process from
                   the currently running program.  It returns the pid of
                   the child process to the parent process, and returns a
                   0 to the child.  This does NOT do a UNIX fork.  It only
                   copies the current stack frame and puts the background
                   muf process on the time queue. (Requires Mucker Level 3)

  KILL       (i -- i)  Attempts to kill the given process number.  Returns 1
                        if the process existed, and 0 if it didn't.
                        (Requires Mucker Level 3)

  ISPID?  (i -- i)  Takes a process id and checks to see if an event with that
                     pid is in the timequeue.  It returns 1 if it is, and 0 if
                     it is not.  NOTE: since the program that is running is not
                     on the timequeue WHILE it is executing, but only when it
                     is swapped out letting other programs run, 'pid ispid?'
                     will always return 0.



  TOUPPER    (s -- s)  Takes a string and returns it with all the letters
                        in uppercase.

  TOLOWER    (s -- s)  Takes a string and returns it with all the letters
                        in lowercase.

  STRIPLEAD  (s -- s)  Strips leading spaces from the given string.

  STRIPTAIL  (s -- s)  Strips trailing spaces from the given string.

  STRIP      (s -- s)  This is a built in $define.  It is read as
                        "striplead striptail"

  SMATCH  ( s s -- i )  Takes a string and a string pattern to check against.
                         Returns true if the string fits the pattern.  In the
                         pattern string, a '?' matches any single character,
                         '*' matches any number of characters. Word matching
                         can be done with '{word1|word2|etc}'.  If multiple
                         characters are in [], it will match a single
                         character that is in that set of characters.
                         '[aeiou]' will match a single character if it is a
                         vowel, for example.  To search for one of these
                         special chars, put a \ in front of it to escape it.
                         It is not case sensitive.  Example pattern:
                         "{Foxen|Lynx|Fiera} *t[iy]ckle*\?"  Will match any
                         string starting with 'Foxen', 'Lynx', or 'Fiera',
                         that contains either 'tickle' or 'tyckle' and ends
                         with a '?'.



  SETLOCKSTR (d s -- i)  Tries to set the lock on the given object to the
                          lock expression given in the string.  If it was a
                          success, then it will return a 1, otherwise, if
                          the lock expression was bad, it returns a 0.  To
                          unlock an object, set its lock to a null string.

  GETLOCKSTR ( d -- s )  Returns the lock expression for the given object
                          in the form of a string.  Returns "*UNLOCKED*" if
                          the object doesn't have a lock set.

  LOCKED? (d d -- i)  Takes, in order, the dbref of the object to test the
                        lock on, and the dbref of the player to test the lock
                        against.  It tests the lock, running programs as
                        necessary, and returns a integer of 0 if it is not
                        locked against them, or 1 if it is.

  UNPARSEOBJ ( d -- s )  Returns the name-and-flag string for an object.
                          For example: "One(#1PW)"



  DBTOP     ( -- d)     Returns the dbref of the first object beyond the top
                          object of the database.

  DEPTH     ( -- i)     Returns how many items are on the stack.

  VERSION   ( -- s)     Returns the version of this code in a string.
                          "Muck2.2fb4.0" is the current version.

  PROG      ( -- d)     Returns the dbref of the currently running program.

  TRIG      ( -- d)     Returns the dbref of the original trigger.

  CALLER    ( -- d)     Returns the dbref of the program that called this one,
                          or the dbref of the trigger, if this wasn't called
                          by a program.



  BITOR     (i i -- i)  Does a logical bitwise or.

  BITXOR    (i i -- i)  Does a logical bitwise exclusive or.

  BITAND    (i i -- i)  Does a logical bitwise and.

  BITSHIFT  (i i -- i)  Shifts the first integer by the second integer's
                          number of bit positions.  Same as the C << operator.
                          If the second integer is negative, its like >>.




  FORCE     (d s -- )  Forces player d to do action s as if they were
                        @forced.  (wizbit only)

  PREEMPT   ( -- )     Prevents a program from being swapped out to do
                        multitasking.  Needed in some cases to protect
                        crutial data from being changed while it is being
                        worked on.  A program will remain in preempt mode
                        until it's execution is completed.  Basically what
                        this command does is to turn off multitasking, but
                        then you have a limit on how many instructions you
                        can run without needing either to pause with a SLEEP,
                        or have a wizbit on the program.

  FOREGROUND ( -- )  To turn on multitasking, you can issue a foreground
                      command.  While a program is in foreground mode, the
                      server will be multitasking and handling multiple
                      programs at once, and input from other users, but it
                      will be blocking any input from the user of the program
                      until the program finishes.  You cannot foreground a
                      program once it is running in the background. A program
                      will stay in foreground mode until it finishes running
                      or until you change the mode.

  BACKGROUND ( -- )  Another way to turn on multitasking is to use the
                      background command.  Programs in the background let
                      the program user go on and be able to do other things
                      while waiting for the program to finish.  You cannot
                      use the READ command in a background program.  Once a
                      program is put into background mode, you cannot set
                      it into foreground or preempt mode.  A program will
                      remain in the background until it finishes execution.




  BEGIN   ( -- )      Marks the beginning of begin-until or begin-repeat loops

  UNTIL   (i -- )     If the value on top of the stack is false, then it jumps
                        execution back to the instruction afer the matching
                        BEGIN statement.  (BEGIN-UNTIL, BEGIN-REPEAT, and
                        IF-ELSE-THEN's can all be nested as much as you want.)
                        If the value is true, it exits the loop, and executes
                        the next instruction, following the UNTIL.  Marks the
                        end of the current loop.

  REPEAT  ( -- )      Jumps execution to the instruction after the BEGIN in a
                        BEGIN-REPEAT loop.  Marks the end of the current loop.

  WHILE      (i -- )   If the value on top of the stack is false, then this
                        causes execution to jump to the instruction after the
                        UNTIL or REPEAT for the current loop.  If the value is
                        true, however, execution falls through to the instr-
                        uction after the WHILE.

  BREAK      ( -- )    Breaks out of the innermost loop.  Jumps execution to
                        the instruction after the UNTIL or REPEAT for the
                        current loop.

  CONTINUE   ( -- )    Jumps execution to the beginning of the current loop.

    The BEGIN statement marks the beginning of a loop.
    Either the UNTIL or the REPEAT statement marks the end of the loop.
      REPEAT will do an unconditional jump to the statement after the BEGIN
        statement.
      UNTIL checks to see if the value on the stack is false.  If it is, it
        jumps execution to the statement after the BEGIN statement, otherwise,
        it falls through on execution to the statement after the UNTIL.
    Within a loop, even within IF-ELSE-THEN structures within the loop
      structure, you can place WHILE, CONTINUE, or BREAK statements.  There
      is no limit as to how many, or in what combinations these instructions
      are used.
      A WHILE statement checks to see if the value on the stack is false.
        If it is, execution jumps to the first statement after the end of
        the loop.  If the value was true, execution falls through to the
        statement after the WHILE.
      The CONTINUE statement forces execution to jump to the beginning of
        the loop, after the BEGIN.
      The BREAK statement forces execution to jump to the end of the loop,
        at the statement after the REPEAT or UNTIL, effectively exiting the
        loop.
    Note: You can nest loops complexly, but WHILE, BREAK, and CONTINUE
      statements only refer to the innermost loop structure.

    Example of a complex loop structure:
      101 begin                       (BEGIN the outer loop)
        dup while 1 -                 (This WHILE, ...)
        dup not if break then         (this BREAK, and..)
        dup 2 % not if continue then  (this CONTINUE refer to the outer loop)
        dup 10 % not if
          15 begin                    (BEGIN inner loop)
            dup while 1 -             (This WHILE, and.. )
            dup 5 % not if break then (... this BREAK, refer to inner loop)
          repeat                      (This REPEAT statement ends inner loop.)
        then
        dup 7 % not if continue then  (This CONTINUE, and...)
        dup 3 % not if dup 9 % while then (this WHILE refer to the outer loop)
        dup intostr me @ swap notify
      dup 1 = until pop               (This UNTIL ends the outer loop)




  On dbload, if a program is set ABODE (AUTOSTART), *AND* it is owned by
    a wizard, then it will be placed in the timequeue with a delay of 0 and
    a string parm of "Startup".  Autostart programs run with the location
    NOTHING (#-1) rather than the location of the owner of the program.

  You can now check the Interactive flag on a player in MUF to see if they
    are in READ mode or @edit'ing.

  MOVETO will now run programs in the @desc and @succ/@fail of a room when
    moving a player.

  When a message is notify_except'ed or notify_exclud'ed to a room, and
    LISTENERS and LISTENERS_ENV are defined, then it will run ALL the
    programs referred to in all the _listen properties down the environment
    tree.  Also, the muf NOTIFY primitive was changed to run the _listen
    program on an object or player if a message is sent to them that way.

  Removed DESC, SUCC, FAIL, DROP, OSUCC, OFAIL, ODROP, SETDESC, SETSUCC,
    SETFAIL, SETDROP, SETOSUCC, SETOFAIL, and SETODROP and replaced them with
    $defines that would set/get the appropriate information in/from properties.
    For example, DESC is now translated to '"_/de" getpropstr' and SETDESC is
    translated to '"_/de" swap 0 addprop'.  One result of this is that if you
    tried to escape one of these command names with a backslash in a macro
    definition, it wouldn't work.  ie:  \SETDESC would get a compile error.

  There is a COMMAND variable, similar to ME, LOC, and TRIGGER, except that
    it contains a string.  The string contains the command the user typed
    that triggered the the program, without the command line arguments.  ie:
    if there was an exit named "abracadabra;foo bar;frozzboz" that was linked
    to the program, and the user typed in "foo bar baz", then the program
    would run with "baz" on the stack, and "foo bar" in the global COMMAND
    variable.

  Made ROOM?, PLAYER?, THING?, EXIT?, and PROGRAM? primitives return false
  if the object passed to it is invalid, instead of aborting interpreting.

  INSTRING and RINSTRING are now inserver defines that let you do case
    insensitive versions of their instr and rinstr counterparts.

Programs are now compiled when they are run or called instead of when
  the databate is loaded.  They are compiled with the uid of the owner
  of the program.

If a program has the HAVEN flag set on it (HARDUID) then it runs with
  the uid and permissions of the owner of the trigger of the program.
  If the program is a timequeue event (with trigger of #-1), then it
  will run with the permissions and uid of the program owner as in SETUID.

A room or player may have a "_connect" property set that contains the
  dbref of a progran to run when a player connects.  The program must be
  either link_ok or must be owned by the player connecting.  When the
  program is run, the string on the stack will be "Connect", the "loc @"
  will be the location of the connecting player, the "me @" will be the
  connecting player, and the "trigger @" (and "trig") will be #-1.  All
  programs referred to by _connect properties on the player, and on rooms
  down the environment tree from the player, will be QUEUEd up to run.
  When a player desconnects, programs referred to by _disconnect properties
  will be run in a similar manner.
  (connect and disconnect _actions_ are also implemented.)

Programs refered to by props in _depart/_arrive/_connect/_disconnect propdirs
  will now be all queued up, eliminating the need for a dispatcher program.
  An example would be _connect/announce:1234  That would queue up program
  #1234 when a player connects.  The name ("announce") is not important, and
  can be anything you want, but they are executed in alphabetic order.

Programs set BUILDER (BLOCKED) run in preempt mode, regardless of the mode
  of the program.  ie: a foreground program, while running in a program set
  BLOCKED, will run pre-empt, with the multitasking effectively shut off.

Programs set HARDUID and SETUID, that are owned by a Wizard, run at the same
  mucker level as the calling program.  This is useful for writing libraries.

Tabs sent to the server are now interpreted as single spaces to help solve
  a problem with tabbed comments in MUF programs being uploaded.


Return to the TinyMUCK Page

Page created by Telzey, and maintained by Tugrik d'Itichi.
Comments/Questions/Flames to: FMPages@furry.com