The muf Den

Q&A -- How do I port MUFs?
by Natasha

Many, many people have asked how to port a MUF program. It's fairly simple, though it's not really well documented anywhere; it's something most MUF coders and wizards pick up from sporadic documentation, other coders, and experience. Here's my attempt at an answer.

Step 0: The Program Object and the muf Directory

First a tiny bit of background: Fuzzball stores MUF programs as .m files in its muf subdirectory. The .m files are named with the dbref of the corresponding MUF object, as granted by the @program command. MUF objects differ from normal things in that:

This doesn't seem important now, but if you ever need to move your MUCK to a new server, or do a global search and replace through all your muck's MUFs, or install an ANSI color MUF, you'll have to know this stuff anyway.

Step 1: Read the Header Comment

When you acquire a MUF to port, one of the first things to do is to read the header comment. This is the text at the very top of the program code, inside a pair of (parentheses). The header comment usually contains porting information and instructions.

If there are instructions, follow them. This is especially important for programs like Caspian's lib-ansi-free, which requires you actually cp the program file over a .m file in the muf directory, because Fuzzball will strip out the escape codes (these being the whole point of the program) if you just paste it through your client like a normal program.

Step 2: Customize the $defines

If there aren't any oddball instructions, next you should check for $defines you need to customize. $defines are commands between the header comment and the program code that allow the author to abstract part of the program for easy customization. A $define will be either a line starting with $def or a line or block of lines with a $define at the start and an $enddef at the end.

The important $defines are dbrefs of programs or objects that the program needs to do something with, but can't find by just looking at the environment. There should be some directions, but where there aren't, the names of the $defines tend to be self-explanatory.

When I include $define-able constants in my programs, I prefix the names with type strings:

ref_
Dbref, such as a program to call or special object where properties or objects are stored.
prop_
A property into which some value should be stored.
propdir_
A propdir into which some values should be stored. These aren't complete properties in and of themselves, like for the prop_ prefix.
str_
A string constant other than a property. I also tend not to put error messages in $defines such as this.
val_
Any numerical (integer) constant.

Step 3: Determine Which Format You Have and Upload

The Uploadable Script Format

After you've set up your $defines, it's time to actually install the program. There are two types of archives you could have the program in. The easier of the two is a preformatted, uploadable script. Usually when you download a MUF from the author's site, it's in this format. It looks something like:

@program foobar.muf
1 9999 d
i
( foobar.muf by Fox Q. Coder
  more header comment
)
$def ref_parentRoom #123
: main
  muf code
;
.
c
q
@set foobar.muf=L
@act foobar=#0,foobar.muf

Notice how the file itself includes the necessary @program command, as well as normal MUCK commands (eg, @set foobar.muf=L). If the @program command is present, you will only have to upload it to your muck to install--don't forget to complete steps 1 and 2 first, though, since there may be some special commands necessary that the author can't include ahead of time (such as the correct dbref for the $def ref_parentRoom in the example). Beyond playing back the script and following the header-comment instructions, that's all there is to do with this format.

The Just-the-Code-Ma'am Format

The other format is just the program. This is what you'll have if you log a @list of a program on some other muck, if you wrote the program yourself (and didn't put it in uploadable script format yet), or download a program from a very lazy author (yes, guilty as charged). The same program in this format would look like:

( foobar.muf by Fox Q. Coder
  more header comment
)
$def ref_parentRoom #123
: main
  muf code
;

Notice that with this format, you will have to provide the @program command and any necessary @set commands. You would type:

@program name.muf
i

That tells the muck, Create a MUF object with name name.muf and wait for me to enter the text. Next you paste your copy of the code in, then type:

.
c
q

That tells the muck, I'm done--stop listening for MUF code, then compile the program, and exit the editor. When you compile the code is one of the points at which errors might show up, so you may want to wait for the Compiler done. message after c before entering the q.

Since nothing but the code was included, if the program needs any special flags such as L or W set, you'll have to set them yourself. The necessary flags should be listed in the program's header comment; if they aren't (or even if they are) you could find a muck that has the same program installed and see what flags it has there. If worse comes to worst, you can try hunting down the author (but only if you can't find the program somewhere else and the header comment doesn't say!), or guessing.

If you have to guess, remember it's best for security to give programs the least permissions possible. A common security hole is to give the cmd-cp-mv2 program a Wizard bit. The common version of the program doesn't adequately check for attempting to read or set wizard properties (props or propdirs starting with ., ~, or @), so if the program has a Wizard bit, it blindly allows anyone to do so.

Step 4: Fix Errors

Errors may occur at compile time or at runtime. Since presumably you're porting a finished, working program, all the errors you will encounter should be due to a misconfiguration somewhere. You'll be much more likely to have errors at compile than at runtime.

If you're debugging a program and have a particular error, skip to the appropriate section:

Being $inclusive

Most programs that are the slightest bit complex use libraries--external programs that have standard, documented words a program can call to accomplish a function for which there's no primitive--to save programmer time and headache. Libraries are utilized by a program through the $include directive, so this error belies a problem with one of the libraries this program uses.

Libraries need to be @registered globally (that is, on #0) to be usable in an $include. There's a problem when you get a compile-time error like:

Error in line 7: I don't understand what object you want to $include.

If this happens, use @list or the MUF editor to list the erroring line (in this example, line 7). It should read something like:

$include $lib/foobar

That means that the MUF editor is looking for a MUF library that is @registered globally as '$lib/foobar'. At this point, use the @find command to see if you actually have this MUF installed (for this example, you would try @find lib?foobar=f--the ? meaning any punctuation character--or @find foobar=f). If you don't, you'll have to get a copy and install it before the program you're trying to install now will compile. If you do have a copy, you'll just have to @register it (typically with @register object=name--see @register #help) then try the compile again.

The Case of the Missing Macros

Similar to libraries are macros, which are strings starting with a dot (.string) that the MUF compiler will replace with a small, predefined bit of code. Sometimes a program will use a macro that your muck doesn't have, which will cause an error like: Specialized macros might be included in the header comment of the program, though more general macros (such as '.tell' or '.popall') may not be. The best place to look for a macro would be on a muck that has a program that uses that macro; just ask a wizard or MUF wizard what the macro is defined as there. (If someone asks you this, you would find out what, for example, .popall is defined as by going into the MUF editor and typing 'popall s' (note no leading '.') where 's' is short for 'show.' If you type just 's' or 'show', the editor will list all macros you have installed.)

call and Program Dependencies

Sometimes a program will expect another program to be installed and working. If it isn't, you'll end up with a runtime error. Since the program will be using a globally registered name if it didn't just use a $define, see the part on $includes for suggestions.

Misconfigured $defines

If a $define is left misconfigured, part or all of the program will fail to work. These errors tend to happen more at runtime than at compile, since Fuzzball has no way to know if you specified #1234 when it should be #5678--they're both dbrefs, which is good enough for compile.

Make sure that all the dbrefs and preferences asked by the $defs and $defines at the top of the program are correct for your muck's setup. Like every real world problem that doesn't fit in a simple troubleshooting list, fixing these is mostly a job for a MUF wizard who knows what he/she is doing, especially since every muck is different.