MUF Reference Manual

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


MUF REFERENCE MANUAL:

This manual was compiled largely from the original MUF reference manual,
with help from Black_Dougal. It is intended more as a reference work than as
a tutorial, and should be current through TinyMUCK 2.1.1. Please feel free to
e-mail me any errata or addenda at rawdon@rex.cs.tulane.edu.    - Jethro

Updated completely for TinyMUCK release 2.2 by me -- ChupChup

Updated for TinyMUCK2.2fb2.3 by foxen@netcom.com

DICTIONARY OF MUF EDITOR COMMANDS
---------------------------------

See @PROG and @EDIT in the MUCK Reference Sheets for information about
enterting the editor.

<number> i
Enter insert mode before line #i. Any number of lines may be contiguously
inserted.  The old line #i will become the first line after the inserted
lines.  Blank lines are ignored and do not become part of the program.
Entering the character `.' (period) alone on a line (not preceded or
followed by any spaces) exits insert mode. The `.' does not become a line.

<number1> <number2> l
Display all lines from <number1> to <number2> inclusive. If only one <number>
is given, only that line will be displayed.

<number1> <number2> d
Delete all lines from <number1> to <number2> inclusive. If only one <number>
is given, only that line will be deleted.

c
Compile the program you are editing. This must be done before a program will
run properly.

u
Unassemble program. This was used to test MUF during its development. It
has no real use for programmers.

n
Toggle display of numbers in program listings.

q
Quit from the editor. @Q may also be used to do this.

<name1> <name2> s
Show macros in long format: name of macro, name of the person who entered it,
and the body of the macro.  `a z s' will show all macros, for instance.

<name1> <name2> a
Abridged macro display.  Shows only the names of macros.

<programnumber> v
Views the first lines of a program, if each begins with ( and ends with ).
This can be done only for programs you own, or that are LINK_OK.

<programnumber> p
lists all of the functions declared Public in the given program.  This has
the same restrictions as View does.  If no argument is given, it lists the
public functions of the program you are editing, if it is compilable.

DICTIONARY OF MUF PRIMITIVES
----------------------------

CONVENTIONS:
d: database reference; i: integer; s: string; v: variable; a: function address;
x, y: Any of the above.

+ - * / % ( i1 i2 -- i )
These words perform arithmetic operations on numbers. `+' = addition
(i1 + i2); `-' = subtraction (i1 - i2); `*' = multiplication (i1 times
i2, or i1 * i2); `/' = division (i1 divided by i2, or i1 / i2) with
integer division truncation of fractions; `%' = modulo (remainder of
i1 / i2, or i1 % i2) Please note: all these operations may also be
performed where i1 is a variable type.  This is mainly useful in
calculating an offset for a variable array.

< > = <= >= ( i1 i2 -- i )
Performs relational operations on integers i1 and i2. These return i
as 1 if the expression is true, and i as 0 otherwise.

@ ( v -- x )
Retrieves variable v's value x.

! ( x v -- )
Sets variable v's value to x.

addpennies ( d i -- )
d must be a player or thing object.  Adds i pennies to object d.
Without Wizard permissions, addpennies may only give players pennies,
limited to between zero and MAX_PENNIES.

addprop ( d s1 s2 i -- )
Sets property associated with s1 in object d.  Note that if s2 is null
"", then i will be used.  Otherwise, s2 is always used.  All four
parameters must be on the stack; none may be omitted.  If the
effective user of the program does not control the object in question
and the property begins with an underscore `_', the property cannot be
changed.  The same goes for properties beginning with a dot `.' which
cannot be read without permission.  If you store values, you must
ensure that it they are never zero.  Otherwise, when the user stores a
non-zero number into the string field, (users may only access string
fields) the next time TinyMUCK is dumped and loaded up again, the
value field will be replaced with atoi(string field).  If it is
necessary to store zero, it is safer to just add 1 to everything.
Properties whose names starts with ~ or @ cannot be changed by the
player with @set, and @props cannot even be seen in an examine.
(Wizards, however, can @set and examine both types of properties)

