MUF
MUF (Multi-User Forth, originally MUCK Forth) is the stack-based, Forth-derived scripting language that Piaw Na built into TinyMUCK 2.0 in 1990 so that players could program a text-based virtual world from the inside - the language that ran FurryMUCK, Tapestries and hundreds of other MUCKs, and is still maintained today in the Fuzzball MUCK server
Created by Piaw Na ("Lachesis"), a University of California, Berkeley undergraduate and Bellcore co-op intern, wrote MUF and its compiler, interpreter and editor for TinyMUCK 2.0 in 1990; Jon Blow of Berkeley wrote down the security rules and built the macro system. TinyMUCK itself was derived by Stephen White (University of Waterloo) from Jim Aspnes's TinyMUD; later maintainers include Robert "ChupChup" Earl (TinyMUCK 2.1-2.2) and Revar Desmera (Fuzzball, the 2.2fb line, from the early 1990s to the present)
MUF - Multi-User Forth, or in its creator’s original expansion MUCK Forth - is the stack-based programming language embedded in TinyMUCK and its descendants, above all the Fuzzball MUCK server. It was written in the first half of 1990 by Piaw Na, then a Berkeley undergraduate on a co-op placement at Bellcore, who wanted a way to build a scrolling virtual movie theatre inside a text-based world and decided that the simplest route was to give the server a compiler. Because he had a week or two of MUD experience, no knowledge of Forth and a deadline of one weekend, MUF is small and pragmatic: colon definitions, a data stack, three data types and a handful of primitives that reach into the game database. That was enough. MUF turned MUCKs into worlds their players could extend from the inside, and it has been running - continuously, and with the same basic syntax - for thirty-six years.
MUF is a language of a particular place and time. It lives only inside a MUCK server, where programs are database objects, the editor is a line editor you enter by typing @prog, and a “Hello, World!” runs when someone walks through an exit linked to it. Its history is therefore also the history of the MUCK family of servers: TinyMUCK 2.0 to 2.2 (1990-1991), Fuzzball (the 2.2fb line, from the early 1990s to Fuzzball MUCK 7.2 in 2024), and offshoots such as NeonMUCK, ProtoMUCK, GlowMuck and DaemonMUCK.
History and origins
TinyMUD and TinyMUCK 1.0 (1989-1990)
Jim Aspnes’s TinyMUD (Carnegie Mellon, 1989) reset the expectations of multi-user text worlds: instead of fighting monsters, players built rooms, objects and exits and talked to each other. It had no programming language, and the immediate response was a wave of derivatives that tried to add one. Stephen White of the University of Waterloo produced TinyMUCK 1.0 from the TinyMUD 1.5.2 code in the winter of 1990; the 2001 MUD FAQ summarises it as “identical to TinyMUD, except that it added the concept of moveable exits, called @actions”, plus the JUMP_OK flag and @recycle. “MUCK” was simply a play on “MUD”: in the words of the FAQ, “the name doesn’t mean anything”.
Lachesis and Atlantis (1990)
Piaw Na - known in the MUDs of the day as “Lachesis”, a female character he role-played with some success - came to TinyMUCK 1.1 in early 1990. His own account, preserved at the MUDdex, is unusually candid about what happened next. He had been “involved in a few MUDs and trying to build a virtual movie theatre”, found that the only way to show a scrolling film was to string rooms together, and “wanted a programmatic interface to do that”. Stephen White and Jim Aspnes were both designing new programmable servers, but “everyone else had a second-system syndrome”, so Na, “a college sophomore” who “knew next to nothing about parsers, compilers, or interpreters” beyond the introductory Structure and Interpretation of Computer Programs course, “decided it was time I bit off more than I could chew”.
The design decisions are set out in his TinyMUCK 2.0 Technical Notes of June 1990, a document Fuzzball shipped in its docs/historical directory until 2015. Three of them defined the language:
- Property lists. To let programs attach data to objects without changing the C source, Na added user-settable string pairs (with a hidden integer field visible only to programs) to every object. Properties became the universal storage mechanism of MUCKs, and later the basis of MPI.
- Forth. “I observe that most MUCKs use a sort of C-like language, which I don’t really like … I hovered between LISP and forth for a while, before coming down on the side of forth because it’s easier to write a byte-compiler for forth than it is to write one for LISP. Note that I had no experience with forth whatsoever … The syntax took all of 5 minutes to learn and an hour to sink in.” He then “mutated it beyond recognition”.
- Source in the database. Unlike most MUD languages, TinyMUCK stored each program’s source, not its bytecode, in a separate file, so that the head wizard “can read the source code on-site and modify it if she finds that it violates her guidelines”. Programs were compiled at server start-up, and later on demand.
The editor and compiler “took about 2 man days, or 1 weekend. Testing and debugging then took another day.” The compiler was single-pass with no lookahead, resolving forward references by back-patching blanks in the bytecode; at that stage the ELSE clause of IF was abandoned for want of time. Recursion was supported, which Na believed most MUD languages did not allow, and the READ primitive - which pauses a program to wait for a line of input from the player - was, he thought, “quite unique”. A MUCKER flag restricted programming to trusted players, because a program “could do so many things (including give players pennies or take away pennies from players)”. Jon Blow of Berkeley “wrote down the rules” of the security system and “helped by developing a macro system for MUF”.
Na’s test server, Atlantis, came up “in March or April” 1990 and took five megabytes of RAM until per-player frames were made dynamic. The oldest surviving MUF tutorial - “Zen in the Art of the Towers of Hanoi (or The Basics of MUF in 10 megs or less)” - was posted to alt.mud on 5 June 1990. By mid-July Atlantis had users “well into the hundreds”, was loading the Bellcore gateway enough to be moved to a night schedule, and had drawn questions from senior management; Na recalls sleeping under his desk after a night hunting a null-pointer bug in the string code (“this was 1990, and there was no purify”). He judged, though, that the real reason for TinyMUCK’s spread was not the language but backward compatibility: “it was painless to switch to MUCK from an already preexisting TinyMUD or TinyMUCK”. He shut Atlantis down in August 1990 when he left Bellcore, “swore off MUDs entirely”, and handed the code to Robert Earl of UC San Diego.
TinyMUCK 2.1, 2.2 and the arrival of Fuzzball (1990-1993)
Robert “ChupChup” Earl produced TinyMUCK 2.1 (announced July 1990) and 2.2, cleaning up the code and porting it; the MUF tutorial header records an update on 10 August 1990 “for the release of TinyMUCK 2.2”, while other accounts date the 2.2 release to April 1991. The MUF reference manual of the period, compiled by “Jethro” (Rawdon, at Tulane) with help from Black_Dougal, was “current through TinyMUCK 2.1.1” and then “updated completely for TinyMUCK release 2.2” by ChupChup.
FurryMUCK opened on Na’s TinyMUCK late in 1990, and MUCKs found their lasting audience in social and role-playing communities - many of them, as Richard Bartle noted in Designing Virtual Worlds, based on “original, anthropomorphic animals (furries)”. Bartle also identified the defining property of the whole TinyMUCK lineage: they “don’t have computer-controlled monsters for players to seek out and … kill”.
The fork that mattered was Fuzzball, by Revar Desmera (also known as Foxen), whose versions carry the prefix 2.2fb in acknowledgement of their TinyMUCK 2.2 ancestry. The first fb changelog adds LVAR program-local variables, the SETLINK, SETOWN, NEWROOM, NEWOBJECT and NEWEXIT primitives and connection-introspection words such as ONLINE and CONCOUNT. 2.2fb2.3 introduced the multitasking model still in use - foreground, background and preempt - and the publics listing of exported functions. 2.2fb4 introduced graded MUCKER levels 1 to 4; Scotfox’s MUF Tutorial, “Revision 2.2fb4 of 28 February 1993”, is the version Fuzzball still distributes.
MPI, NeonMUCK and ProtoMUCK (1995-2001)
Fuzzball 5 (2.2fb5.0; Wikipedia dates version 5 to 1995) added a second language, MPI, the Message Parsing Interpreter - a curly-brace macro language such as {if:{eq:{name:me},Revar},hello} that lives inside descriptions and messages - with a PARSEPROP MUF primitive so the two could call each other. The fb5 series also adopted Dr. Cat’s dictionary-based database compression (5.44) and, in 5.53, closed “a major security hole that exists in all earlier versions of fbmuck, and in the TinyMUCK 2.2 code it was derived from”.
Other groups took the Fuzzball code in their own directions. NeonMUCK 1.5 (copyright 1996 Andrew Nelson and Jeremy Blackman; Joe Traub joined for NeonMUCK 2.0) added Pueblo multimedia support (notify_html), ANSI colour (ansi_notify), a new MUCKER/WIZARD level scheme and a built-in web server on which “MUF programs can work as webpages”. ProtoMUCK, by Chris “Moose” Brine and Richard “Akari” Taylor, descended from NeonMUCK and released 1.00 on 18 September 2000; its repository was still receiving small changes in July 2020. A 2001 revision of the Usenet MUD FAQ summed up the state of play: TinyMUCK 2.* was “TinyMUCK v1.* with a programming language added”, MUF “is very powerful, and can do just about anything a wizard can”, the latest version was 2.3b, and “FBMUCK and DaemonMUCK 0.14” were the most common varieties. Tapestries MUCK, another long-lived furry world, later forked its own server from “TinyMUCK FB 5.67”.
Fuzzball 6 and 7 (2000s-2026)
The 6.00 alpha, beta and release-candidate series, developed on SourceForge during the 2000s, is where MUF grew from a 1990 toy into a full scripting language. Contributions credited to “Points” added a floating-point type and maths library (6.00a3); 6.00a17 added the array type - lists and dictionaries - with a large ARRAY_* vocabulary (the { ... }list and }dict constructors are documented by 6.00b1); 6.00a21 added MCP primitives and 6.00a28 added MCP-GUI primitives so that programs could put dialog boxes on MCP-capable clients such as Fuzzball’s own Trebuchet; 6.00b1 added TRY-CATCH-ENDCATCH; 6.00rc7 added REGEXP, which 6.02 moved onto PCRE; timers, SSL connections and DESCRFLUSH arrived in the same period. The 6.x line ran for more than a decade - 6.09 was current by 2013 and 6.14/6.15 appeared in May 2015.
Development moved from CVS to Git on 19 September 2012 and to the fuzzball-muck GitHub organisation. Alphas and a beta of 7.00 followed in 2016-2017, and Fuzzball MUCK 7.0 was released on 28 December 2020 under the GPL v3 (with an OpenSSL linking exception): new lock types, regname matching, operator aliases such as ^, &, |, ** and <<, CASE/WHEN/DEFAULT/ENDCASE defines, and the $DOCCMD directive. 7.1 (4 May 2023) added SMTP_SEND, official Docker support and IEEE INF/NAN semantics; 7.2 (27 March 2024) added terminal-size introspection and OpenSSL password hashing; 7.2.1 (12 April 2024) fixed a buffer overflow in password handling (issue #728). The project’s Docker image reached tag 7.2.3 in June 2026 and the repository was still being patched in August 2026.
Design philosophy
MUF was designed, in Na’s words, with “primary consideration … given to ease of implementation, reliability, extensibility, and speed. Secondary considerations included ease of use”. He wanted the language not “to seem like a kludge. (By definition it is a kludge, but I did want it to possess some elegance.)” Three ideas follow from that.
The server is the runtime. A MUF program is an object in the database with a dbref like #1234; it is created with @prog, edited line by line, compiled inside the game, and run when an action or exit linked to it is used, when a lock is tested, when a description is looked at, or when a _listen, _connect or _disconnect event fires. Data lives in properties on objects. There is no file system, no standalone interpreter and no way to run MUF outside a MUCK.
Everyone can program, but not equally. Because a program can move players, hand out currency and rewrite the world, MUF has had a privilege model from the first day: the MUCKER flag in 1990, and from Fuzzball 4 four mucker levels. Level 1 “apprentices” can only inspect objects in the same room and are capped at roughly 20,000 instructions; level 2 “journeymen” have the old MUCKER powers and around 80,000; level 3 “masters” can use connection primitives, QUEUE and KILL and create objects without limit; level 4 is the wizard bit, required for RECYCLE, FORCE, SETOWN and DESCRHOST. A program runs at the lesser of its own level and its owner’s, and can be marked SETUID to run with the owner’s permissions rather than the user’s - the same trade-off Unix makes.
Sharing the CPU. From 2.2fb2.3 a program runs in one of three modes. Foreground programs multitask with everyone else but block their user’s input; background programs let the user carry on but may not READ; preempt programs take the whole interpreter until they finish and are therefore held to an instruction limit unless they are wizard programs. Locks, descriptions and success/fail messages run preempted; actions run in the foreground; queued events run in the background. Compiled programs that go unused are reportedly dropped from memory and recompiled from source when next needed.
Key features
Syntax
MUF reads like Forth. A word is defined between : and ;; comments sit in parentheses; arguments are pushed onto the stack and consumed by primitives. Variables are read with @ and written with !. The last word in a program is its entry point. The canonical first program, from Scotfox’s 1993 tutorial:
| |
me holds the dbref of the player who triggered the program; notify sends a string to a player. Link an action to the program (@action hello=here, @link hello=#1234) and typing hello prints the message.
Control flow is Forth’s: if ... else ... then, begin ... until, begin ... while ... repeat, for ... foreach, with break and continue. The stack words are the usual dup, pop, swap, over, rot, pick and friends, and every primitive is documented with a stack diagram such as NOTIFY ( d s -- ). Fuzzball 7 adds CASE/WHEN/DEFAULT/ENDCASE as compiler defines over begin dup ... until.
Types and the database
The 1990 language had exactly three stack types - integers, strings and dbrefs (database references written #42) - plus variables and function addresses, and integer arithmetic only. A dbref is the handle to any room, exit, thing, player or program, and most primitives take one: name, owner, location, contents, exits, moveto, getpropstr, setprop, match. Because properties are the storage layer, a typical MUF program is largely reading and writing props on objects:
| |
Fuzzball 6 added floating point (FLOAT, SQRT, POW, FRAND, with props able to hold floats), lock values, and two container types: lists and dictionaries, built with a stack marker:
| |
together with ARRAY_GETITEM, ARRAY_SETITEM, ARRAY_INSERTRANGE, ARRAY_SORT, ARRAY_NUNION, ARRAY_JOIN, ARRAY_FMTSTRINGS and dozens more. TRY … CATCH … ENDCATCH handles run-time errors (CATCH_DETAILED returns a dictionary describing them) and REGEXP provides PCRE matching that returns lists of matches and indices.
Interaction
READ pauses a foreground program until the player types a line; Na used it for interactive quizzes and it is still how MUF menus and editors work. notify, notify_except and notify_exclude send text; descr* primitives address individual connections; QUEUE, FORK, SLEEP, TIMER_START and KILL schedule and control processes; FORCE (wizard only) makes an object execute a command. Fuzzball 6’s MCP and MCP-GUI primitives let a program draw dialog boxes on a client that supports the MUD Client Protocol; 7.1’s SMTP_SEND can send e-mail; 7.2’s WIDTH and HEIGHT report the user’s terminal size negotiated over telnet.
Programs in the large
Fuzzball’s preprocessor turns MUF into something one can build systems in. $define/$def and $include give macros; $ifdef, $ifver and $iflibver allow conditional compilation against the server (__FUZZBALL__, __VERSION) and library versions; $author, $version, $lib-version, $note and $doccmd document a program. Functions declared PUBLIC can be called from other programs, and a library is just a program that declares its exports with $libdef, is set LINK_OK and VIEWABLE, and is registered as $lib/name; $include $lib/strings then makes its words available as if defined locally. The standard libraries shipped with Fuzzball - strings, props, lmgr (lists), edit and editor, mesg and mesgbox, match, reflist, gui and optionsgui - are themselves MUF, maintained in the fuzzball-muf repository. This is how lib-strings defines a word and exports it:
| |
The Fuzzball 7 source tree implements the primitive vocabulary in a dozen files (p_array.c, p_connects.c, p_db.c, p_error.c, p_float.c, p_math.c, p_mcp.c, p_misc.c, p_props.c, p_regex.c, p_stack.c, p_strings.c) containing roughly 400 prim_* functions.
Evolution
| Version | Date | Maintainer | What changed for MUF |
|---|---|---|---|
| TinyMUCK 2.0 | June 1990 | Piaw Na (Lachesis) | The language: Forth-like compiler and interpreter, @prog editor, property lists, MUCKER flag, READ, recursion; source stored in the database |
| TinyMUCK 2.1-2.2 | July 1990 - 1991 | Robert Earl (ChupChup) | Bug fixes, ports, updated tutorial and reference manual |
| 2.2fb - 2.2fb2.3 | early 1990s | Revar Desmera | LVAR locals, object-creation and connection primitives, foreground/background/preempt multitasking, public functions |
| 2.2fb4 | by February 1993 | Revar Desmera | Four graded mucker levels with instruction limits |
| 2.2fb5 | c. 1995 onward | Revar Desmera | MPI embedded language with PARSEPROP; dictionary compression; security fix in 5.53 |
| NeonMUCK 1.5 / ProtoMUCK 1.00 | 1996 / 18 September 2000 | Nelson and Blackman / Brine and Taylor | Pueblo, ANSI, web-server and MAGE-level extensions to the MUF dialect |
| 2.2fb6.00 series | 2000s | Fuzzball project (SourceForge) | Floating point, lists and dictionaries, TRY/CATCH, REGEXP (PCRE), MCP-GUI, timers, SSL; GPL v2 |
| Fuzzball 7.0 | 28 December 2020 | fuzzball-muck (GitHub) | Operator aliases, CASE defines, $DOCCMD, new lock types; GPL v3 |
| Fuzzball 7.1 / 7.2 / 7.2.1 | May 2023 / March and April 2024 | fuzzball-muck | SMTP_SEND, Docker distribution, IEEE maths; WIDTH/HEIGHT, OpenSSL password hashes |
Current relevance
The master list that this encyclopedia follows marks MUF “dormant”, and as a language that is fair: its syntax and model have not changed in any fundamental way since 1990, and nobody starts a new project in MUF unless they are building a MUCK. As an implementation it is anything but dormant. Fuzzball is one of the more actively maintained MUD servers of any family, with tagged releases in 2020, 2023 and 2024, an official Docker image updated in June 2026, continuous integration on Linux, Windows and FreeBSD, and commits in August 2026. The fuzzball.org development MUCK is open to the public, the full MUF reference (mufman.html), MPI reference and Scotfox’s tutorial are online, and the MINK manual explains how to run a world.
The user base is the one MUF has had since 1990: social and role-playing text worlds, prominently the furry MUCKs. FurryMUCK, founded in late 1990, and Tapestries are still running, and the fuzzball-muf repository collects programs from them and from other MUCKs such as SpinDizzy. The derivative servers are quieter - ProtoMUCK’s last change was in July 2020, GlowMUCK’s public repository history runs from 2002 to November 2014 - and a few hobbyist reimplementations of TinyMUCK (RubyMUCK, for instance) exist on GitHub mainly as exercises. There is no MUF outside the MUCK, no package ecosystem beyond $lib/, and no prospect of either; that is the nature of an embedded world-scripting language.
Why it matters
MUF was, with Stephen White’s MOO and the TinyMUSH softcode of the same era, one of the first languages that let ordinary participants in an online world program it. Where LambdaMOO offered a C-like object language designed at Xerox PARC, MUF offered a college sophomore’s weekend Forth - and it is a fair test of what a scripting language actually needs that both are still running in 2026. Its design choices were pragmatic and turned out to be durable: source kept in the database so administrators could audit it; a privilege model (MUCKER bits, then mucker levels and SETUID) that let untrusted users write code on a shared server a decade before web sandboxes; instruction limits and cooperative multitasking so that one runaway program could not stop the world; and properties as a universal, user-extensible data model that later carried MPI as well.
Historically it also settles a question that Na himself raised. He believed TinyMUCK spread not because of MUF but because it was “painless to switch to MUCK from an already preexisting TinyMUD”. Yet the language is the part that survived: TinyMUD is gone, TinyMUCK 1 is a footnote, and what the Fuzzball, Neon and Proto lines all carried forward, version after version and licence after licence, was the Forth in the middle. A postfix language chosen because “it’s easier to write a byte-compiler for forth” ended up as the programming interface for a family of virtual worlds that has now outlasted most of the programming languages its designers might have preferred.
Further reading
- Fuzzball MUCK source, releases and Docker image: github.com/fuzzball-muck/fuzzball, fuzzball.org, hub.docker.com/r/fbmuck/fbmuck
- MUF Reference Manual (Fuzzball 7): fuzzball.org/docs/mufman.html; MPI reference: fuzzball.org/docs/mpihelp.html
- Scotfox, The MUF Tutorial, revision 2.2fb4 (28 February 1993), distributed as
docs/muf-tutorialin the Fuzzball tree - Lachesis (Piaw Na), TinyMUCK 2.0 Technical Notes, June 1990 - formerly
docs/historical/technical.docin Fuzzball (removed 29 May 2015; recoverable from the repository’s 2012 initial commit) - Piaw Na’s recollection of writing TinyMUCK, at the MUDdex: linnaean.org/~lpb/muddex/tinymuck.txt
- Standard MUF libraries and programs: github.com/fuzzball-muck/fuzzball-muf; MINK, the Muck Information Kiosk: fuzzball-muck.github.io/muckman
- ProtoMUCK source (with NeonMUCK change files): github.com/protomuck/protomuck
- Usenet MUD FAQ, part 2 (2001 revision), server descriptions: faqs.org/faqs/games/mud-faq/part2
- Richard Bartle, Designing Virtual Worlds, New Riders, 2003 (on TinyMUCK and MUCK culture)
- Wikipedia: TinyMUCK, FurryMUCK
Timeline
Notable Uses & Legacy
FurryMUCK
Founded in late 1990 on Piaw Na's TinyMUCK, FurryMUCK is one of the oldest and largest non-combat MUD-style games still online. Its commands, builders' tools, message boards and social machinery are MUF programs, and it later moved to the Fuzzball server; Wired called it 'the first anthropomorphic MUD' in 1994 and by 1999 it was described as 'one of the longest-running and best-maintained social MUCKs online'
Tapestries MUCK
An adult furry MUCK that runs its own fork of the Fuzzball server, published on GitHub as TinyMUCK-Tapestries and 'originally forked from TinyMUCK FB 5.67'. The Tapestries fork embedded Lua alongside MUF and added a new security system while a replacement server was planned, illustrating both the longevity of MUF codebases and their limits
Fuzzball's starter database and standard MUF libraries
Every Fuzzball MUCK ships with a starter database whose core user commands (cmd-lsedit, cmd-page, cmd-watchfor, cmd-who and dozens more) are MUF programs, and with the $lib/ standard libraries - lib-strings, lib-props, lib-lmgr, lib-edit, lib-editor, lib-mesg, lib-match, lib-reflist, lib-gui and others - maintained in the fuzzball-muf repository. The Muck Information Kiosk (MINK) documents how to build a world from them
Atlantis (1990)
Na's experimental MUCK at Bellcore, the first TinyMUCK, was where MUF was designed, debugged and first used: within months it had 'well into the hundreds' of users, a virtual movie theatre, and enough traffic that Na was restricting it to night hours before shutting it down in August 1990
NeonMUCK and ProtoMUCK worlds
The NeonMUCK (1996) and ProtoMUCK (2000) servers carried MUF into new territory: Pueblo multimedia and ANSI colour primitives, MUF programs that could serve as web pages through a built-in HTTP server, and 'MAGE' privilege levels. ProtoMUCK-based games used these to blend graphical clients with the traditional text world
Language Influence
Influenced By
Influenced
Running Today
Run examples using the official Docker image:
docker pull fbmuck/fbmuck:7.2.3Example usage:
docker run -d --init -p 4201:4201 -v $(pwd)/fb-data:/opt/fbmuck fbmuck/fbmuck:7.2.3 # then: telnet localhost 4201