MUF Reference Manual for FBMuck 6.00
by Revar Desmera <revar@belfry.com>
You can get more help on the following topics:
Symbols
A's
B's
C's
D's
E's
F's
G's
I's
J's
K's
L's
M's
N's
O's
P's
Q's
R's
S's
T's
U's
V's
W's
X's
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
cannot be run.
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 cannot use
ADDPENNIES. Level one programs don't list DARK objects or rooms in the
contents of a room, unless they are controlled by the program owner.
Additionally, level one programs have an absolute instruction limit that
is the same size as the PREEMPT instruction limit. This is usually
around 20,000 instructions.
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 two programs can run as many as four times the
number of instructions that a preempt program could. This is usually
around 80,000 instructions.
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 NEXTPROP 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. There is no absolute instruction count
limit for level three or above, except for programs running in PREEMPT mode.
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. Programs running
ML4 do not even have instruction limits on PREEMPT mode programs.
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 Mucker 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. When a program is created, it is
automatically set to the same MUCKER level as the creating player.
When a program is loaded from an old db, if it is Mucker Level 0,
it is upgraded to Mucker Level 2.
There are 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)
1) Use "@register lib" to list what libraries exist.
2) Use "@view $lib/<libraryname>" to list the docs on that library.
3) When you've found the library and the function you want, then all
you have to do in your program is, at the beginning of it,
$include $lib/<libraryname>
then just use the function name to invoke it later in your program
and it will run as if it were a function in your program.
How to make a library:
1) Create a program with several useful generic subroutines.
2) DOCUMENT those subroutines in a commented out header in the prog.
3) @set <program>=_docs:<command to list those DOCS you made>
4) Set the version number of the code in the library with $version 1.000
This lets you keep track of the code revision installed, separately
from the version of the library calling API.
5) Set the library API version number with $lib-version 1.000
This is the version of the calling interface for this library.
Remember to up this version when you change this library's calls.
Remember that 1.19 is less than 1.2, so use numbers like 1.002.
6) For each function you want to be externally callable, do the following:
a) Declare it PUBLIC
b) Create the caller macro with either:
$libdef FUNCNAME or
$pubdef EXPORTEDNAME "$lib/THISLIB" match "FUNCNAME" call
7) Make sure the program is set LINK_OK and VIEWABLE.
8) Globally register the program with the @register command with a
prefix of "lib/". ie: @reg lib-strings.muf=lib/strings
9) You're done!
Currently standard libraries:
$lib/strings Functions for manipulating strings.
$lib/props Routines for searching for properties, or setting them.
$lib/lmgr Standard list manager routines.
$lib/stackrng Routines to handle variable sized ranges on the stack.
$lib/edit String range editing and manipulation routines.
$lib/editor Standard user text editor.
$lib/mesg Standard message manager routines.
$lib/mesgbox Routines for handling lists of messages.
$lib/match Object or string matching routines.
$lib/reflist Dbref-list management routines.
$lib/index Hashed linked list manager with partial key matching.
$lib/gui Routines to make MCP's GUI package easier to use.
$lib/optionsgui Given datums, auto-generates a GUI to edit them.
If a program is set DARK (DEBUG), then when it is run, it will print out
a stack trace for each instruction executed, to the player running the
program. This is useful for debugging programs.
If a program is set ZOMBIE, then when the owner runs it, they will enter an
interactive debugger, useful for following a program as it runs and
changing it to see what different situations do.
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.
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.
If a program is set both SETUID and HARDUID, and it is owned by a wizard,
then it inherits the uid and mucker level of the program that called it.
If it was not called by a program, then it runs SETUID. This is useful
for writing libraries.
Programs set BUILDER (BOUND) run in preempt mode, regardless of the mode
of the program. ie: a foreground program, while running in a program set
BOUND, will run pre-empt, with the multitasking effectively shut off.
A program that is set WIZARD ignores almost all permissions checking.
The Mucker Level of the program also has a great deal of influence on what
a program can and cannot do. See MUCKER LEVELS for more information.
Programs are compiled when they are run or called, or when explicitly
compiled in the editor. They are compiled with the uid of the owner of
the program. After being unused for a number of minutes, programs will
be removed from memory until needed again.
When a message is notify_except'ed or notify_exclude'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, And
in all of the objects in the room with LISTENERS_OBJ defined. 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.
A room or player may have a "_connect" property set that contains the
dbref of a program 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 the object
that had the _connect property on it. All programs referred to by
_connect properties on the player, and on rooms down the environment tree
from the player, will be run. When a player disconnects, programs referred
to by _disconnect properties will be run in a similar manner.
(connect and disconnect _actions_ are also triggered.)
Programs referred to by props in _depart/_arrive propdirs will all be
run when a player leaves or enters a room, respectively. An example would
be _arrive/announce:1234 That would queue up program #1234 when a player
enters a room. The name ("announce") is not important, and can be anything
you want, but they are run in alphabetic order.
A pre$defined macro that contains the value 1 on a FuzzBall Muck server.
This is useful for server-type specific $ifdefs, when code needs to be
different on, say, FuzzBall Mucks and ProtoMucks. For example:
$ifdef __fuzzball__
me @ "This is a FuzzBall Muck server.!" notify
$endif
A pre$defined macro that contains the name of the server's muckname @tune
parameter value. This is useful for muck specific $ifdefs. For example:
$ifdef __muckname=FurryMUCK
me @ "Helloooooo Furry!" notify
$endif
A pre$defined macro that contains the current server version. Contains
the same string that the VERSION primitive returns. This is mainly useful
in $ifdef/$ifndef comparisons. The value of this will always start with
'Muck2.2fb' for historical reasons, followed by the current fbmuck server
version. Ie: Muck2.2fb6.00 for the 6.00 fbmuck server.
A pre$defined macro that expands to the maximum number of variables of
each type allowed in a program. For function-scoped variables, this is the
max number of scoped vars that each function may have.
Sets the _author string property on the program to <rest_of_line>.
The preferred format is an email address with name comment. ie:
$author Revar Desmera <revar@belfry.com>
To denote multiple authors, separate them with commas. ie:
$author Revar Desmera <revar@belfry.com>, Foxen <foxen@belfry.com>
If you don't want to include your email address, just omit it. ie:
$author Revar, Foxen
Sets the _version string property on the program to <float>. Version
numbers should be like 1.009 and 1.010, so that they can be compared using
floating point comparisons. (Remember, 1.9 is greater than 1.10.)
Sets the _lib-version string property on the program to <float>. Version
numbers should be like 1.009 and 1.010, so that they can be compared using
floating point comparisons. (Remember, 1.9 is greater than 1.10.)
Sets the _note string property on the program to <rest_of_line>.
Basically the same as C's #define <defname> <definition>
This is the same as $define, except that the definition stops at the end
of the program line, without using an ending $enddef.
About the same as C's #undef <defname>
Sets a bunch of $defines from the properties in the /_defs/ propdir of the
given program. 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. For example,
'desc' would be replaced throughout the program with '"_/de" getpropstr'
NOTE: You cannot have a slash in a definition name. ie: The property
_defs/a/b:foo
will NOT make a definition named a/b.
By using this directive, the _defs/ directory on a MUF program can
be set at compile time.
$pubdef : Clears the _defs/ propdir on the program.
$pubdef <defname> Clears the _defs/<defname> prop on the prog.
$pubdef <defname> <rest_of_line> Sets _defs/<defname> prop to <rest_of_line>.
$pubdef \<defname> <rest_of_line> Sets _def/<defname> if not already set.
For example:
$pubdef tell me @ swap notify
would put a property named '_defs/tell' on the program object, with the
value 'me @ swap notify'. Def names cannot have ':' nor '/' in them.
Sets up an _defs/ prop on the program to call the specified function.
For example:
$libdef myfunc
would put a prop named '_defs/myfunc' on the program object, with the
value '<this_programs_dbref> "myfunc" call'
Ignores program _defs/ when compiling the program. Wizards programs can
use '$cleardefs ALL' to also ignore #0 _defs/ when compiling. This does
not affect macros, and internal _defs/ are always loaded no matter what.
This determines whether or not to compile optional sections of code,
depending on the existence of or value of certain $defined names.
The four accepted forms of the <condition> argument are:
DEFNAME Is true if DEFNAME was $defined earlier, whatever the value.
DEFNAME=VALUE Is true if DEFNAME exists and its value equals VALUE.
DEFNAME>VALUE Is true if DEFNAME exists and is greater than VALUE.
DEFNAME<VALUE Is true if DEFNAME exists and is less than VALUE.
The semantics of greater than and less than is the same as that used by
the strcmp string comparison command. There must be no spaces between the
DEFNAME, comparator, and VALUE. They must be run together as one word.
There is no >= or <= comparator available, so to make such a comparison
you need to use $ifndef with the opposite comparator. Ie, to check if
FOO is greater than or equal to 3, use:
$ifndef FOO<3
BAR
$enddef
Compiler directives are nestable also. For examples:
$ifdef __version>Muck2.2fb3.5
$def envprop .envprop
$endif
$define ploc
$ifdef proplocs
.proploc
$else
owner
$endif
$enddef
This determines whether or not to compile optional sections of code,
depending on the non-existence of or value of $defined names. $ifndef is
short for 'If NOT Defined' or 'If Not', so it compiles the first code
branch (before the optional $else), only if the <condition> is false.
The four accepted forms of the <condition> argument are:
DEFNAME Is true if DEFNAME was $defined earlier, whatever the value.
DEFNAME=VALUE Is true if DEFNAME exists and its value equals VALUE.
DEFNAME>VALUE Is true if DEFNAME exists and is greater than VALUE.
DEFNAME<VALUE Is true if DEFNAME exists and is less than VALUE.
The semantics of greater than and less than is the same as that used by the
strcmp string comparison command. There must be no spaces between the
DEFNAME, comparator, and VALUE. They must be run together as one word.
This determines whether or not to compile optional sections of code,
depending on the $version of the given program, which is stored in its
'_version' property. In the form '$ifver this' then this checks this
compiling program's $version. Otherwise, this checks the $version of
the program referenced by $regname or #dbref.
The <truebranch> will be compiled if the given program's $version
is greater than or equal to the given <float>, using a floating point
number comparison. Otherwise, the <falsebranch>, if given, will be
compiled.
This determines whether or not to compile optional sections of code,
depending on the $version of the given program, which is stored in its
'_version' property. In the form '$ifnver this' then this checks this
compiling program's $version. Otherwise, this checks the $version of
the program referenced by $regname or #dbref.
The <truebranch> will be compiled if the given program's $version
is less than the given <float>, using a floating point number comparison.
Otherwise, the <falsebranch>, if given, will be compiled.
This determines whether or not to compile optional sections of code,
depending on the $lib-version of the given program, which is stored in its
'_lib-version' property. In the form '$iflibver this' then this checks this
compiling program's $lib-version. Otherwise, this checks the $lib-version
of the program referenced by $regname or #dbref.
The <truebranch> will be compiled if the given program's $lib-version
is greater than or equal to the given <float>, using a floating point
number comparison. Otherwise, the <falsebranch>, if given, will be
compiled.
This determines whether or not to compile optional sections of code,
depending on the $lib-version of the given program, which is stored in its
'_lib-version' property. In the form '$ifnlibver this' then this checks this
compiling program's $lib-version. Otherwise, this checks the $lib-version
of the program referenced by $regname or #dbref.
The <truebranch> will be compiled if the given program's $lib-version
is less than the given <float>, using a floating point number comparison.
Otherwise, the <falsebranch>, if given, will be compiled.
This determines whether or not to compile optional sections of code,
depending on the existence of a given program.
The <truebranch> will be compiled if the given object exists and is a
program. Otherwise, the <falsebranch>, if given, will be compiled.
This determines whether or not to compile optional sections of code,
depending on the existence of a given program.
The <truebranch> will be compiled if the given object does not exist, or
if it is not a program. Otherwise, the <falsebranch>, if given, will be
compiled.
This determines whether or not to compile optional sections of code,
depending on the ability for the compiling program to call a given public
function on a given program.
If the given program is given as 'this', then this will check if the
given callable function was declared earlier in this compiling program.
The <truebranch> will be compiled if the given program exists, is a
program, and has a given callable function (declared with PUBLIC or WIZCALL)
that this compiling program has permission to call. Otherwise, the
<falsebranch>, if given, will be compiled.
This determines whether or not to compile optional sections of code,
depending on the ability for the compiling program to call a given public
function on a given program.
If the given program is given as 'this', then this will check if the
given callable function was declared earlier in this compiling program.
The <truebranch> will be compiled if the given program does not exist,
is not a program, or does not have a given callable function (declared with
PUBLIC or WIZCALL) that this compiling program has permission to call.
Otherwise, the <falsebranch>, if given, will be compiled.
Echos the given string to the screen of the person compiling the program.
Runs at compile-time.
Aborts compiling and prints out the error message.
You can 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.
Pops the top of the stack into oblivion.
Also see:
POPN
Pops the top i stack items.
Also see:
POP
Duplicates the item at the top of the stack.
Duplicates the top i stack items.
Also see:
DUP and
LDUP
Duplicates a stackrange on top of the stack.
Also see:
DUP and
DUPN
Takes objects x and y on the stack and reverses their order.
Duplicates the second-to-top thing on the stack. This is the same as 2 pick.
Rotates the top three things on the stack. This is equivalent to 3 rotate.
Rotates the top i things on the stack. Using a negative rotational
value rotates backwards.
Examples:
"a" "b" "c" "d" 4 rotate
would leave
"b" "c" "d" "a"
on the stack.
"a" "b" "c" "d" -4 rotate
would leave
"d" "a" "b" "c"
on the stack.
Also see:
ROT and
SWAP
Takes the i'th thing from the top of the stack and pushes it on the top.
1 pick is equivalent to dup, and 2 pick is equivalent to over.
Also see:
OVER and
PUT
Replaces the i'th item from the top of the stack with the value of ni.
The command sequence '1 put' is equivalent to 'swap pop'.
Example:
"a" "b" "c" "d" "e" 3 put
would return on the stack:
"a" "e" "c" "d"
Also see:
PICK
Reverses the order of the top i items on the stack.
Example:
"a" "b" "c" "d" "e" 4 reverse
would return on the stack:
"a" "e" "d" "c" "b"
Reverses the order of the top i stack items, leaving i.
Example:
"a" "b" "c" "d" "e" 4 lreverse
would return on the stack:
"a" "e" "d" "c" "b" 4
Returns the number of items currently on the stack.
Pushes a marker onto the stack, to be used with } or }list or }dict.
Finds the topmost marker in the stack, and counts how many stack items
are between it and the top of the stack. The marker is removed from the
stack, and the count is pushed onto the stack.
There is a global variable named ME that contains the dbref of the
player who invoked the program. The value of this variable is not
guaranteed to be secure, as another program could change the value of
ME then call your program. If you must be certain that the value of
the ME variable is correct, use the commands:
"me" match me !
The ME global variable is the same variable as '0 variable'
There is a global variable named LOC that contains the dbref of the
location of the player who invoked the program. The value of this
variable is not guaranteed to be secure, as another program could change
the value of LOC then call your program. If you must be certain that
the value of the LOC variable is correct, use the commands:
"me" match location loc !
The LOC global variable is the same variable as '1 variable'
There is a global variable named TRIGGER that contains the dbref of the
trigger object that invoked the process. The value of this variable is
not guaranteed to be secure, as another program could change the value of
TRIGGER then call your program. If you must be certain that the value of
the TRIGGER variable is correct, use the commands:
trig trigger !
The TRIGGER global variable is the same variable as '2 variable'
The value of TRIGGER will be #-1 for AUTOSTART programs,
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. The TRIGGER global variable is the same variable as '2 variable'
When used inside a function, a function-scoped variable is created.
This variable is local to each invocation of a given function; recursive
calls each get their own scoped variable dataspace. This variable type
is analogous to C's function-scoped variables. The use of function-scoped
variables is highly recomended to make functions more readable.
When used outside of a function, the compiler allows the use of <name>
as a global variable in all functions defined after the var declaration.
This variable dataspace is shared between ALL muf programs called in
this process. This means that if program A declares a global variable,
then calls program B, and program B also declares a global variable,
then changes its value, then the global variable declared in program A
will also have been changed. For this reason, this usage of VAR is
deprecated and shoud NOT be used. Use LVAR instead. This usage is only
kept around for backwards compatability with some old icky programs that
used this feature to pass data between some programs.
This must be used within a function. It declares a function-scoped
variable named <name> that then has its value set to the topmost stack
item. For example, the following program prints out "Hello World!":
: myfunction
"Hello World!" var! foo
me @ foo @ notify
;
This declares a variable as a program-local variable. If another program
calls this program, the values of the program-local variables will not be
changed in the calling program, even if the called program changes them.
This variable will be available to all functions defined later in the
program, after the lvar declaration. This variable's data is persistent
within this process. Ie: if program A calls program B, and program B sets
the value of this program-local variable, then returns to A, which then
calls B again, the value of this variable will still have the value it was
set to in the first call. The value is NOT persistent between different
processes. This variable type is analogous to C's global variables.
Retrieves variable v's value x.
Sets variable v's value to x.
Converts integer i to global variable reference v. Of the pre-defined
variables, `me' corresponds to integer 0, `loc' to 1, `trigger' to 2,
and 'command' to 3.
Thus:
me @
and
0 variable @
will do the same thing (returning the user's dbref). User-defined variables
are numbered sequentially starting at 4 by the compiler. Note that these
variable numbers can be used even if variables have not been formally
declared. This command has been deprecated, and is not recommended to use.
It's original purpose was to allow MUF to do small arrays. Since MUF now
has an intrinsic array stack item type, this should no longer be used.
Takes an integer and returns the respective program-local variable.
Similar to the 'variable' primitive. Use of this command is deprecated
and is not recommended. Use the array stack item type instead.
Compares two numbers and returns 1 if n1 is less than n2, and 0 otherwise.
Compares two numbers and returns 1 if n1 is greater than n2, and 0 otherwise.
Compares two numbers and returns 1 if n1 is equal to n2, and 0 otherwise.
Compares two numbers and returns 1 if n1 is less than or equal to n2,
and 0 otherwise.
Compares two numbers and returns 1 if n1 is greater than or equal to n2,
and 0 otherwise.
Returns true (1) if the top stack item is considered false. Returns
false (0) otherwise. The stack item can be of any type. For the various
types, here are their false values:
Integer 0
Float 0.0
DBRef #-1
String ""
Also see:
AND,
OR and
XOR
Returns true (1) if both of the top two stack items are considered true.
Returns false (0) otherwise. The stack items can be of any type. For the
various types, here are their false values:
Integer 0
Float 0.0
DBRef #-1
String ""
Also see:
NOT,
OR and
XOR
Returns true (1) if either of the top two stack items are considered true.
Returns false (0) otherwise. The stack items can be of any type. For the
various types, here are their false values:
Integer 0
Float 0.0
DBRef #-1
String ""
Returns true (1) if either of the top two stack items are considered true,
but NOT both of them. Returns false (0) otherwise. The stack items can be
of any type. For the various types, here are their false values:
Integer 0
Float 0.0
DBRef #-1
String ""
Also see:
NOT,
AND and
OR
Returns true if x is a string.
Returns true if x is a int.
Returns true if the item on the stack is a floating point value.
Returns true if x is a dbref.
Tests if stack item is an array. Returns i as 1 if so, 0 if
otherwise.
Tests if stack item is an array of dictionary type. Returns i as 1
if so, 0 if otherwise.
Returns true if the top stack item is a function address.
Returns true if the top stack item is a lock.
Examines boolean value x. If x is TRUE, the sequence of statements
after the 'if' up until the `then' (or until the `else' if it is
present) performed. If it is FALSE, then these statements are skipped,
and if an `else' is present, the statements between the `else' and the
`then' are performed. Control continues as usual at the statement
after the `then'. Note that checking the top of the stack actually
pops it, so if you want to re-use it, you should dup (see DUP) it
before the if. For every IF in a word, there MUST be a THEN, and
vice-versa. ELSE is optional.
Begins an ELSE block in an IF-ELSE-THEN code block. If the value
tested by the IF is false, then this code block will be executed.
Also see:
IF and
THEN
Denotes the end of an IF-THEN or IF-ELSE-THEN code block.
Also see:
IF and
ELSE
Pushed the address of the start of the previously defined function
FUNCNAME onto the stack. This can be useful for use with EXECUTE and
arrays to make a list of functions you can call by index, or for making
function callbacks.
Executes the function pointed to by the address a on the stack.
This function does NOT need to be in the same program as the function
that did the EXECUTE.
Also see:
'
The JMP primitive takes an address like those supplied by 'funcname and
moves execution to that point. It's one early way that was used to do
tail-recursion loops without as much overhead, and without failing due to
system stack overflows. It's mostly obsolete now, except that it's one
of the three or four internal primitives used to implement IF-ELSE-THEN and
BEGIN-WHILE-REPEAT loops and such. You shouldn't use JMP explicitly in
in modern MUF code, as it is deprecated. NOTE: Using JMP to jump into a
different function can have problems, and is not recommended.
Example of JMP as a tail-recursion optimization:
: countforever ( i -- )
1 +
dup intostr .tell
'countforever jmp
;
A better ways to do the same thing with looping primitives would be:
: countforever ( i -- )
begin
1 +
dup intostr .tell
repeat
;
Calls another program d. Program d will inherit the values of ME, LOC,
TRIGGER, and all other global variables. If used in the second form,
this will call the named PUBLIC function s in the given program d.
The called program will NOT share the same localvars as the caller,
unless the caller is calling itself.
Takes a program dbref to run d1, the trigger to use d2, and the top stack
item string and calls the program with the given string on the stack.
Returns when interpretation halts, which could be the result of an exit, an
error, or a primitive that suspends execution such as sleep or read.
Return value is the top item off the stack if successful exit, or a null
string for anything else.
Exits from the function currently being executed, returning control to
the calling function, at the statement immediately after the location of
the call (exiting the program if applicable).
Marks the beginning of BEGIN-UNTIL or BEGIN-REPEAT loops.
Marks the beginning of a iterative FOR loop, and initializes it with i1
as the start index, i2 as the end index, and i3 as the step. If i2 is less
then i1, or if i3 is negative and i2 is greater then i1, the entire loop is
skipped without executing. If i3 is 0 the loop will run infinitely until
some other condition causes an exit.
Marks the beginning of an iterative FOREACH loop, stepping through every
index/value pair in the array.
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
instruction after the WHILE.
Breaks out of the innermost loop. Jumps execution to the instruction
after the UNTIL or REPEAT for the current loop.
Jumps execution to the beginning of the current loop.
This marks the end of the current loop. Execution jumps to the instruction
after the matching BEGIN, FOREACH or FOR in a loop.
This marks the end of the current loop. If the value on top of the
stack is false, then execution jumps back to the instruction after
the matching BEGIN or FOR statement. If the value is true, it exits
the loop, and continues execution at the next instruction following
the UNTIL.
Loops, TRY-CATCH-ENDCATCH's, and IF-ELSE-THEN's can all be nested in
each other as much as you want.
The BEGIN, FOR, or FOREACH 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 back to the BEGIN or FOR statement.
UNTIL checks to see if the value on the stack is false. If it is, it
jumps back to the BEGIN or FOR 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 top value on the stack is false.
If it is, then execution breaks out of the innermost loop and resumes
after the matching REPEAT or UNTIL statement.
The CONTINUE statement causes the loop to jump back to the beginning
of its next iteration, after the BEGIN, FOR, or FOREACH.
The BREAK statement forces execution to break out of the innermost loop,
resuming after the matching REPEAT or UNTIL.
Note: You can nest loops complexly, but WHILE, BREAK, and CONTINUE
statements only refer to the innermost loop structure.
0 begin
dup 10 < while
1 +
me @ over intostr notify
repeat
How to count from 1 to 10 using a BEGIN-UNTIL loop:
0 begin
1 +
me @ over intostr notify
dup 10 =
until
How to count from 1 to 10 using a FOR-REPEAT loop:
1 10 1 for
intostr me @ swap notify
repeat
1 10 1 for
me @ swap intostr notify
repeat
Example of nested FOR loops:
1 5 1 for
"" swap 1 -1 for
intostr strcat
repeat
me @ swap notify
repeat
Example of a complex (if pointless) FOR loop:
10 -10 -2 for
me @ over intostr notify
dup -5 > while
dup 0 = if pop continue then
dup -3 = if pop break then
not
until
Example of a FOREACH loop:
{
"index1" "value1"
"index2" "value2"
"index3" "value3"
}dict
foreach
" = " swap strcat strcat me @ swap notify
repeat
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 (...this WHILE refer to the outer loop)
then
dup intostr
me @ swap notify
dup 1 = until pop (This UNTIL ends the outer loop)
Declares a previously defined 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
Declares a previously defined function to be callable from other programs,
as long as the calling program has wizbit permissions. 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
Returns true if the given program has a public or wizcall function that the
current program has permissions to call. Returns false, otherwise.
d must be a player object. s must be a string. Tells player d message
s. If s is null it will print nothing. This primitive will trigger
the _listen'er property on the object the message is sent to, unless
the program that would be run is the same as one one currently running.
d1 must be a room object, s must be a string. Tells everyone at
location d1 except object d2 message s. If object d2 is not a player
or NOTHING (#-1) all players are notified. If s is null it prints
nothing. NOTE: notify_except is now only an inserver $define. It is
translated to '1 swap notify_exclude'. Please see the man sections on
NOTIFY_EXCLUDE and DIRECTIVES for more information.
Displays the message s to all the players (or _listening objects),
excluding the n given players, in the given room. For 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. _listener's will not be triggered by a notify_exclude
if the program they would run is the same as the current program running.
Tells the interpreter that this process wants to be able to receive blank
lines from the READ primitive. If this is not executed, the process will
silently ignore blank ("") lines in READ. This only needs to be done once
per process, and isn't reversable.
Reads a string s from the user. This command should not be used in a
program that is locked (as opposed to linked) to an object, as the
lock will always fail and print the fail messages at read time. It
cannot be used in a program associated with a room object.
Acts like a timed READ call. If the user does not provide input within
the given number of seconds, the READ call will time-out and return a
false boolean, otherwise it returns a true boolean and the string value
entered. This is implemented as an in-server macro as follows:
"__tread" timer_start { "TIMER.__tread" "READ" }list event_waitfor
swap pop "READ" strcmp if "" 0 else read 1 "__tread" timer_stop then
Logs an arbitrary message to the user log file. (#defined in config.h
as USER_LOG, defaults to the "logs/user" file.) The log entry will be
formatted like:
Winged(#4023) [newaction.muf(#666)] 06/11/02 03:09:31: <string>
The program must be running at a mucker level at least equal to the @tune
value 'userlog_mlev' (defaults to 3) to write this log entry.
Converts variable, float, or dbref x to integer i.
This adds two numbers, n1 + n2. If both numbers are integers, an integer
will be returned. If one of them is a floating point number, then a float
will be returned. You can also use this on a dbref or a variable number,
so long as the second argument is an integer. In those cases, this will
return a dbref or variable number, respectively.
This subtracts two numbers, n1 - n2. If both numbers are integers, an
integer will be returned. If one of them is a floating point number,
then a float will be returned. You can also use this on a dbref or a
variable number, so long as the second argument is an integer. In those
cases, this will return a dbref or variable number, respectively.
This multiplies two numbers, n1 * n2. If both numbers are integers, an
integer will be returned. If one of them is a floating point number,
then a float will be returned. You can also use this on a dbref or a
variable number, so long as the second argument is an integer. In those
cases, this will return a dbref or variable number, respectively.
This divides two numbers, n1 / n2. If both numbers are integers, an
integer will be returned. If one of them is a floating point number,
then a float will be returned. You can also use this on a dbref or a
variable number, so long as the second argument is an integer. In those
cases, this will return a dbref or variable number, respectively.
This returns the integer modulo (remainder) of the division of two
numbers, n1 % n2. Floats cannot use the % modulo function. For them,
use either the FMOD or MODF primitives.
If given an integer, float, or dbref, adds 1 to it, and returns the result.
If given a variable containing an integer, float, or dbref, adds 1 to the
value stored in the variable, and returns nothing.
Also see:
--
If given an integer, float, or dbref, this subtracts 1 from it, and
returns the result. If given a variable containing an integer, float,
or dbref, this subtracts 1 from the value stored in the variable, and
returns nothing.
Also see:
++
Given an integer, returns its absolute value.
Given an integer, returns 1 if positive, -1 if negative, and 0 if 0.
Returns the the current SRAND seed string.
Sets the seed for SRAND. Only the first thirty-two characters are
significant. If SRAND is called before SETSEED is called, then SRAND
is seeded with a semi-random value.
Generates a seeded random number.
Returns a random integer from 0 to the MAXINT of the system running the MUCK.
In general this number is (2^31)-1 or 2,147,483,647 (2.1 billion). This is
based on the standard C random() function, so it's not very secure.
Does a mathematical bitwise or.
Does a mathematical bitwise exclusive or.
Does a mathematical bitwise and.
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 >>.
Converts integer to floating point type.
Returns the value of Pi.
Returns the value of an Infinite result. Most functions will not
accept this value as a legal input.
Returns the smallest number such that 1.0 + Epsilon is distinct from 1.0
in the internal representation for floating point numbers. This is the
precision error. This is useful when comparing that two numbers are equal
to within the precision of the system. ie:
float1 @ float2 @ - fabs epsilon < if "Equivalent" then
When you are working with numbers that have exponent parts that may not be
near e+00, you should do a relative comparison instead:
float1 @ float2 @ - float1 @ / fabs epsilon < if "Equivalent" then
Converts a floating point number into a string. Always includes the decimal
point. FTOSTR can return either the xxx.yyy form or the x.yyyEzz form of
a float, depending on which would give the shortest string length.
Converts a string into a floating point type.
STRTOF recognizes most standard forms of floating point representation,
including the xxx.yyy and x.yyyEzz forms.
Returns the absolute value of the float f.
Returns the next highest integer, as a floating point type.
Returns the next lowest integer number, as a floating point type.
Rounds the floating point number to the precision requested, given as the
number of places to the right of the decimal point. ie: '1.111 1 round'
would leave '1.1' on the stack, while '1.111 0 round' would leave '1.0'.
Negative i values denote places to the left of the decimal place. ie:
'1234.56 -2 round' would return '1200.0' on the stack.
Returns the floating point remainder of f1 divided by f2. (f1/f2)
The modf primitive breaks f into an integral part and a fractional part,
each of which has the same sign as f. Both returned values are floats.
fi is the integral part, while ff is the fractional part.
Returns a float's square root. Expects a value greater than or equal
to zero.
Returns the cosine of a float. Only operates in the range of -Pi/4 to Pi/4.
Returns the inverse cosine of a float. Only operates within the range
from 0 to Pi.
Returns the sine of a float. Only operates within the range of -Pi/4
to Pi/4.
Returns the inverse sine of a float. Only operates within the range
from -Pi/2 to Pi/2.
Returns the tangent of a float. Only operates within the range of
-Pi/4 to Pi/4.
Returns the inverse tangent of a float. Only operates within the range
from -Pi/2 to Pi/2.
Returns the inverse tangent of (fy / fx), taking into account the signs
of both values, and avoiding problems with DIVBY0. This is useful to
get an angle from X-Y coordinates.
Returns the natural log of float f. Requires a value greater than zero.
Very small values will return INF.
Returns the value of e raised to the power of the passed float.
Returns the log base 10 of float f. Requires a value greater than zero.
Very small values will return INF.
Returns f1 to the power of f2. If f1 is zero, f2 must be greater than
zero. If f1 is less than zero, f2 must be an integer value.
Returns three floats, being the differences of fx1 - fx2, fy1 - fy2, and
fz1 - fz2, respectively.
Returns the distance of the XYZ coordinate (fx,fy,fz) from the origin.
To do a 2D distance calculation, simply use a Z value (fz) of 0.
Converts the XYZ coordinate (fx, fy, fz) to the spherical polar coordinate
(fr, ft, fp). fr is the radius, ft is theta (the plane angle), and fp is phi
(the elevation angle) To do 2D X-Y to radius and angle conversion, simply use
a Z coordinate (fz) of 0, and discard phi (fp).
Converts the spherical polar coordinate (fr, ft, fp) to the XYZ coordinate
(fx, fy, fz). fr is the radius, ft is theta (the plane angle), and fp is phi
(the elevation angle) To do 2D radius and angle to X-Y conversion, simply use
a phi angle (fp) of 0, and discard Z (fz).
Returns a random floating point number between 0 and 1.
Clears all error flags for floating point math operations.
Clears a specific error flag for floating point math operations.
Returns true if any of the floating point error flags have been set. In
most cases, an error condition in a math operation will return a zero value
(except in the case of integer math, which will wrap around on an overflow
or underflow condition). It is possible to poll for error conditions after
every math operation, or when a '0' result is found.
The following is a list of the current Error Flags:
DIV_ZERO - (0) Division by zero attempted.
NAN - (1) Result was not a number.
IMAGINARY - (2) Result would be imaginary.
FBOUNDS - (3) Floating-point inputs were