and ( x y -- i )
Performs the boolean `and' operation on x and y, returning i as 1 if
both i1 and i2 are TRUE, and returning i as 0 otherwise.

atoi ( s -- i )
Turns string s into integer i.  If s is not a string, then 0 is pushed
onto the stack.

awake? ( s -- i )
Takes a player dbref, and returns the number of connections that player
has to the server, or 0 if they are not online.

begin ( -- )...until (i -- ), begin ( -- )...while (i -- )...repeat ( -- )
The word 'begin' marks the beginning of a loop structure.  There are
two types of loop structures that you can make with it.  The first is
the begin-until loop, which uses the syntax of 'begin <commands>
<conditional> until'.  Basically, it will execute the commands and teh
conditional statements each time through the loop.  It expects the
conditionals to leave a value on the stack.  If the value is false, the
execution jumps back up to after the begin statement.  If the value is
true, the execution falls through to the statement after the until
statement, exiting the loop.  One example:
    10 begin
	    me @ over intostr notify
	    1 - dup not
    until pop
The other type of loop is the begin-while-repeat loop, with the syntax
of: 'begin <conditional> while <commands> repeat'.  Here, the
conditional statements leave a value on the stack where a falso value
exits the loop, and execution resumes after the repeat statement, and a
true value will continue execution after the while statement, staying
within the loop.  The repeat statement forces execution to jump to the
beginning of the loop.  One example:
    10 begin
	    dup while
	    me @ over intostr notify
	    1 -
    repeat pop
In general, begin-until loops are slightly more efficient than
begin-while-repeat loops, but they always must execute the loop at
least once.

bitand, bitor, bitxor, bitshift (i1 i2 -- i)
Performs bitwise operations with the given integers, and returns the results.
Bitshift shifts the i1 integer, i2 bits to the left if i2 is positive, or, if
i2 is negative, it shifts the absolute amount of bits to the right.

call ( d -- ?? )
Calls another program d.  d must have been compiled already. d will
inherit the values of ME, LOC, TRIGGER, and all other variables.

call ( d s -- ?? )
Call is overloaded, such that if there is a string on top of the stack,
it will call the public function of that name in teh preogram dbref given.
Otherwise, this is like a regular call.

caller ( -- d)
returns the dbref of the program or trigger that started this program running.
This will contain a #-1 if run from a QUEUEd event.  If a program called
this one, then it contains that program's dbref.  Otherwise, it will return
the dbref of the original trigger.

contents ( d -- d' )
Pushes the dbref of the first thing contained by d.  This dbref can
then be referenced by `next' to cycle through all of the contents of
d.  d may be a room or a player.

copyobj ( d -- d' )
Creates a new object (returning d' on top of the stack), that is a
copy of object d. Each program is allowed to create only one new
object per run.

conboot (i -- )
Disconnects the connection referred to by the connection number on top
of the stack.  This is a wizbit only command.  NOTE: this causes all the
connections with connection number greater than it to decrement their
connection number by one.

concount ( -- i)
Returns the number of connections to the server.  A connection number is
an integer between 1 and this number.

condbref (i -- d)
Takes a connection number and returns the dbref of the player connected to
it.

conhost (i -- s)
Takes a connection number, and returns a string that contains the name
of the host that the player is connected to the server from.  This is a
wizbit only primitive.

conidle (i -- i)
Takes a connection number and returns the length in time (in seconds) that
that connection is idle.

connotify (i s -- )
Takes a connection number and a string.  It sends the string to only the
given connection number, (as opposed to notify which sends a string to all
the connections a player has.)

contime (i -- i)
Takes a connection number and returns the length in time (in seconds) that
that connection has been connected to the server.

dbcmp ( d1 d2 -- i )
Performs comparison of database objects d1 and d2. If they are the
same object, then i is 1, otherwise i is 0.

dbref ( i -- d )
Converts integer i to object reference d.

desc ( d -- s )
Takes object d and returns its description (@desc) string field.

drop ( d -- s )
Takes object d and returns its drop (@drop) string field.

dup ( x -- x x )
Duplicates the item at the top of the stack.

execute ( a -- ?? )
Executes the function pointed to by the address a on the stack.

exit ( -- )
Exits from the word currently being executed, returning control to the calling
word, at the statement immediately after the invokation of the call (exiting
the program if applicable).

exit? ( d -- i )
Returns 1 if object d is an exit object, 0 if otherwise.
See also player?, program?, room?, thing?, ok?.

exits ( d -- d' )
Returns the first exit in the linked exit list of room/player/object d.
This list can be transversed with `next'.

explode ( s1 s2 -- ... i )
s2 is the delimiter string, and s1 is the target string, which will be
fragmented, with i pushed on top of the stack as the number of strings
s1 was broken into.  For instance:
    "Hello world" " " explode
will result in
    "world" "Hello" 2
on the stack.  (Note that if you read these items off in order, they
will come out "Hello" first, then "world".)  For TinyMUCK 2.2, s2 may
be any length.  But "" (null string) is not an acceptable string for
parameter s2.

fail ( d -- s )
Takes object d and returns its fail (@fail) string field.

flag? ( d s -- i )
Reads the flag of object d, specified by s, and returns its state: 1 =
on; 0 = off.  Different flags may be supported in different
installations.  flag? returns 0 for unsupported or unrecognized flags.

getlink ( d -- d' )
Returns what object d is linked to, or #-1 if d is unlinked.  The
interpretation of link depends on the type of d: for an exit, returns
the room, player, program, action, or thing that the exit is linked
to.  For a player, program, or thing, it returns its `home', and for
rooms returns the drop-to.

getpropstr ( d s -- s )
s must be a string. Retrieves string associated with property s in
object d.  If the property is cleared, "" (null string) is returned.

getpropval ( d s -- i )
s must be a string. Retrieves the integer value i associated with
property s in object d. If the property is cleared, 0 is returned.

if ... [ else ... ] then ( x -- )
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.

instr ( s s1 -- i )
Returns the first occurrence of string s1 in string s, or -1 if s1 is
not found.  See also rinstr.

int ( x -- i )
Converts variable or object x to integer i.

intostr ( x -- s )
x must be an integer or a dbref. Converts x into string s.

jmp ( a -- )
Jumps to address a.  Used internally by the compiler for constructing
else and loop clauses, but jmp can also be generated by user code.

location ( d -- d' )
Returns location of object d as object d'.

match ( s -- d )
Takes string s, first checks all objects in the user's inventory, then
checks all objects in the current room, as well as all exits that the
player may use, and returns object d which contains string s.  If
nothing is found, d = #-1. If ambiguous, d = #-2. If HOME, d = #-3.

moveto ( d1 d2 -- )
Moves object d1 to object d2.
MOVETO is affected by the following rules:
    a) If the object being moved is !JUMP_OK and is it being moved by someone
       other than the object's owner, then the moveto fails.
    b) If the object being moved is a person and either the source or
       destination rooms (if not owned by the person being moved) are
       !JUMP_OK, the moveto fails.
    c) If the object being moved is not a player, is owned by the owner of
       either the source or destination rooms, and either room where the
       ownership matches is !JUMP_OK, the moveto fails.
The moveto succeeds under any other circumstances.  MOVETO rules
follow the permissions of the current effective userid.

name ( d -- s )
Takes object d and returns its name (@name) string field.

newobject, newroom, newexit ( d s -- d )
These three create an object of the appropriate type, with name s and
located in object d, and return the dbref of the new item.  For rooms,
the d parameter is their parent room.  For exits, it is where they are
attached.  For Objects (Things), it is their location.  The new objects
will be owned by the player running the program.  These are wizbit
primitives only.

next ( d -- d' )
Takes object d and returns the next thing in the linked contents/exits
list of d's location.

not ( x -- i )
Performs the boolean `not' operation on x, returning i as 1 if x is
FALSE, and returning i as 0 otherwise.

notify ( d s -- )
d must be a player object. s must be a string. Tells player d message
s.  If s is null it will print nothing.

notify_except ( d1 d2 s -- )
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.

number? ( s -- i )
Returns 1 if string on top of the stack contains a number. Otherwise
returns 0.

odrop ( d -- s )
Takes object d and returns its odrop (@odrop) string field.

ofail ( d -- s )
Takes object d and returns its ofail (@ofail) string field.

ok? ( x -- i )
Takes x and returns 1 if x is a type dbref, as well as 0 or above,
below the top of the database, and is not an object of type garbage.
See also exit?, player?, program?, thing?.

or ( x y -- i )
Performs the boolean `or' operation on x and y. Returns i as 1 if
either x or y is TRUE, returns i as 0 otherwise.

osucc ( d -- s )
Takes object d and returns its osuccess (@osucc) string field.

over ( x y -- x y x )
Duplicates the second-to-top thing on the stack.  This is the same as 2 pick.

owner ( d -- d' )
d is any database object. Returns d', the player object that owns d.
If d is a player, d' will be the same as d.

pennies ( d -- i )
Gets the amount of pennies player object d has, or the penny value of thing d.

pick ( ni ... n1 i -- ni ... n1 ni )
Takes the i'th thing from the top of the stack and pushes it on the top.
1 pick is equivalent to swap, and 2 pick is equivalent to over.

player? ( d -- i )
Returns 1 if object d is a player object, otherwise returns 0.
See also program?, room?, thing?, exit?, ok?.

pop ( x -- )
Pops the top of the stack into oblivion.

program ( d -- )
Internal instruction used to set permissions on called programs.
Cannot be generated directly by user code.

program? ( d -- i )
Returns 1 if object d is a program, otherwise returns 0.
See also player?, room?, thing?, exit?, ok?.

pronoun_sub ( d s -- s' )
Takes database object d and substitutes string s according to o-message
rules.  For example:
  me @ "%N has lost %p marbles." pronoun_sub
would return:
  "Igor has lost his marbles."
if the player's name was Igor and his sex were male.
d does not have to be a player for the substitutions to work.

random ( -- i )
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).

read ( -- s )
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.

remove_prop ( d s -- )
Removes property s from object d.  If the property begins with an
underscore, `_' or a dot `.', and the effective user does not have
permission on that object, the call fails.

repeat ( -- )
See BEGIN.

rinstr ( s s1 -- i )
Returns the last occurrence of string s1 in string s, or -1 if s1 is
not found.  See also instr.

rmatch ( d s -- d' )
Takes string s, checks all objects and actions associated with object
d, and returns object d' which matches that string.  For example,
matches actions and inventory objects for a player object, actions on
a thing object, etc.  If nothing is found, d' = #-1.  if ambiguous, d'
= #-2. If HOME, d' = #-3.

room? ( d -- i )
Returns 1 if object d is a room, otherwise returns 0.
See also player?, program?, thing?, exit?, ok?.

rot ( x y z -- y z x )
Rotates the top three things on the stack.  This is equivalent to 3 rotate.

rotate ( ni ... n1 i -- n(i-1) ... n1 ni )
Rotates the top i things on the stack.

set ( d s -- )
Sets flag s to object d.  Currently settable things are: abode, chown,
dark, haven, jump, link, sticky.  (haven and abode are not available
in some places.)  Boolean operations (e.g. `!abode') work as expected.

setdesc setdrop setfail setname setodrop setofail setosucc setsucc ( d s -- )
Takes object d, and sets the string field specified to s. A program
may only set string fields of objects that are owned by the effective
user of the program, or any object if the program is Wizard.

strcat ( s1 s2 -- s )
Concatenates two strings s1 and s2 and pushes the result s = s1s2 onto the
stack.

strcmp ( s1 s2 -- i )
Compares strings s1 and s2. Returns i as 0 if they are equal,
otherwise returns i as the difference between the first non-matching
character in the strings.  For example, "a" "z" strcmp returns 25.
This function is case sensitive, unlike stringcmp.
See also strncmp.

strcut ( s i -- s1 s2 )
Cuts string s after its i'th character.  For example,
   "Foobar" 3 strcut
returns
   "Foo" "bar"
If i is zero or greater than the length of s, returns a null string in
the first or second position, respectively.

stringcmp ( s1 s2 -- i )
Compares strings s1 and s2. Returns i as 0 if they are equal,
otherwise returns i as the difference between the first non-matching
character in the strings.  For example, "a" "z" stringcmp returns 25.
This function is not case sensitive, unlike strcmp.

strlen ( s -- i )
Returns the length of string s.

strncmp ( s i -- i' )
Compares the first i characters in string s.  Return value is like strcmp.

subst ( s1 s2 s3 -- s )
s1 is the string to operate on, s2 is the string to change all occurences
of s3 into, and s is resultant string.  For example:
    "HEY_YOU_THIS_IS" " " "_" subst
results in
    "HEY YOU THIS IS"
s2 and s3 may be of any length in TinyMUCK 2.2.

succ ( d -- s )
Takes object d and returns its success (@succ) string field s.

swap ( x y -- y x )
Takes objects x and y on the stack and reverses their order.

then ( -- )
See IF.

thing? ( d -- i )
Returns i as 1 if object d is a thing, otherwise returns i as 0.
See also player?, program?, room?, exit?, ok?.

time ( -- s m h )
Returns the time of day as integers on the stack, seconds, then minutes,
then hours.

until (i -- )
See BEGIN.

var <name>
Var is not a `true' primitive in that it must always be used outside
words and does not alter the stack in any way. When the compiler sees
a `var' statement, it allows the use of <name> as a variable in all
words sequentially defined after the var declaration. See VARIABLES in
the encyclopedia.

variable ( i -- v )
Converts integer i to variable reference v. Of the pre-defined variables,
`me' corresponds to integer 0, `loc' to 1, and `trigger' to 2. Thus:
     me @
and
     0 variable @
will do the same thing (returning the user's dbref). User-defined variables
are numbered sequentially starting at 3 by the compiler. Note that these
variable numbers can be used even if variables have not been formally
declared, making implementation of such things as arrays conveniently easy.
See @, !, and VAR.

version ( -- s)
This returns a string containing the server's version.  For 2.2fb2.3, it
returns the string "Muck 2.2fb2.3"

while (i -- )
See BEGIN.


ENCYCLOPEDIA OF MUF TERMS
-------------------------

ADDRESSES:
     Each function in MUF has an address in memory.  This address can
be pushed on the stack with the construct: 'function.  Thus:
  'foobar
will push a pointer to foobar on the stack.  It can now be put in a
variable, dup'ed, pop'ed, anything.  To call the function pointed
to by the address, use the EXECUTE primitive.  In actuality,
"'function EXECUTE" is the same as "function".

@Q:
     If a program user enters this in response to a MUF prompt
(e.g. from a read statement), the program will be exited. Also, typing
@Q while in the editor will exit the editor, the same as `q' will.
If a program is running in FOREGROUND mode, then the user can also use
@Q to quit it and begin entering commands again.

COMMAND-LINE ARGUMENTS:
     This only applies to exits that are linked to a program, not
for objects that are locked to a program or call the program by @#.
     When a program is invoked by a player, this may be done with a
command-line argument. This argument is pushed on the stack before the
program is executed.  For example, if an exit "get" is linked to a
program, typing "get flower" will invoke the program with the argument
"flower" pushed on the stack. Arguments are always strings - never
integers.
     At invocation time, TinyMUCK will examine all exits in the
room location of the user and attempt to find the exit with the
longest name which will match a leftmost substring of the invocation
string. For example, if the user types the invocation string "get
flower", TinyMUCK will match an exit named "get flower" before
matching "get". The remainder of the invocation string is pushed on
the stack as one object. Thus, if "eat jelly doughnut" is matched with
"eat", "jelly doughnut" will be pushed. explode can be used to
separate "jelly" and "doughnut".
     TinyMUCK searches for exit matches in this order: room exits,
room contents exits, player inventory exits, player exits.
     Even if an exact match is found (i.e., an exit named with the
precise invocation string), a null string ("") is pushed on the stack.
Thus, the stack ALWAYS has at least one element atop it at the
begining of ANY program's execution.  See EXECUTION, LINKING, LOCKING,
and, in the dictionary, EXPLODE.

COMMENTS:
     Comments in MUF are surrounded by parentheses. Any characters
in a program between two parentheses (e.g. `(argle)') will be ignored
by the compiler, and do not count as part of the program.

DBREF:
     This stands for "database reference". It refers directly to an
object in the TinyMUCK database. An integer is not an acceptable
substitute, but the primitive dbref (q.v. in the dictionary) will
convert an integer on top of the stack into a dbref.

EXECUTION:
     If a program has had an exit linked to it or had an object
locked to it, then whenever someone tries to use that object, it may
be executed (see LINKING and LOCKING for more details).
     If a program is executed, the last word sequentially defined
in the program is executed. Other words (or, indeed, other programs)
may be executed by that word, or by words invoked by that word, and so
on. If a word is not invoked in the sequential course of execution, it
will never be executed.
     Whenever a word is executed, each statement in it will be
executed in sequence, from first to last. Note that statements such as
IF...THEN and EXIT may alter this flow of execution, but these are
exceptions to the rule.
     When a program is initially executed by an exit that is linked
to it, at least one word will always be on top of the stack. See
COMMAND-LINE ARGUMENTS for more details. For programs executed by a
locked object, in general the stack will be initially empty.
See also STATEMENTS and WORDS.

EXITS:
     Note that since you can both link and lock (see LINKING and
LOCKING) an exit to a program, you may therefore have two programs
executed per exit.

HOME:
     Dbref #-3 on the stack always refers to the dbref of the home
of a thing or player object.

ITERATION:
  This can be accomplished through recursion or looping structures. One
way to do this is to use a variable as a counter. An example of iteration
(also known as looping) is given at the end of these documents.
See RECURSION.

LINKING:
  You may @link exits (but nothing else) to a program. A program will then
execute every time a player goes through that exit. Multiple exits may be
linked to a single program. See EXECUTION, and various entries in the MUCK
Reference Sheets including @ACTION, @LINK, @OPEN, ACTIONS and LINKING.

LOCKING:
  You may @lock rooms, programs, exits, things or players to a
program. A program will then execute every time a player TRIES to go
through that exit or pick up that thing or look at that room. The
program may define whether or not the object may be picked up or the
exit traveled through. This is done by pushing 1 on top of the stack
before the program terminates to indicate success, or pushing 0 to
indicate failure. See EXECUTION and LINKING.

PROPERTIES:
  All rooms, players and things have properties. These may be set by either
players or programs. However, players may only set properties to strings,
while programs may set them to either strings or integers. Thus, things
such as hit points, dollars, strength, etc., can be set.
  Remember, though, that players can always `@set me = :' which erases all
their properties. Be prepared to always set a default value on properties.
  The value 0 should never be stored in a property.
  See ADDPROP, GETPROPSTR, GET PROPVAL, and REMOVE_PROP in the dictionary, as
well as PROPERTIES in the MUCK Reference Sheets.

RECURSION:
  A word calling itself is called a recursive call. Such calls are best
handled inside the if part of an if-then block, since there should always
be an "escape clause" at which the recursion terminates. The subtleties of
recursion are outside the scope of these documents. I suggest you find a
book on the computer language Pascal to better familiarize yourself with
the concept. See WORDS, and, in the dictionary, CALL.

STACK:
In MUF, all statements are pushed on the stack when a running program reaches
them during execution, except primitives and user-defined words, which are
executed, and variables, whose addresses are pushed on the stack (and may be
operated on by the @ and ! primitives - see the dictionary). The maximum
number of elements that can be pushed on the stack is about 500. See
EXECUTION, STATEMENTS, VARIABLES and WORDS.

STATEMENTS:
  A statement is a discrete sequence of characters. Any string of characters
between double-quotes (e.g. "Hello. How are you?") is a statement. Without
quotes, any string of characters between spaces is a statement. (E.g.,
`Hello.' is a statement. `Hello there.' is two statements.) See STACK and
WORDS.

USER:
     The person using the program (as opposed to the programmer).
Non-setuid programs run according to the permissions of the user
rather than the programmer who wrote owns the program.  The variables
ME and LOC refer to the user. See VARIABLES.

VARIABLES:
     Usually, variables are not needed. A program can simply push
and pop things from the stack. However, `real' variables may be
defined, which can make program writing much easier. They MUST be
declared outside of words using the `var' primitive (they are
therefore global to all words in a program).  When a variable name is
a program statement, its address is pushed on the stack. The program
can then use the primitive `@' to retrieve is value, or `!'  to load a
value into it.
     The variables ME, LOC and TRIGGER are pre-defined in MUF. ME
stores the dbref of the program's user. LOC stores the dbref of his
location.  TRIGGER stores the dbref of the exit/thing which caused the
program to be executed.  See USER, WORDS, and, in the dictionary, @,
!, VAR and VARIABLE.

WORDS:
     A word in MUF begins with a colon (`:') and ends with a
semicolon (`;').  The statement after the colon is the name of the
word, and the remaining statements are the actual executed code of the
word.  Thus, a word's form is:
        : {word name} {body of word} ;
     Obviously, a program may contain many words. Calling a word is
accomplished by including its name in a word. A word may not be called
before it has been defined, though a word can call itself.
See EXECUTION, RECURSION, STATEMENTS, and, in the dictionary, CALL.


COMMON MUF EXECUTION ERRORS
---------------------------

Below is a list of all known errors which can arise when running a MUF
program, with brief descriptions. Input on how to make this list more
useful would be appreciated.


ADDPENNIES: would exceed MAX_PENNIES.
All MUCKs have a value MAX_PENNIES above which the addpennies
primitive cannot add more pennies to a player's penny count.

COPYOBJ: Invalid object.
The object trying to be copied is invalid in some way.

Program not compiled.
All programs must be compiled before they can run. This error could occur
when a program is triggered or called and has not been compiled.

SETNAME: Permission denied.
Since renaming a player requires that the player's password may be supplied,
MUF disallows this.

MOVETO: object can't be moved.
Self explanatory. The object being moved is not JUMP_OK.

MOVETO: source (or destination) not JUMP_OK
Under certain circumstances, when a MOVETO is attempted, one or both
of these rooms or players must be set JUMP_OK for the command to
succeed. See MOVETO in the dictionary.

Non-<type> argument:
The specified command requires an argument of the specified <type> as one of
its parameters, and the item on the stack in the position of that parameter is
not of that <type>. Possible types that may be mismatched include: integer,
object, player, room, string, variable, address.
There are other errors which are similar to this error. These include:
-   argument is an exit		  (MOVETO)
-   invalid argument type	  (Arithmetic, Comparison, DBCMP, INT,
				  CONTENTS, flag retreive, string field
				  retreive and set, SET, RMATCH)
-   invalid object		  (Flag retreive)
-   invalid object type		  (COPYOBJ, MOVETO)

Permission denied:
The problem here probably has to do with ownership of the object being
acted upon. This could apply to MOVETO, SET<string field> or SET.

Program internal error:
The program has been compiled improperly or the compiled code has been
corrupted.  This should never happen.

Stack Overflow:
An attempt was made to push an element on the stack when the stack was full.

Stack Underflow:
An attempt was made to pop an element from the stack when the stack was empty.


Examples of Basic MUF Programming Techniques
--------------------------------------------

A very simple program to add 2 and 3 and print the result to the user. Note
that the result must be converted to a string before the notify primitive.
(Tells the user the sum of two and three                             )
: simple
  2 3 +                         (Add 2 + 3                           )
  intostr                       (Convert to string                   )
  me @ swap                     (Order of the notify primitive       )
  notify                        (  necessitates the swap             )
;

---
A simple example of the if-then primitive. This word looks at the top
of the stack and prints "Hello!" if it is zero, and "Goodbye..." otherwise.
Note the inclusion of the 'not' primitive to do this.
: greeting
  not                           (Change logical value of top of stack)
  if                            (Check top of stack                  )
    "Hello!"                    (If it is nonzero, use "Hello"       )
  else
	"Goodbye..."                (otherwise, if it is zero, use "Goodbye..." )
  then
  me @ swap notify              (Show the appropriate string to the player)
;

---
A simple tail-recursion loop:

(This word, when called with a number on top of the stack, will print)
(out 'Hello world!" to the user that number of times                 )
: tail-recurser
  dup 0 <=
  if
    pop exit                     (Clean up stack and exit if done    )
  then
  me @ "Hello world!" notify     (Print "Hello world!" to user       )
  1 -                            (Subtract one from counter          )
  tail-recurser                  (Recursive call to iterator         )
;

---
An alternate version of the above word, using the begin-while-repeat
looping structure.

: iterator (i {count} -- )
  begin
    dup 0 > while                (Terminate if counter <= 0          )
    me @ "Hello world!" notify   (Print "Hello world!" to user       )
    1 -                          (Decrement counter                  )
  repeat                         (repeat loop from after the begin   )
  pop                            (Clean up the stack                 )
;

---
An alternate of the above, using a begin-until loop.  This will always
print out "Hello world!" at least once.

: iterator-2  (i {count} -- )
  begin
	me @ "Hello world!" notify   (Prints "Hello World!" to the user  )
	1 -                          (Decrement counter                  )
  dup 0 < until                  (repeat until counter is < 0        )
  pop                            (Clean up the stack                 )
;

---
An alternative of the above begin-while-repeat loop, using a local variable.

lvar counter                        (Declare the variable local to the prog )
: iterator-3
  begin                             (Mark the start of the loop             )
	counter @ 0 > while             (Exit the loop if done                  )
	me @ "Hello World!" notify      (Print "Hello World!" to the player     )
	counter @ 1 - counter !         (Decrement the counter                  )
  repeat                            (repeat the loop                        )
  pop                               (clean up the stack                     )
;

---
A random-number generator:

(This word pushes a random number from 1 to 100 on the stack)
: random-100  ( -- i {random#} )
  random 100 % 1 +
;




        dbref?          ( ? -- i )         is top stack item is an dbref?
        dbtop           ( -- d )           top of database + 1 item.
        depth           ( -- i )           stack depth
        force           ( d s -- )         player, force string
        int?            ( ? -- i )         is top stack item is an integer?
        localvar        ( i -- l )         local var num -- localvar
        locked?         ( d d -- i )       player, object -- is object locked?
        nextprop        ( d s -- s )       object, propname -- next propname
        online          ( -- dN ... d1 N ) all connected players w/ count
        prog            ( -- d )           this program's dbref
        propdir?        ( d s -- i )       object, propname -- is it a propdir?
        queue           ( i d s -- ??? )   queue event to run prog d after i seconds with s on the stack.
        recycle         ( d -- )           item to recycle
        setlink         ( d d -- )         object, dest
        setown          ( d d -- )         object, newowner
        sleep           ( i -- )           pause the program for i seconds
        string?         ( ? -- i )         is top stack item is an string?
        systime         ( -- i )           system time in secs since 00:00 1/1/70 GMT
        timefmt         ( s i -- s )       format, systime -- timestring
        timesplit       ( i -- 8 ints)     sec, m, hr, dy, mnth, yr, wkdy, yrdy
        trig            ( -- d )           a secure form of trigger @

Return to the TinyMUCK Page

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