Previous Page TOC Index Next Page Home


11

Online Entertainment for the Internet Guru


--by Joseph R. Poirier and Tod Foley

How to Program Muds

Several years ago I joined the Information Superhighway and took the on ramp marked MUD, or Multi-User Domain.... What makes these games so enticing is that they are a step up from chat and e-mail. Not only is it possible to assume whatever personality you want, but you can act any way you want. You can kill without ever seeing blood, roar threats or cross swords without ever breaking into a sweat.... With MUDs and other on-line multiplayer games, you can live vicariously in a new universe and even attain godhood, thereby achieving omnipotence.

—Kristina Harris, "Godhood: Not All Fun and Games," "My Turn," Newsweek, July 18, 1994, p. 12.

One of the advantages of access to the Internet is the increased ability for people from all over the world to meet, and one of the major meeting places is interactive multi-user virtual realities. Also known as multi-user dungeons, or MUDs, these environments have expanded out of the game-playing niche into educational uses, corporate uses, and research. Some people call them multi-user domains in an attempt to de-emphasize the Dungeons and Dragons™ role-playing influences and highlight the multi-user side. Nowadays, the acronym MUD has been generalized to lowercase mud.

Muds are a cross between a text adventure game and a chat line. Muds contain a number of rooms, each having a description and possibly containing objects that players can use. Players of the mud—known as mudders—move from room to room around the mud. They can pick up objects and use them, meet and talk to other players, solve puzzles, play games, read mud newspapers, combat monsters, and explore virtual reality.

Muds are becoming more and more mainstream. Once the bastion of male computer science students who also liked a good role-playing game from time to time, they now attract all sorts of people from many walks of life. On a mud, you can bump into someone, male or female, who is a film director in real life, or perhaps an English professor, a high school teacher, a sociologist or an engineer—all in the same room! Newsweek magazine, for instance, has mentioned muds several times in its new Cyberscope Department, a page-long collection of short articles related to Cyberspace.

There are some graphical muds being developed, but the vast majority are text-based. Some muds emphasize social aspects; others emphasize combat. On social muds, players tend to use the mud as a communication medium. Players talk to other players, create and play games, and join group discussions. On combat muds, players buy weapons and armor, join guilds, learn skills, and fight monsters to gain experience. With enough experience, a player can become a wizard on the mud. Wizards have the ability to create new objects, rooms, and puzzles on combat muds.

There are several major types of muds, such as MUCKs, MUSHes, MOOs, MUSEs, LP-MUDs, Diku-MUDs, and others. Each type of mud differs in the underlying programming environment. Sometimes you will see the word mud expressed as MU* in newsgroups and research papers. This is due to the various mud types that have those two letters in the beginning of their names.

Which type of mud you end up programming for (also known as building), often depends as much on happenstance as on deliberate decision. After all, one tends to hang out wherever one's friends hang out. But there are distinct differences from one variety of mud to the next, in both the structure of their programming languages and in the kind of players and builders they tend to attract. For what it's worth, just about any kind of virtual environment could be created in any of the mud languages, and yet certain languages have developed genre- or function-based followings, and have evolved further than other, lesser-used types of muds.

Chapter Overview

This chapter describes how to use and program several different types of muds: MUCKs, MUSHes, MUSEs and MOOs. LP-MUDs and Diku-MUDs, which are also very popular, are not discussed here. Many small examples will be presented throughout the chapter.

If you are totally new to muds, you might want to begin by reading through "Interactive Multi-User Realities: MUDs, MOOs, MUCKs and MUSHes," which can be found in The Internet Unleashed, an earlier SAMS book. That chapter describes mud basics in more detail. It describes several resources you can use on the Internet, such as newsgroups and FTP directories, to obtain more information on muds. It also details mud history and reflects on various social issues involving muds.

Here is a quick outline of mud expertise. It gives a few broad categories of mud programming knowledge so that you can see where your overall skills currently lie.

This chapter deals with beginner, intermediate, and some advanced levels. First, a quick summary of basic mud commands is presented. Following this is a tutorial that talks about intermediate and advanced mud programming issues in a step-by-step manner. Many examples, throughout the tutorial, will help you understand the concepts presented. After the tutorial, there is a detailed reference of mud commands, attributes, functions, and flags.

Notation

Throughout this chapter, commands and actions that you actually type will appear in monospaced type, and italicized type for placeholder terms for which you supply the appropriate item.

In addition, examples will use the > character as your prompt on the mud, to denote the commands you type as opposed to the messages the mud sends back to you. In those examples, you don't actually type the > character.

A | (vertical line) indicates two or more options exist. Choose one. Don't type the |.

Terms in [] (brackets) denote optional arguments. Don't type the brackets.

Finally, throughout this chapter, you will be using a character named Speedy.

Overview of Common Mud Commands

Each type of mud has its own set of commands, and these commands differ from mud to mud. However, there are several common commands that you can expect no matter which type of mud you use. To refresh your memory, here is a quick summary of some basic commands you should know.

Connecting to the Mud

You can connect to the mud using telnet:

telnet machine-name port-number

However, most mudders use some kind of mud client program, which interprets and displays mud messages to them in a nicely formatted fashion.

Connecting to a Character

To connect to your character after you are on the mud, you type:

> connect character password

Some muds take care of password entry—or even the entire login sequence—for you. Just follow the prompts.

On most muds, you have to send e-mail to the mud administrator in order for him or her to create a character for you to play. Most muds provide for a "guest" character also, so that you can explore the mud a bit before deciding to establish a real presence there.

Obtaining Help

To access the help facilities on your mud, use:

> help

This may lead to more specific help topics. You can type

> help topic

to obtain help on just about everything in the mud, such as commands, attributes, functions, and various general topics.

Talking

This command allows you to talk to other players, and other players to talk to you. The text you speak is transmitted, publicly, to everyone else in the room with you.

On most muds, the command to speak out loud to other players is the double-quote ("):

> "message

You do not need to put a double-quote at the end of your message. The mud puts that in for you.

> "Hey, what's for dinner?

You say, "Hey, what's for dinner?"

Acting out Actions

In addition to speaking, you can act out actions on the mud. These actions create a kind of narrative element to the mud environment, and allow you to express yourself in a different manner than merely speaking.

On many muds, the act command is the colon (:):

> :message

This command will append your message to your name and then display that to everyone in the room.

> :ran a marathon yesterday.

Speedy ran a marathon yesterday.

Looking at Objects

The command to look at an object is:

> look object

When you perform this command, the object's description is shown to you. If you leave off the object portion, the mud assumes you want to see the description of the current room. The look command can be abbreviated to l.

> l book

You see a musty, leather-bound tome.

> l
Library

You are in the library of the house. You can see several bookshelves filled with dusty books lining the walls of the room.

Moving Around

To move around from room to room on a mud, you use:

> go direction

To move to a specific place, use:

> go place

You can also move in a particular direction by typing that direction, such as:

> north

There may be several possible directions or places to move from each room. The best muds are very good at clearly denoting the exits from rooms in the mud.

Whispering to Other Players

To send a message secretly to another player in the same room, use the whisper command. This command differs from mud to mud:

> whisper player = message         (MUSH, MUCK, MUSE)
> whisper "message" to player      (MOO)

This command has an abbreviation: w.

Paging other Players

To send a secret message to another player not in the same room as you, use the page command. This command differs from mud to mud.

> page player = message            (MUSH, MUCK, MUSE)
> page player "message"            (MOO)

This command has an abbreviation: p.

On some muds, the page command costs virtual money, whereas the whisper command is free.

Picking up Objects

The command to pick up an object is:

> get object

If the object can be taken, it is placed into your inventory.

On some muds, the command is also known as take.

Dropping Objects

The command to drop an object is:

> drop object

The object will be removed from your inventory and placed in your current room.

On some muds, the command is also known as put.

Listing What You Are Carrying

To see a list of the objects you are carrying, use:

> inventory

This can be abbreviated to i.

> i
You are carrying:
     a rose
     an envelope containing:
          a letter
     some chocolates

Finding out Who Else Is Playing the Mud

The command to see who else is on the mud varies from mud to mud:

> WHO                              (MUSHes, MUCKs, MUSEs)
> @who                             (MOOs)

Returning to Your Home

The command to return to your place of origin in the mud is:

> home

When you first begin playing a mud, your place of origin is usually a standard home room. Later, you can create your own room and reset your home room to it.

Quitting the Mud

The command to quit playing varies from mud to mud:

> QUIT                             (MUSHes, MUCKs, MUSEs)
> @quit                            (MOOs)

How to Program MUCKs, MUSHes, and MUSEs: A Tutorial

This section discusses most of the key topics you should be familiar with as a MUCK, MUSH or MUSE programmer. Most of the concepts apply to all of the MU* environments; however, there are a few topics that only apply to certain types of muds. These topics will be labeled as such in the text.

MUCK is the most basic of the three types of muds that are discussed in this section. MUSH is more advanced than MUCK, and MUSE can be thought of as MUSH with a few extensions.

Thanks go to Lydia "Amberyl" Leong for the mud help document upon which this section is based.

Objects

MUCKs, MUSHes and MUSEs have four basic types of things: rooms, players, exits, and objects. You can think of rooms, players, and exits as special objects that have added capabilities. Rooms are the building blocks of the mud. You move through the rooms in the mud in order to explore it and meet other people. Players are the people that you meet. You, of course, are a player, and there may be many more players, besides yourself, playing the mud at the same time. Exits connect rooms to each other. Finally, objects are everything else in the mud. You can create objects yourself and program them to behave in many ways.

DBREF

Every object in the mud has a database reference number, known as its DBREF. This number can be used to access properties and attributes on the object.

Most commands will accept either names or DBREF as object specifiers, but some will insist on one or the other. Try it both ways if you get stuck.

Money

Most muds have their own monetary system. As you wander around the mud, from room to room, you may find gold coins or other monetary types. You can then use this money to create new objects, build rooms, and other such activities—since many of these activities require a small amount of money to be used.

Different muds have different types of money, such as gold coins, drachmas, cookies, pennies, dollars, or a fictional type like "blabooies." This chapter uses credits as the monetary unit in its examples.

Wizards and Officials

Throughout this chapter, you may see the term wizard or official. Wizards are players in the mud who have special abilities. Frequently, the wizard is the person who is actually running the mud on their machine. However, there may be other wizards who help the mud administrator, with such things as character creation, policing the mud, and keeping the environment consistent. On MUSEs, wizards are called officials.

Some commands in the mud are only available to wizards. These commands will be identified as such where appropriate.

At-Commands

Some commands and attributes in the mud start with an "at" symbol (@), such as the command to teleport from one room to another, @teleport. These commands and attributes are collectively known as at-commands.

Flags

There are several flags that you can set in a MUSH. The syntax for setting a flag is:

> @set object = flag               (To turn the flag ON)
> @set object = ! flag             (To turn the flag OFF)

Throughout this section, different flags will be mentioned as appropriate.

Messages

In addition to speaking and acting, you can write messages directly to other players using the emit command: @emit message. The message you type will be sent to everyone in the room, including you. As an abbreviation, you can type: \\ message. There are a few variants of this command. @pemit player = message will display the message only to the player specified. @oemit player = message displays the message to everyone in the room except the player specified.

An emitted message does not print who emitted it. If you want to always see who caused an emitted message, you can turn on your NOSPOOF flag. Upon doing so, you will be informed of the player or object that causes an emitted message.

Another flag is the HAVEN flag. When this is set on a player, the player will not receive pages or @pemit messages. If you try to page a player with HAVEN set, you will be told that that player is not accepting pages. This flag does not black out @emit messages, however.

To find out where a player is located, use the @whereis player command. This command will display the room where the player is. After the player is located, he or she is given a message that you are looking for him or her. If you do not want to be located, set yourself to DARK.

These commands are not available in MUCK.

Creating and Naming Objects

To create a new object in the mud, type:

> @create object-name = cost

If you leave off the cost, the object will be created with the default cost, usually 10 credits. After checking to make sure you have enough money to create the object, the mud will respond with the message "Object created as object #DBREF" and the object will be placed into your inventory. You can now refer to this object by using either its object name or it's DBREF. The MUSH performs pattern-matching, so you only need to type enough of the object name to differentiate it from other objects you may be holding.

If you change your mind and you want to rename an object, use:

> @name old-object-name = new-object-name

To change your own name, you can use

> @name me = new-name password

Attributes

Now that you have created an object, you can set its description. The description of an object is one of the attributes that an object can have. An attribute is simply a property on an object.

There are several types of descriptions. @desc object = description sets the description that is displayed to the player that is looking at the object. @odesc object = description is displayed to everyone except the person looking at the object. The player's name and a space are prepended to the message specified. The command @adesc object = actions sets a list of actions that are executed by the mud when the object is looked at.

At this point, it is useful to take note of the basic forms that attributes take throughout MUSH. Assume there is an attribute with the name @xxx. It is applied to the player that is dealing with the object. In addition to the basic attribute, there are usually additional attributes that correspond to the basic attribute. @oxxx is applied to everyone except the player dealing with the object, and @axxx runs a list of actions when the object is used is some fashion. Familiarizing yourself with the @xxx / @oxxx / @axxx combination of attribute names will help you understand and remember other attribute names, since they are similar.

MUCKs, in general, don't have the @axxx attributes, and usually do not have as many @xxx and @oxxx attributes as MUSHes and MUSEs do.

When an object is picked up, its @succ attribute is triggered—"succ" is short for "success". To set the success attribute on an object, use @succ object = message. When the object is picked up, the message will be displayed to the player who took it. The @osucc attribute sets the message displayed to players other than the player who took the object, and the @asucc attribute can be used to set actions that you want performed when the object is taken.

Conversely, the @fail attribute is triggered when a player fails to pick up an object, and the @ofail and @afail attributes correspond appropriately. Usually, a player fails to pick up an object because an object is locked.

It is frequently a good idea to lock an object since unlocked objects can be stolen from you. To lock an object to yourself, use:

> @lock object = me

This will allow only you to pick up the object. In a more general form, the lock command is:

> @lock object = key

The key can be an object name, or a DBREF, or the special words "me" or "here." Boolean expressions are allowed. If you want the key to be a player, you must prefix the player name to an asterisk (*), as in @lock spinach = *Popeye.

Locks are related to the @succ (success) and @fail (failure) attributes in that successfully passing a lock will trigger @succ and failing the lock test will trigger @fail.

To unlock an object, use @unlock object.

The @drop attributes set the messages that are displayed when an object is dropped. Using @drop object = message sets the message displayed to the player who drops the object. @odrop is the message displayed to others, and @adrop are the actions performed when the object is dropped

The @move attributes are triggered when the player or object on which they are set moves from one room to another. The @move, @omove and @amove behave as you would expect.

To destroy an object that you own, use @destroy object-name. You will be paid whatever it cost you to create the object. Destroying objects when you don't need them anymore helps free up space in the mud database. If you want to give anyone the ability to destroy an object that you have created, turn on its DESTROY_OK flag.

If you want other players to be able to see how you have programmed an object, set the object VISUAL.

> @create root beer float
root beer float created as object #1765.
> inventory
You are carrying:
root beer float (#1765).
You have 921 credits.
> @desc root = You see a frosted mug of root beer with a dollop of vanilla ice cream floating in it.
Set.
> @succ root = You pick up the frosted mug.
Set.
> @osucc root = picks up the mug of root beer.
Set.
> @drop root = You put down the frosted mug.
Set.
> @odrop root = puts down the mug of root beer.
Set.
> drop root beer float
You put down the frosted mug.
> look root beer float
root beer float (#1765)
You see a frosted mug of root beer with a dollop of vanilla ice cream floating in it.
> get root beer float
You pick up the frosted mug.
> @destroy root
You get back your 10 credit deposit for root beer float (#1765).
Destroyed.

On most muds, you can type enough of the object name to make it distinguishable from any other object in the room. Thus, in the root beer float example, referring to it as root was sufficient.

Action Lists

The @axxx attributes (attributes that start with the letter a) are used to execute action lists. An action list is simply a list of one or more actions, separated by semicolons. For example, you could create a fragile vase. When it is dropped, it does two things: it prints a message describing how it shatters, and then it destroys itself.

> @adrop vase = @emit The fragile vase shatters.;@destroy me
Set.
> drop vase
The fragile vase shatters.
fragile vase has left.
You get back your 10 credit deposit for fragile vase (#1238).

Actions lists are not available in MUCK.

Examining

In addition to the basic look command, you can also examine items in the mud. Examining an object provides you with more detailed information about the object. The command to examine an object (or player) is:

> examine object

If you do not control the object, the examine command will tell you the owner of the object and show any public attributes on the object, such as its description, its success and fail attributes, and so forth.

If you do own the object, or if the object has its VISUAL flag set, you will be able to see all the attributes and how they are programmed.

You will also see any objects that are inside the object you are looking at—provided that the containing object is not set OPAQUE.

If you set an object DARK, it will not show up in a room's contents list. If a player is set DARK, no one will be able to see what that player is carrying.

More Movement Commands

You can teleport from one room to another by using the teleport command. You can only teleport into rooms that are set JUMP_OK.

> @tel room-number

You can also teleport objects that you own into rooms that are JUMP_OK:

> @tel object = room-number

So, if you know that a meeting place that you want to go to is room #222, you could get there by typing:

> @tel #222

If an undesirable player or object is in a room that you own, you can teleport it out of your room to any other room that is JUMP_OK. You could also teleport it to any other room that is yours. So, if someone barges into your room, where you are having a private conversation with someone, and they won't leave, you can get rid of them!

You can also get rid of them by more violent method of killing them.

Killing

Killing, in general, is frowned upon. In fact, some muds don't allow player killing. However, one must remember that muds are only games. So, if someone is being obnoxious, and won't stop, sometimes the only way to drive your displeasure home is to kill them off. The command to do this is:

> kill thing = money

The default cost of killing something is 10 credits. This gives you a 10% chance of success. For each additional credit you spend, your chance of success goes up 1%. Spending 100 credits gives you a 100% chance of success.

Killing something sends it home. The object killed is also paid half the amount of money used to kill it, as a sort of insurance policy.

When an object is killed, the @kill, @okill, and @akill attributes are triggered. They work as you would expect.

Certain things, such as wizards or objects set IMMORTAL, cannot be killed. Only wizards can set things IMMORTAL.

Giving and Receiving Objects

Occasionally, you may want to give another player an object that you have. Or perhaps you want to give them some money. The commands to do these things are:

> give player = object
> give player = money

The player who is receiving the object must have their ENTER_OK flag set.

Conversely, you can take an object from another player by using the possessive form of the get command:

> get player's object

The player who is holding the object must be set ENTER_OK, and the object that you are trying to take cannot be locked against you. This is another reason to use locks on objects. If you don't lock an object, someone else can steal it from you!

Sometimes, instead of just giving a player an object, you many want to allow some other player to own an object that you have created. In order to do this, you must first allow your object to have its ownership changed by setting it CHOWN_OK. You can then give the object to someone else. The player who receives the object may then change its owner by using the change ownership command, @chown object = me.

Finding and Searching for Objects

In a mud with lots of rooms and objects, you might end up losing one of your objects and forgetting where it is. The @find string command will scan through the database and pick out all objects and rooms that have the given string in their names. It prints out the object name and DBREF. @find without any arguments displays all the objects and rooms in the mud that you own. However, it can cost a lot because it takes a lot of computations. Here are some examples

@find dog
@find Speedy

Related to the find command is the search command, @search. It scans through the mud and prints everything about an object. There are several arguments you can give to this command: @search player will display all the objects owned by that player. @search type = object-type will display objects that have that type. For object-type, you can use the types: rooms, exits, objects, or players. @search string searches for that string. And @search flags = flags-desired will search for those flags. Here are some examples:

@search Speedy
@search type = objects
@search dog
@search flags = D

If you want to make sure you don't lose an object, you can link it to yourself. First, set its home to yourself by using the command @link object = me. Then, turn on the object's STICKY flag. STICKY objects are sent home when they are dropped. Thus, when the object is dropped, it will return to you.

> @link homing pigeon = me
> @set homing pigeon = STICKY

If someone then takes the pigeon, and later lets it go by dropping it, it will return to you.

Rooms and Exits

In addition to objects and players, you can also create your own rooms, complete with their own descriptions.

As an example, consider building a tree with a treehouse in it. The tree will be in the middle of a field. The treehouse will have a balcony outside.

The field room already exists. It has been set LINK_OK. The example will describe how to create the tree, the treehous,e and the balcony. It will then describe how to link the three rooms to the existing field.

It helps to form a mental picture of the scene you wish to create. This is expressed in Figure 11.1. From the mental image, you can generalize the scene into objects, rooms, and exits, as seen in Figure 11.2.


Figure 11.1. This is the conceptual idea of the scene.


Figure 11.2. Here are the generalized rooms and exits of the scene.

Now that you have an idea of what you are trying to accomplish, you can begin to create it. To create a room, use the dig command:

> @dig room-name

This creates a room with that name. The mud responds with a message informing you of the DBREF of the room.

Following the example, create the Tree:

> @dig Tree
Tree created with room number #1442.
> @tel #11442
Tree (#1442R)
> @desc #1442=You see a large tree. There seems to be a treehouse up in the branches.
Set.

The descriptions used here are simplistic because the focus here is room construction. In a real mud, though, a more eloquent description would better convey the sense of the scenery.

This room will initially be disconnected from everything else. You can think of it as floating in hyperspace. You can then teleport into that room using the @tel command and set its description and other attributes. However, if your room is not linked to other rooms, you may get a message from time to time indicating that you have an unconnected room. To turn off the message, set the room's FLOATING flag.

Rooms are connected to each other using exits. Exits are the links between rooms. You can create exits by using qualifiers with the @dig command, or by creating them directly with the @open command.

The format to create exits with the @dig command at the same time you create rooms is:

> @dig room-name = in1;in2;in3;... , out1;out2;out3;...

In this command, the in1;in2;in3;... names are names of entrances into the new room. Each name in the in-list is an alias for the entrance. The out1;out2;out3;... names are the names of exits from the new room back into your current room. Each name in the out-list is an alias for the exit. The first name in the list of entrances, in1, will be used as the name in the Obvious exits of the current room. The first name in the list of exits, out1, will be used in the Obvious exits of the new room.

You can specify as many of these entrance and exit names as you wish; just remember to separate them with semicolons. Note that the list of entrance names is separated from the list of exit names by a comma.

Two links are created in the @dig command above. One link goes from the current room to the new room, and uses the in-list names. That's the entrance to the new room. The other link goes from the new room back into the current room, and uses the out-list names. That's the exit from the new room.

You can use the @dig command with exit names to create the treehouse and the deck in the example. Assume you are in the Tree room:

> l
Tree (#1442R)
You see a large tree. There seems to be a treehouse up in the branches.
> @dig Treehouse=treehouse;house;up;u,tree;down;d
Treehouse created with room number 1443.
Opened.
Linked.
Opened.
Linked.
> l
Tree (#1442R)
You see a large tree. There seems to be a treehouse up in the branches.
Obvious exits:
treehouse

Note how the treehouse exit name now appears in the Obvious exits list. That's because it was the first name in the list of entrances into the new room, treehouse;house;up;u.

You can then move into the treehouse by typing one of the entrance names, such as treehouse, or house, or up, or u. This moves you through the exit, into the new room that you have just created.

> treehouse
Treehouse (#1443R)
Obvious exits:
tree

The Obvious exits in the treehouse specifies tree because tree was the first name in the list of exits, tree;down;d, in the @dig command earlier.

Next, we can describe the treehouse and then create the deck:

> @desc here=You are in a small treehouse near the top of a large tree. A deck can be seen outside.
Set.
> @dig Deck=deck;out,treehouse;house;in
Deck created with room number 1446.
Opened.
Linked.
Opened.
Linked.
> deck
Deck (#1446R)
Obvious exits:
treehouse
> @desc here = You are standing on the deck attached to the treehouse. A field can be seen below.
Set.

Now the tree, the treehouse, and the deck have been created. To link the field to the tree and the deck, you can use the @open command to create specific exits

> @open in1;in2;in3;... = #DBREF , out1;out2;out3;...

which will open an exit from the current room to the room specified by the DBREF. The exit will have the entrance names specified in the in-list. Another exit will go from the DBREF room to the current room, and will have the names specified in the out-list.

You can leave off the out-list. In that case, the exit from the DBREF room to the current room is not created.

Using the @open command, we can create the exits from the field to the tree:

> @open tree;up;u=#1442,field,down;d
Opened.
Linked.
Opened.
Linked.

The messages for opening and linking are indicating to you that both the incoming and outgoing links from the tree to room #1442 have been created.

Next, we can create the exit from the deck to the field by teleporting to the deck and then using the @open command without an out-list, thereby creating a one-way link from the deck to the field, but not the other way. Assume the field room has a DBREF of 1440.

> @tel #1446
Deck (#1446R)
You are standing on the deck attached to the treehouse. A field can be seen below.
Obvious exits:
treehouse
> @open field;jump;down;d=#1440
Opened.
Linked.
> l
Deck (#1446R)
You are standing on the deck attached to the treehouse. A field can be seen below.
Obvious exits:
treehouse field

Now the example is complete!

Rooms as Homes

To set your home to a particular room, use the @link command:

> @link object = #room-number

If you are in the room you want to change to your home, you can use the shorthand keyword here in place of the room-number:

> @link me = here

You can also allow other players to set their homes to one of your rooms by setting that room's ABODE flag. Rooms that are set ABODE may become other players homes.

In addition, rooms may be linked to other rooms using the same @link command

> @link room = #other-room

which will make room a so-called "drop-to" room. Objects that are dropped in room are sent to other-room. For instance, in the tree example, you can set the tree's @link to be the field. Then, any object dropped from the tree will fall down to the field:

> @tel #1442
Tree (#1442R)
You see a large tree. There seems to be a treehouse up in the branches.
Obvious exits:
treehouse field
> @link here = #1440
Dropto set.
> drop brick
Dropped.
> l
Tree (#1442R)
You see a large tree. There seems to be a treehouse up in the branches.
Obvious exits:
treehouse field
> down
Field (#1440R)
You are standing in the middle of a field. There is a large tree here.
Contents:
brick
Obvious exits:
tree north south east west

If a drop-to room is also set to be STICKY, then any objects dropped in it will fall to the next room only when all the players have left the drop-to room. Think of the STICKY flag on a room as a delayed drop-to action.

Examining Exits

Exits are really one-way streets from one room to another. To create a path going from one room to another both ways, you actually have to create two exits—one exit going one direction and the other exit going the opposite direction.

Once an exit is created, it shows up if you examine the room from which it leaves. For instance, if we examined the Deck of the example:

> examine here
Deck (#1446R)
Type: ROOM
You are standing on the deck attached to the treehouse. A field can be seen below.
Owner: Speedy  Key: *UNLOCKED*
Contents:
Speedy (#5Pc)
Field;jump;down;d (#1451E)
Treehouse;house;in (#1448E)

Thus, with the examine command, you can see all the exits that are going out of a room.

You can also get a list of all the links going into a room by typing:

> @entrances #room-number

This will also show all the objects whose homes are set to that room.

> @entrances here
Treehouse (#1443R) (Deck;out)
1 entrance found.

Exit Attributes

Exits can have the same types of attributes that other objects have, such as @succ or @fail messages. Here is a summary of attributes as they apply to exits:

@succ

Message displayed when a player goes through the exit successfully. It is displayed to the player going through the link.

@osucc

Message displayed to the other people in the room from which the player is leaving successfully.

@asucc

Actions to be executed when a player leaves a room successfully. Not present in MUCK.

@fail

Message displayed when a player fails to go through an exit. It is displayed to the player who fails to pass through the link.

@ofail

Message displayed when a player fails to go through an exit. It is displayed to the people in the room from which the player is trying to leave.

@afail

Actions to be executed when a player fails to exit a link successfully. Not present in MUCK.

@drop

This attribute does not apply to exits. It is included here for completeness with the other drop attributes.

@odrop

Message displayed to the other people in a room that a player is entering successfully. Not present in MUCK.

@adrop

Actions executed when a player enters a room successfully. Not present in MUCK.

As a rule, you should define the @osucc, @ofail, and @odrop attributes on any exit you create. In this way, a message will be displayed to the people in the room that the player is leaving, and another message will be displayed to the people in the room that the player is entering. You can also define the @desc attribute on a exit, so that something is displayed to a player who tries to look at it.

Special Exits

Most exits from one room lead into another room. However, you can create special NULL exits that display messages to players rather than move them to different rooms. To do this, create an exit on a room, set its lock to #0, and then set its @fail message to the message you want to display when the player types that exit name. You should also set it DARK.

For example, perhaps you want to display the message You wave to the crowd when the player types the command wave. To accomplish this:

> @open wave = here
Opened.
Linked.
> @lock wave = #0
Locked.
> @fail wave = You wave to the crowd.
Set.
> @set wave = DARK
Set.
> wave
You wave to the crowd.

NULL exits can also be used to display a message to the user when he or she tries to move in a direction that does not exist. Normally, when a player tries to move in a non-existent direction, a default Huh? (Type 'help' for help) message is displayed to that player. The Huh? message is displayed for any unrecognized command that the player types. A better, more informative message would be something like You cannot go in that direction. To create this, create a NULL exit as mentioned above. Then, for the exit's name list, specify the directions for which you want the message to appear.

For instance, suppose a room only has a north exit. You want to display the You cannot go in that direction message when the player tries to go in a direction other than north. So, create an exit whose name list has all the non-north directions and abbreviations, and then set up its @lock and @fail:

> @open east;e;west;w;south;s = here
Opened.
Linked.
> @lock east = #0
Locked.
> @fail east = You cannot go in that direction.
Set.
> @set east = DARK
Set.
> east
You cannot go in that direction.
> west
You cannot go in that direction.
> south
You cannot go in that direction.

Other Flags on Rooms and Exits

To allow people to be able to teleport into your room, set the room JUMP_OK. To allow people to create links that lead into your room, set your room LINK_OK. Note that other players still can't create links that lead out of your room—you have to do that.

The TRANSPARENT flag, when set on an exit, causes the description of the next room to be seen when a player looks at that exit. This allows players to see into adjoining rooms.

Unlinking Exits

You can unlink an exit by using the @unlink command:

> @unlink exit

This will unlink the destination of the exit. You can then relink the destination to some other room using the @link command. Exits become owned by whomever links them, so you shouldn't leave an exit unlinked.

Containers

You can create objects that can contain other objects by setting the object ENTER_OK. Then, to go inside the object, use the command:

> enter object

and to go out of the object, use the command:

> leave

Enter and Leave Attributes

The normal @desc attribute is the description of the container, and it is displayed to players that look at the object from the outside. The @idesc attribute sets the message that is displayed to anyone inside the container who types the look command.

There are several attributes that are triggered when an object is entered by something, or when something exits an object. The @enter attribute is displayed to the entering object, the @oenter attribute is displayed to anyone else inside the object, the @oxenter message is displayed to people who are in the room that the player leaves, and the @aenter attribute is a list of actions that are to be executed when an object is entered. The @leave, @oleave, @oxleave, and @aleave attribute correspond similarly for objects that are leaving a container.

> @create phone booth
phone booth created as object #999.
Set.
> @desc = You see a telephone booth here.
Set.
> @idesc = You are inside a phone booth. There is a coin-operated telephone attached to one side of the booth.
> @enter phone booth = You enter the phone booth.
Set.
> @oenter phone booth = :squeezes into the phone booth with you.
Set.
> @oxenter phone booth = :enters the phone booth.
Set.
> @leave phone booth = You leave the phone booth.
Set.
> @oleave phone booth = :departs from you, leaving the phone booth.
Set.
> @oxleave phone booth = :leaves the phone booth.
Set.

Pronoun Substitutions

Sometimes you want to create sentences in your attribute messages that depend on the gender or name of the player performing some action on an object. The attributes that begin with @a (such as @asucc, @afail, @adrop, and so forth) frequently use special substitutions in their actions.

For instance, perhaps you want to create a cat that meows when it is dropped. You want to display a message to everyone that the cat meows at him when dropped by a male player, and meows at her when dropped by female player. In addition, you want to use the dropping player's name in the message. You can do this using special pronoun substitutions:

> @adrop cat = %N drops the cat, which lands on the ground and meows at %o.

In the preceding message, the player's name is substituted for the %N portion of the message, and the objective form of the player's name is substituted for the %o part of the message. In this manner, a male player named Linus would trigger a message Linus drops the cat, which lands on the ground and meows at him, while a female player named Lucy would trigger the message Lucy drops the cat, which lands on the ground and meows at her. The mud determines which pronoun to substitute by looking at the gender of the player, which is stored in the @sex attribute.

There are several types of pronoun substitutions:

%N, %n

Substitutes the player's name. %N is the capitalized form; %n is not capitalized.

%S, %s

Substitutes the subjective form of the player's name (he/she/it/they). %S capitalizes the first letter; %s does not.

%O, %o

Substitutes the objective form of the player's name (him/her/it/them). %O capitalizes the first letter; %o does not.

%P, %p

Substitutes the possessive form of the player's name (his/her/its/their). %P capitalizes the first letter; %p does not.

%A, %a

Substitutes the absolute possessive form of the player's name (his/hers/its/theirs). %A capitalizes the first letter; %a does not.

Try It Out!

This information is enough to get you started on creating objects, setting some of their attributes, building some rooms and linking them up with exits, and making your own little virtual world.

The next few sections will describe some specifics for several types of muds: MUCKs, MUSHes, and MUSEs.

Programming a MUCK

MUCK, which is a pun on the term MUD, is a spin-off of the original TinyMUD. This section describes TinyMUCK version 2.2.

Popular MUCKs

There are many popular MUCKs on the Internet. Some of them were among the first muds to appear on the Internet and, as a result, have a large population of longtime mud players.

Name

Machine Name

Internet Address

Port

AnimeMUCK

anime.tcp.com

128.95.10.106

2035

CaveMUCK

cave.tcp.com

128.95.44.29

2283

FurryMUCK

sncils.snc.edu

138.74.0.10

8888

NAILS

flounder.rutgers.edu

128.6.128.5

5150

FurryMUCK, one of the earliest muds, harbors a large group of devoted players. Its theme is anthropomorphic animals—characters that are animals with human characteristics.

These addresses are current as of August, 1994. Keep in mind that they may change.

Things Specific to MUCKs

From the player's standpoint, MUCKs operate similarly to other types of mud on the Net. Beneath the visible text, however, programmers will find that they are significantly different. This section indicates some of the principle features of programming in MUCKs.

MUF Programming

In order to program more complex objects in MUCK, you have to learn how to program in the MUCK programming language, called Multi-User Forth, or MUF for short.

Using the MUF Editor and Compiler

MUF programs must be entered into the MUCK and then compiled in order for them to function. To enter the editor, you can type:

@program program-name

This will put you into the MUCK editor. You can then enter insert mode by typing

line-number i

which will start inserting what you type before the given line-number. To exit insert mode, type a period (.) on a line by itself.

You can then compile the program by typing:

c

And, finally, you can run the program by typing:

????

A more detailed listing of editor commands can be found in the MUCK Reference Manual section, later in this chapter. This should be enough to get you started.

MUF Basics

In MUF programs, comments are enclosed in parentheses:

(This is a comment)

MUF programs consist of words. A word is simply a series of statements. They usually manipulate the stack in some manner. A word begins with a semicolon, followed by the name of the word, the statements of the word, and then ending with a semicolon:

: word-name
   statements
;

There are three basic types of values in MUF: the integer, the string, and the DBREF. Strings are enclosed in double-quotes. DBREFs are denoted by putting a pound symbol (#) in front of the DBREF number:

7        (This is an integer)
"Test"   (This is a string)
#354     (This is a DBREF)

MUF is a stack-based programming language based on Forth. If you are not familiar with the concept of a stack, it is a place to hold information, and it has a "top" element that can be accessed as necessary. When you "push" an element onto the stack, that element becomes the new "top" of the stack, similar to stacking plates on top of one another. The first element to be removed, or "popped" from the stack is the top element. The next element to be removed is the element under the top element, and so forth.

You can put these basic values onto the stack by simply specifying them in your MUF words:

: stack_test
     56
     "First string"
     #45
     "Second string"
;

In this example, the stack now has four values on it. The number 56 is at the bottom of the stack because it was pushed onto the stack first. The Second string is on the top of the stack, and we can access it if we look at the top of the stack or pop the top value from the stack.

The indentation did not matter in the previous example. Indentation is simply used to make MUF programs easier to read. The previous example can also be written:

: stack_test
     56 "First string" #45 "Second string"
;

Basic MUF Functions

MUF functions operate on the top of the stack. A value may be taken from the top of the stack, processed in some manner, and perhaps put back onto the stack. More commonly, the top two values are taken from the top of the stack and then processed in some manner to result in one new value, which is then placed back onto the top of the stack. The addition function behaves in this manner. It takes the top two values from the stack, adds them together, and then places the result back onto the stack:

: simple_add
     5 8 +
;

This simple addition would first place 5 onto the stack, followed by 8. The + operator would then pop these two values off the stack, add them together, and push the result, 13, back onto the stack. The number 13 could then be used in some fashion.


Note: This is the same as RPN (Reverse Polish Notation), also known as postfix. Anyone familiar with the high-end HP calculators will know how to use it already.

Another example is

: more_add
     4 5 9 + 8 + +
;

which first puts 4, 5 and 9 on the stack. It then adds the top two values, 5 and 9, and pushed their sum, 14, back onto the stack. It then pushes 8 onto the stack. The next addition adds 14 and 8 together to get 22, and the last addition adds 4 and 22 together to get 26. Thus, at the end, the stack has one value: 26.

Subtraction, multiplication and division work in a similar manner. For subtraction, the top value is subtracted from the value underneath it. For division, the second-from-the-top value is divided by the top value.

The equality function is an equals sign (=). It pops the top two integers from the stack and compares them. If they are equal, 1 is pushed onto the stack. If they are not equal, 0 is pushed onto the stack. Thus:

: equals_test
     4  100  =  7  7  =
;

would result in a stack of: 0 1.

Similar to the equality function, the dbcmp function also compares two values on the top of the stack. It compares two DBREFs. If they are equal, 1 is pushed, otherwise 0 is pushed.

: dbcmp_example
     #54  #54  dbcmp
;

would result in the stack consisting of the number 1.

As mentioned previously, the top value can be removed from the stack by "popping" it. The pop function accomplishes this in MUF programs, appropriately enough:

: pop_example
     5 7 pop 8 9 pop
;

This places 5 and 7 onto the stack, pops 7 back off, then places 8 and 9 onto the stack and pops 9 back off. The stack would thus be 5, 8, with 8 being the top of the stack.

Another basic function is the swap function. It switches the top two values on the stack around:

: swap_example
     4 5 swap 7 swap
;

This program would place 4 and 5 onto the stack, then swap them to get 5 and 4. The number 7 is then pushed onto the stack, to get 5, 4 and 7. The last swap would swap 4 and 7. The end result is 5, 7, 4, with 4 being at the top of the stack.

One more frequently used function is the duplicate function, dup. It simply pushes a copy of the top of the stack onto the stack:

: duplicate_example
     4 dup 7 dup
;

After this function, the stack would be 4, 4, 7, 7. The second 7 would be on the top of the stack.

Variables

You can use variables in MUF code. First, you must declare the variable by putting:

var variable-name

at the top of the program. Once declared, the variable can be used in a variety of ways.

The variable storage function is an exclamation point (!). It places the next-to-the-top value into the variable named on the top of the stack.

var testvar
: variable_storage_example
     7 testvar !
;

This puts the value 7 into the variable named testvar.

To retrieve the value of a variable, use the fetch function, which is an "at" symbol (@). It pops the top value on the stack and uses it as a variable name. The contents of that variable are then placed back onto the stack:

var testvar
: variable_fetch_example
     7 testvar !
     testvar @
;

This first places the value 7 into the variable named testvar. It then accesses testvar and places its contents, 7, onto the stack. The stack, then, would consist only of the number 7.

Three special variables in MUF are me, loc, and trigger. The me variable contains the DBREF of the playerm, and loc contains the DBREF of the player's current room. The trigger variable contains the DBREF of the player who triggered the program. These variables will be used in later examples.

Messages

To send a message to an object, you use the notify function. This function sends the string at the top of the stack to the player at the second top element of the stack:

: notify_example
     me  @  "Hello, there!"  notify
;

This example first retrieves your DBREF from the me variable. It then pushes a string onto the stack. Finally, it uses the notify function to send that string to you.

Conditional Statements

MUF has an IF-THEN construct similar to other programming languages. However, it has a major difference with the IF-THEN statement you may be familiar with from other programming languages. In MUF, the IF-THEN statement is more like a compare and jump statement in assembly language.

if
     if-statements
then
following-statements

In the preceding syntax, the if keyword pops the top value from the stack. If the value does not equal 0, the if-statements are executed, and then the following-statements are also executed. The if-statements consist of all statements up to the next then keyword. If the value popped by if is 0, the if-statements are skipped, and only the following-statements are executed.

As an example, consider:

: if_example
     4 2 2 +  =
     if "The values were equal"
     then "Top string"
;

First, 4 and the sum of 2 and 2 are compared, using the equality function. Since they are equal, the if statement pushes The values are equal onto the stack. It then pushes the string Top string onto the top of the stack.

The program

: if_example
     4 2 3 +  =
     if "The values were equal"
     then "Top string"
;

would only push the string Top string onto the stack because 4 and 5 are not equal.

As a helpful hint, it may be useful to think of the then keyword as an endif.

An Example MUF Program

With these concepts, you can create many MUF programs. In addition, you can use the built-in functions that are available in MUF. For a listing of these, consult the MUCK Reference Manual, later in this chapter.

Programming a MUSH

MUSH, which stands for Multi-User Shared Hallucination, is a spin-off of the original TinyMUD. This section describes TinyMUSH version 2.0.

Popular MUSHes

There are several MUSHes on the Internet. Many of them have certain themes.

Name

Machine Name

Internet Address

Port

Deep Seas

muds.okstate.edu

139.78.9.1

6250

DuneMUSH

mellers1.berkeley.edu

128.32.243.78

4201

NarniaMush

argo.unm.edu

129.24.9.24

6250

NeverendingStory

jove.cs.pdx.edu

131.252.21.12

9999

PernMUSH

cesium.clock.org

130.43.2.43

4201

Shadowrun

yacht.slip.andrew.cmu.edu

128.2.116.75

4201

TinyCWRU

caisr2.caisr.cwru.edu

129.22.24.22

4201

DeepSeas, previously known as SpaceMadness, DreamScape, Asylum, Chaos, and TinyHELL, is another long-standing mud with a consistent player base. A lot of dino mudders (long-timers) can be found there.

These addresses are current as of August, 1994. Keep in mind that they may change.

Things Specific to MUSHes

In addition to the commands and objects previously mentioned in the tutorial section, there are a few things that are specific to MUSHes.

Possessive Pose

You can use a semicolon to possessive-pose. This is the same as posing (acting), except that it adds a possessive s after your character name and before the action message

;message
> ;brain hurts.
Speedy's brain hurts.

Puppets

Puppets are special types of objects that seem just like players. Puppets can be controlled by their owners and can see and hear things in a room just like a player would. The controlling player can then use the information returned by the puppet because the puppet echoes the text it sees and hears back to its owner. It does not echo back actions that are performed in the same room as its owner, to prevent message confusion.

To change an object into a puppet, set the object to be a puppet: @set object = puppet. The puppet will announce that it has grown ears and can now hear. After it becomes a puppet, you can use its name or its DBREF to have it perform actions that you want.

You can force an object to perform some action by using @force object = actions. Or, you can use DBREF actions. The object will behave as if it, itself, had typed the action.

> @create a little dog
a little dog created as object #333
> @set little dog = puppet
a little dog grows ears and can now hear.
Set.
> inventory
You are carrying:
a little dog (#333p)
You have 930 credits.
> @desc little dog = You see a little puppy.
Set.
> drop little dog
a little dog> Speedy's Room
a little dog> You are in Speedy's Room.
a little dog> Contents:
a little dog> Speedy (#5Pc)
a little dog> Obvious exits:
a little dog> north
a little dog> Dropped.
Dropped.
> l little dog
a little dog (#333p)
You see a little puppy.
> @force little dog = :wags its tail.
a little dog wags its tail.
> #333 :pants happily.
a little dog pants happily.
> #333 "Yap yap!
a little dog> You say "Yap yap!"
a little dog says "Yap yap!"
> #333 north
a little dog walks north out of Speedy's Room.
a little dog has left.
a little dog> Hallway
a little dog> You are in a short hallway. Speedy's room is to the south. A stairway can be seen to the north.
a little dog> Obvious exits:
a little dog> north south
> #333 south
a little dog> You walk south into Speedy's Room
a little dog> Speedy's Room
a little dog> You are in Speedy's Room.
a little dog> Contents:
a little dog> Speedy (#5Pc)
a little dog> Obvious exits:
a little dog> north
a little dog walks in from the north.
a little dog has arrived.
> @set #333 = DESTROY_OK
Set.
> @destroy #333
a little dog> *NOTHING*
You get back your 10 credit deposit for a little dog (#333).
Destroyed.

Listening and Responding to Messages

Sometimes it's fun to program an object that listens for certain strings and responds to those strings in some manner. The @listen directive will set the pattern string and the @ahear attribute sets the actions that are executed when the listen string is matched.

> @listen object = string
> @ahear object = actions

When using @listen, the string frequently has some word or phrase that the object is listening for, plus some wildcard characters to match whatever else might be in a message. If a matching string is seen, the @ahear actions are then executed. For instance, the command

> @listen me = * movie*

would be looking for a string of anything, followed by a space, followed by the word movie, followed by anything else. This could match something like Speedy went to see a movie today. It could also match What's playing at the movies tonight?.

> @listen me = * movie*
Speedy - Set.
> @ahear me = :wanna direct!
Speedy - Set.

Then, later, maybe someone mentions movies. That triggers the response automatically:

Archimedes went to see a movie last night.
Speedy wanna direct!
Mak says, "Which movie did you see?"
Speedy wanna direct!

In addition to the @ahear attribute, there is also an @amhear and an @aahear attribute. @ahear responds only to messages that the listening object did not generate. @amhear only responds to messages that the object itself generated. @aahear responds to all messages.

Percent Substitutions

Whenever an action occurs, the mud stores information related to that action in a special storage area. These variables can then be accessed using percent substitutions.

Percent substitutions are simply variables that begin with a percent sign. For instance, in the previous section, you learned about pronoun substitutions. Pronoun substitutions are just special kinds of percent substitutions.

One of the items that the mud stores is the name of the enactor—the object that caused an action. As described in the previous section, the name of the enactor is stored in the %N variable. The %N variable is the capitalized name, such as Speedy, and the %n variable is the uncapitalized form, such as speedy. Additionally, the actual DBREF of the enactor can be accessing by using the %# variable.

Another item stored by the mud is the affected object—the object on which the action is being performed. The DBREF of this object can be accessed by using the %! variable.

For example, if Speedy dropped a bowling ball, Speedy would be the enactor, and the bowling ball would be the affected object. Speedy's name could be accessed using %N or %n, and Speedy's DBREF could be accessed using %#. The DBREF of the bowling ball could be accessed using %!.

The DBREF of the location of the action can be accessed through the %l variable.

There are several special percent substitutions that are used for text formatting. These formatting characters resemble the special formatting characters in the C programming language: %r converts into a carriage return-newline combination, %t converts into a tab character, %b converts into a blank space, and %% converts into an actual percent sign.

That is why you have to type two percent signs when you want to say a line with a percent sign in it. If you say

> "24.6% of all statistics are made up on the spot!
Speedy says "24.6 of all statistics are made up on the spot!"

you notice that the percent sign disappears. The mud is trying to convert it to a percent substitution, and a percent sign followed by a blank space converts into a blank. To get a percent sign into your text and actions, type two percent signs

> "24.6%% of all statistics are made up on the spot!
Speedy says "24.6% of all statistics are made up on the spot!"

since the %% is the formatting specification for a percent sign.

Another way to get an actual percent sign is to use the escape character, which is a backslash (\):

> "24.6\% of all statistics are made up on the spot!
Speedy says "24.6% of all statistics are made up on the spot!"

The escape character causes any of the characters following it to be printed as-is.

Registers

In addition to the various percent substitutions just mentioned, there are 26 registers that you can set using @va through @vz and access by using %va through %vz. These registers are like attributes or variables. They can store just about any mud value—numbers, strings, messages, function results, and so forth. To set a register, use the syntax

> @register object = actions

and then access it using the corresponding percent-substitution, %register.

As an example, consider creating a water balloon that splats when it is dropped. The va register will be used to print out a message when the balloon is dropped.

> @create water balloon
water balloon created as object #1765.
> @va water balloon = SPLAT!
Set.
> @drop water balloon = The balloon falls and goes %va.
Set
> drop water balloon
The balloon falls and goes SPLAT!

Triggers

You can also use the register to perform an action. To do this, you have to trigger the register using the trigger command:

> @trigger object/attribute

The @trigger command can be abbreviated @tr.

In the water balloon example, a more realistic action would be for the water balloon to destroy itself when it is dropped. You can put the destroy command in a register, and then trigger it using the trigger command when the balloon is dropped. So, adding to the water balloon example:

> @vb water balloon = @destroy me
Set.
> @adrop water balloon = @tr me/vb
Set.
> drop water balloon
The balloon falls and goes SPLAT!
water balloon has left.
You get back your 10 credit deposit for water balloon (#1765).

When the balloon is dropped, the @drop attribute used the va register as a string, and the @adrop attribute triggered the vb register, which destroyed the balloon.

With 26 registers to play around with, you can perform a lot of complex programming. You can use registers to store temporary information. Registers can trigger other registers, too.

Numbered Variables

You can also make use of the 10 numbered variables, named %0 through %9. These variables are collectively known as the stack in mud terms, although it isn't really a stack in the computer science sense of pushing and popping objects. The stack is just a storage area for the 10 numbered variables.

These numbered variables are known as positional parameters. They are set consecutively using two methods: the @listen command and the @trigger command.

To illustrate the @listen command and how positional parameters are set, consider a parrot that listens for phrases with the word Parrot in them. The parrot will speak the three phrases that come after the trigger word Parrot:

> @create parrot
parrot created as object #1799.
> @listen parrot = * says "Parrot * * * *
parrot - set.
Set.
> @ahear parrot = "SQUAWK %1 %2 %3
Set.
> drop parrot
Dropped.
> "Parrot can you hear?
You say "Parrot can you hear me?"
parrot says "SQUAWK can you hear"
> "Parrot tell a story to us.
You say "Parrot tell a story to us."
parrot says "SQUAWK tell a story"

In this simple example, the asterisks in the @listen command convert to numbered variables %0, %1, %2, %3, and %4. The first asterisk matches the player's name from the spoken text, and this is placed in the variable %0. The three phrases after the string Parrot are matched and placed into numbered variables %1, %2, %3, and %4, respectively. The %1 variable is the first word after Parrot, %2 is the second word, %3 is the third word, and %4 is everything else, including the ending double-quote. The @ahear command then uses some of these variables in its spoken text.

The @trigger command can also be used to set the numbered variables, using the format:

> @trigger object/attribute = item, item, item, ...

This command sets the positional parameters to the given items, consecutively, starting from %0. The attribute that is triggered can then access these numeric variables.

Consider a globe that has its va attribute programmed as follows:

> @va globe = @emit The globe %0, %1, and %2.
Set.

Now, to get %0, %1, and %2 to be shimmers, sparkles, and glows eerily, you can use the @trigger command:

> @tr globe/va = shimmers, sparkles, glows eerily.
Triggered.
The globe shimmers, sparkles, and glows eerily.

Note how the parameters to the @trigger command become the numeric variables for the va attribute.

Braces

You can use braces to surround strings so that commas within them do not get interpreted by the mud as separation characters.

Consider the globe in the previous section. What if you wanted the second phrase to be hums, glistens instead of sparkles? If you type

> @tr globe/va = shimmers, hums, glistens, glows eerily.

you get

Triggered.
The globe shimmers, hums, and glistens.

This is because the comma separating hums and glistens is taken to be a parameter separator.

In cases like this, you want a comma to be taken as an actual comma, rather than a parameter separator. You can use braces to specify that the string within the braces is to be taken as a whole unit, and any commas within the braces are part of the string:

> @tr globe/va = shimmers, {hums, glistens}, glows eerily.
Triggered.
The globe shimmers, hums, glistens, and glows eerily.

So remember, when you want to get an actual comma into a string, you may need to throw a pair of braces around the string. Braces are also frequently used in function calls and switch statements (both discussed later in this section), since those programming constructs commonly use commas.

Using an Object

You can also trigger an object by using it. To use an object, simply type the use command:

> use object

This command triggers the @use, @ouse, and @ause attributes. The object will respond to the use command only if the @ause attribute has been set on the object.

Functions

The format for a function call is:

[ function-name(parameters...) ]

The parameters of the function must be enclosed within parentheses, and the function itself must be enclosed in square brackets.

As an example, the name() function returns the name of an object when given its DBREF. If object #5 was the player Speedy, you could determine the name by using the name() function and the object number:

> @emit [name(#5)]
Speedy

Functions can be nested, and nested functions only require one outermost set of square brackets. You can put the name() function, mentioned earlier, and the Ustrlen() function, which returns the length of a string, together to find out the length of the name of object #5 by typing:

> @emit [strlen(name(#5))]
6

Sometimes, you may want to evaluate the value of an attribute as though it were a function. In those cases, you may have to add additional square brackets to denote that you are trying to access a variable as a function.

For instance, the get(object/attribute) function returns the value of the named attribute on a given object. If the va and vb attributes on some test object are defined as

> @va testobject = vb
Set.
> @vb testobject = blah blah
Set.

then by accessing va you see

> @emit [get(testobject/va)]
vb

and by accessing vb indirectly through va you see

> @emit [get(testobject/[get(testobject/va)])]
blah blah

because [get(testobject/va)] returns vb, which is substituted into the outermost get()function to return blah blah.

There are dozens of predefined functions to choose from. A few important functions are discussed next. For a description of the rest of the functions available, or for quick reference, see the function glossary section, later in this chapter

The v() Function

The v() function is simply another way to access the 26 v-registers. The code [v(va)] is functionally equivalent to %va. However, the percent sign form is evaluated faster than the function call form, so it tends to be used in most cases.

The s() Function

The s() function performs pronoun substitution on a string, and returns that string. The pronouns apply to the object that triggers the function.

Thus, if your character has male gender, and you evaluate

> @emit [s(%P went down the road.)]

you see

He went down the road.

And, if your character had female gender, you would see:

She went down the road.

All the pronoun substitutions, discussed earlier, can be used in the s() function.

The get() Function

The get() function, mentioned earlier, is another frequently used function. It is used to access various attributes from a particular object. Its syntax is

[get(object/attribute)]

The rand() Function

This function tends to be used frequently. The syntax is

rand(number)

and it returns a random integer between 0 and (number - 1).

The Switch Command

You can create conditional expressions on an object by using the switch command. The switch command is similar to a CASE statement in a programming language. There is a conditional expression that is evaluated and, based on the results of that evaluation, different actions are performed.

The format for the switch command is:

> @switch test = condition1, action1, condition2, action2, ..., conditionN, actionN, default

The switch command tests the result of the test against each condition. If there is a match, the corresponding action is performed.

As an example, consider programming a dog to obey commands you give it. When you tell the dog to sit, it sits down; when you tell the dog to speak, it barks, and so forth. You can accomplish this by using the switch command. First, set up the dog to listen for commands:

> @create Rover
Rover created as object #6745.
> @listen Rover = *"Rover, *"
Set.

Now, use the switch command on the @ahear attribute to perform different actions based on what a player commands Rover to do:

> @ahear Rover = @switch %1 = sit , :sits down. , speak , "RARWK!, jump, :does a backflip., play dead, :lies down on the ground., beg, {:whimpers, cries, and looks utterly heartbroken.}
Set.

Now you can tell Rover what to do:

> drop Rover
Dropped.
> "Rover, sit
You say "Rover, sit"
Rover sits down.
> "Rover, speak
You say, "Rover, speak"
Rover says "RARWK!"
> "Rover, jump
You say "Rover, jump"
Rover does a backflip.
> "Rover, play dead
You say "Rover, play dead"
Rover lies down on the ground.
> "Rover, beg
You say "Rover, beg"
Rover whimpers, cries, and looks utterly heartbroken.

Note that the conditions and actions are separated by commas. As mentioned previously, if you want to use a comma or a semicolon in one of your conditions or actions, make sure you surround the statement with braces ({}). Otherwise, a comma signifies a new condition or action, and a semicolon signifies the end of the switch command.

The last action in the switch command for Rover is enclosed in braces because the action contains commas within it.

As another example, you can achieve an IF-THEN-ELSE effect by using a switch statement and testing for either 1 or 0 in the conditionals:

> @create Parrot
Parrot created as object #6746.
> @listen Parrot = * has arrived.
Set.
> @ahear Parrot = @switch [eq("Speedy", %0)] = 1, {:flies around squawking, "Speedy is here! Speedy is here!"}, 0, :ignores %0.

The test portion of the switch command tests to see if Speedy is the name of the player who is entering the room. If so, it flies around and announces Speedy's entrance; if not, it ignores the entering player:

Snowball has arrived.
Parrot ignores Snowball.
Speedy has arrived.
Parrot flies around squawking, "Speedy is here! Speedy is here!"
Pooka has arrived.
Parrot ignores Pooka.

Again, note the braces around the true part of the command because of the comma within it.

User-Defined Commands

Perhaps you want to create an object and then define some specialized commands on that object. You can create a stuffed bear that growls when you squeeze it. The squeeze command is not a predefined command in the mud. You have to define it. You can create user-defined commands by setting them on a register:

> @attribute object = $command:actions

To define the squeeze command on the bear:

> @va bear = $squeeze:@emit The stuffed bear grrrowls huskily.

Then, when you type

> squeeze

you see

The stuffed bear grrrowls huskily.

You can define multiple commands on an object. Just make sure that you don't pick a command name that is already used, such as page or get, because predefined mud commands take precedence over user-defined commands.

You can allow your user-defined commands to accept arguments, too. You specify these arguments by using asterisks (*) in the command definition. These asterisks are converted into the positional parameters for the attribute that defines the command. For instance, you can change the squeeze command to accept an argument:

> @va bear = $squeeze *:@emit You squeeze the bear's %0. The bear grrrowls huskily.
Set.
> squeeze tummy
You squeeze the bear's tummy. The bear grrrowls huskily.

User-Defined Attributes

In addition to user-defined commands on an object, you can also create user-defined attributes on an object. The format is:

> &attribute object = anything

You can also define an attribute using

> @set object = attribute:anything

You can set an attribute on an object to anything you want. You can use it for temporary storage of variables, names or DBREFs of objects, strings, and so forth. You can define an unlimited number of attributes on an object.

Make sure that your user-defined attribute does not conflict with an already-defined attribute. As you create more and more complex objects, the chances increase for you to think of an attribute that you have already defined on that object, and you end up redefining something that you have already written!

You can access these attributes using the get() function or the v() function.

> @va bear = $squeeze:@emit You squeeze the bear.;&lastsqueeze bear = %N
Set.
> @vb bear = $last:@emit This bear was last squeezed by [get(me/lastsqueeze)].
Set.
> squeeze
You squeeze the bear.
> last
This bear was last squeezed by Speedy.

This example sets a user-defined attribute called lastsqueeze whenever the bear is squeezed. The lastsqueeze attribute is set to the squeezing player's name. Then, when the player types last, this attribute is used to recall which player last squeezed the bear.

The Queue

Each command that the mud executes goes into a queue first. The mud then runs commands out of the queue. Most of the time, the commands are executed immediately. However, some commands delay action for a few rounds, such as @trigger and @force.

To get a listing of the queue, you can use the @ps command. This command displays four queues. The Player Queue shows actions that you have triggered. The Object Queue shows actions that have been triggered by objects that you own. The Wait Queue displays commands that have been queued up and thus will be executed at some future point in time. And the Semaphore Queue shows semaphores, explained next. The @ps command has options you can use to obtain different process displays, such as a verbose listing, a brief listing, or a quick summary. See the Help on your mud for a description of these options to the @ps command.

The Wait Command

You can delay commands so that they are executed at a later time by using the wait command:

> @wait #seconds=actions

This queues up the specified actions and runs them after waiting the specified number of seconds. For instance, you can set up a twilight effect by setting up these attributes on a test object:

> @va testobj = @wait 5 = @emit It is starting to get dark.;@tr me/vb
Set.
> @vb testobj = @wait 10 = @emit It gets darker.;@tr me/vc
Set.
> @vc testobj = @wait 15 = @emit It's completely dark now.
Set.

Then, if you trigger the va attribute, the messages are displayed after each wait delay:

> @tr testobj/va

A delay of 5 seconds and you see:

It is starting to get dark.

Then, 10 seconds later:

It gets darker.

And, finally, 15 seconds after that:

It's completely dark now.

The Halt Command

Sometimes, though, the commands that you have queued up will interact with each other in such a way that things get out of control. When these infinite loops occur, you can use the halt command to stop them.

> @halt

clears out your personal queue,

> @halt command

clears out your queue and puts the specified command onto the queue, and

> @halt object=command

clears out the given object's queue and puts the specified command onto the queue.

Semaphores

One of the more advanced mud concepts is the semaphore. A semaphore is a signal that indicates that it is okay for something to perform some action. On many real-life train tracks, semaphores alongside the road indicate that a train has recently passed. The semaphore is initially green, indicating to an approaching train that it is okay for the train to continue. Once the train has passed, the semaphore changes to red. Another approaching train would see the red semaphore and know that another train recently passed through, and it may be necessary for the second train to slow or stop in order to avoid hitting the back end of the first train. A timer on the semaphore eventually changes the red light back to green.

Similarly, a semaphore in a mud is used to signal when certain actions can occur and prevent other actions from occurring until the correct time.

One typical use of a semaphore is to prevent an attribute or object from being triggered until it finishes executing its actions. For instance, you have a vending machine that dispenses magic baseballs. When it is triggered, it starts performing actions to create a new magic baseball and to give that baseball to you. A semaphore can be used to prevent someone from coming along and triggering the machine again while it is in the middle of first action list.

Another common use of semaphores is to force commands to be executed in a specific order. You can create user-defined commands hop, skip, and jump, and force them to be executed in that order through the use of semaphores.

Each semaphore has a count associated with it. The count is the number of actions that are currently blocked, waiting for a notification to unblock them and thus allow them to execute. If the count is 0, an action will occur immediately. A positive number indicates that that many actions are currently blocked. A negative number indicates that that many actions in a row will immediately execute.

The @wait command is used to place an action list on a semaphore and then "block" those actions from occurring until a notification occurs. The syntax is

> @wait object=actions

which will set up a semaphore on the object and enqueue the given actions onto the semaphore's pending action list. If the actions are a list of commands, you have to enclose the list in braces. You can also set up a default execution time by using

> @wait object/#seconds=actions

Such a wait command will behave like a normal wait command, except that after the given number of seconds, the actions execute anyway, regardless of whether an actual notification has occurred. You can use this to make sure a set of actions is eventually executed, even if no notification ever occurs.

The @notify command is used to notify the semaphore. When notified, the semaphore will execute the first action in the action list. The action item will be "unblocked." A second notification will start the second action, and so forth. To notify a semaphore on an object, use

> @notify object

which will execute the first action that is pending on the object's semaphore queue. You can also execute a given number of actions by specifying that number

> @notify object=#notifications

which executes that many actions on the object's semaphore queue.

Finally, the @drain command resets the semaphore count to 0.

Semaphores are usually used on larger, more complex objects, such as vending machines, mud e-mail systems, and so forth. As a simple example of semaphores, consider constructing a trick "ack-in-the-box." The box contains a cat that springs out and coughs up a hairball when the box is wound up. The idea is for the commands relating to the hairball to be executed in a group, without interruption, so a semaphore is used:

> @create ack-in-the-box
ack-in-the-box created as object #1515.
> @desc ack= This is an ack-in-the-box. Type 'wind' to wind it up.
Set.

Now set up the ack-in-the-box to be ready to execute a wait command immediately by setting up a notification for right now, and for when the mud starts up. The startup actions make sure that the ack-in-the-box begins with its semaphore at -1, which means that any action on it will not be blocked.

> @notify ack
Notified.
> @startup ack=@drain me;@notify me
Set.

Now the object is ready to execute an action on it. This next section of code sets up a user-defined command, wind, that performs various actions and then, as its last action, renotifies the ack-in-the-box. This will allow the next wind command to immediately execute:

> &do_wind ack=$wind:@wait me={@emit The box whirrs and humms. Suddenly, the box SPROINGS open, and a scruffy-looking orange cat SPRINGS out of the box!;@create hairball;@desc hairball=You see a slimy cat hairball.;@drop hairball=The slimy cat hairball splats on the floor.;@adrop hairball=@emit A slimy cat hairball splats onto the floor.;@set hairball=DESTROY_OK;@emit The cat says "ACK!" and coughs up a hairball!;drop hairball;@emit The cat is then pulled back into the box, which closes.;@notify me}
Set.
And test it out!
> drop ack-in-the-box
Dropped.
> l
Speedy's Room
You are in Speedy's Room.
Contents:
ack-in-the-box (#1515)
Obvious exits:
out
> l ack
This is an ack-in-the-box. Type 'wind' to wind it up.
> wind
The box whirrs and humms. Suddenly, the box SPROINGS open, and a scruffy-looking orange cat SPRINGS out of the box!
The cat says "ACK!" and coughs up a hairball!
ack-in-the-box dropped hairball.
The cat is then pulled back into the box, which closes.
A slimy cat hairball splats onto the floor.
> l
Speedy's Room
You are in Speedy's Room.
Contents:
hairball (#1530d)
ack-in-the-box (#1515)
Obvious exits:
out
> wind
The box whirrs and humms. Suddenly, the box SPROINGS open, and a scruffy-looking orange cat SPRINGS out of the box!
The cat says "ACK!" and coughs up a hairball!
ack-in-the-box dropped hairball.
The cat is then pulled back into the box, which closes.
A slimy cat hairball splats onto the floor.
> l
Speedy's Room
You are in Speedy's Room.
Contents:
hairball (#1530d)
hairball (#1531d)
ack-in-the-box (#1515)
Obvious exits:
out

As you can see, every time you wind the ack-in-the-box, a slimy hairball is created, which drops onto the floor! If you were holding the ack-in-the-box, it would drop into your hand (and thus into your inventory).

This simple example illustrates the use of semaphores to make sure that the commands to create the hairball describe it, and set attributes on it are not preempted by another wind command, issued as the ack-in-the-box was working on the first wind command.

Putting It All Together: Exploding Jawbreaker Example

Putting all the concepts together, this section will go through the programming of an exploding jawbreaker. The jawbreaker will have a command defined on it that will allow a player to eat it. When the player attempts to eat the jawbreaker, various random amusing things happen. The object will also have several user-defined attributes. These attributes store various variables, strings, and messages.

Here goes!

> @create jawbreaker
jawbreaker created as object #4545.
> @desc jawbreaker = It looks like a giant candy jawbreaker, about the size of a plum. Upon closer inspection, it seems to be made of sugar, nitroglycerin, [name(v(currate))]'s saliva, salt and various corn by-products. Type 'eat jawbreaker' to eat it!
Set.
> @fail jawbreaker = Type 'eat jawbreaker' to eat it.
Set.

This creates the jawbreaker and sets its description. Note the function call within the description. The currate attribute contains the DBREF of the player who last tried to eat the jawbreaker. This attribute is set by other commands later. The name() function uses the value in the currate attribute to generate the name of the player who last ate the jawbreaker.

> &comment jawbreaker = This is a trick jawbreaker that explodes when someone tries to eat it.
Set.

The comment attribute is simply a note to future programmers. It describes what this object does. On very complex objects, it is helpful to throw in a few comments to describe how the object works, so that other people can figure out what is going on!

Next, program the eat jawbreaker command:

> &chew jawbreaker = $eat jawbreaker:@emit [name(%#)] picks up the jawbreaker and pops it into %p mouth!;@trigger me/rand[rand(3)];&lastate me=[get(me/currate)];&currate me=%#
Set.

This sets the eat jawbreaker command and the actions to be performed when eat jawbreaker is typed by a player. There are four actions in the action list.

The first action displays a message to everyone indicating that the player put the jawbreaker in his or her mouth. Note how the %p pronoun substitution is used to print the appropriate possessive pronoun corresponding to the player.

The second action generates a random number from 0 to 2, using the rand() function. This number is appended to the string rand to generate a random attribute name, which is then triggered. One of three attributes will be triggered: rand0, rand1, or rand2.

The third and fourth actions in the action list set the lastate attribute to the last player who ate the jawbreaker, and the currate attribute to the player who is currently trying to eat the jawbreaker. These two attributes can then be used in later commands and actions.

Now, all there is to do is to define the three random actions that are triggered when the player eats the jawbreaker.

> &rand0 jawbreaker=@emit [name(v(currate))] closes [poss(v(currate))] eyes and smiles from ear to ear as the sugar kick from the jawbreaker sets in. Ahhh. After a few seconds of sucrose satisfaction, [name(v(currate))] removes the jawbreaker from [poss(v(currate))] mouth.

This first random action is fairly harmless. Nothing bad happens to the player. The currate attribute is used to determine both the player's name, using the name() function, and the possessive form of the player (his, her, its), using the poss() function.

> &rand1 jawbreaker=@emit [name(v(currate))]'s eyes get real big as the fire-hot super jalapeno pepper flavor of the jawbreaker takes effect! [poss(v(currate))]'s eyes start to water as [subj(v(currate))] screams, "YOW THAT'S HOT!" Suddenly, [name(v(currate))]'s head EXPLODES with a flash and a smell of hot peppers and burnt sugar!! *BOOM* !!;kill [name(v(currate))]=100

This second random action is a bit more violent. It kills off the player, due to the flavorful effects of the jawbreaker, by performing a kill command on that player. The subj() function returns the subjective pronoun of the player.

>&rand2 jawbreaker=@emit [name(v(currate))] gasps, "I've been poisoned by [name(v(lastate))]'s *gag* spit!" In a last-ditch attempt for revenge, [name(v(currate))] throws the jawbreaker at [name(v(lastate))]! [switch (eq(here, loc(v(lastate))), 1, The jawbreaker BONKs [name(v(lastate))] on the head and the unstable nitroglycerides in the jawbreaker EXPLODE!, 0, Luckily, [name(v(lastate))] is not around, and the jawbreaker merely ricochets off the wall and rolls to a stop nearby.)];kill [name(v(currate))]=100;kill [name(v(lastate))]=100

The last random action is somewhat whimsical. It tries to kill off both the current player and the player who last ate the jawbreaker. Note the switch statement in the action list. It tests to see if the player who last ate the jawbreaker is in the same room. If so, an appropriate message is printed as the jawbreaker hits that player. If not, the jawbreaker just rolls around to a stop. Finally, a few kill commands are performed. If the person who last ate the jawbreaker is not in the current room, that kill command will have no effect.

This exploding jawbreaker is amusing to play around with in a room full of people! Players who lose out and are killed by the jawbreaker can simply teleport back to the room, so there isn't much harm done.

Thanks to Jen "Tourmaline" Kleiman for providing the idea behind this example.

Programming a MUSE

MUSE, a variation and elaboration of MUSH, is written in a language called TinyMUSE, another spin-off of the original TinyMUD. TinyMUSE was first implemented in a popular simulated environment called MicroMUSE. This on-line environment was first conceived in 1990 by programmer Stan Lim ("Jin"), who built the original environment in Larry Foard's TinyMUSH programming language. "Cyberion City," as it came to be called, is a beautiful vision of a utopian society in an orbital station high above the Earth, complete with talking robots, spaceships, and otherworldly adventures. As the years went by and the source code was refined and elaborated upon, the newer language became known as TinyMUSE, and a specialized client program, called TinyFugue (also commonly known as tf) was developed to interface with the MUSE during play. TinyMUSE worlds come in a variety of flavors, but the language has become a favorite of many educators because of its ease of use, and its firm but modifiable "social structure."

Almost all of the capabilities of MUSHes can also be found in MUSEs. MUSEs also have a few idiosyncracies all their own, such as a heirarchical player class system.

Popular MUSEs

There are a few thematic MUSEs out there, but the granddaddy MUSE is MicroMUSE.

Name

Machine Name

Internet Address

Port

MicroMUSE

chezmoto.ai.mit.edu

18.43.0.102

4201

Rhostshyl

rhostshyl.cit.cornell.edu

128.253.180.15

4201

TimeMuse

murren.ai.mit.edu

18.43.0.179

4201

TrekMUSE

grimmy.cnidr.org

128.109.179.14

1701

These addresses are current as of August, 1994. Keep in mind that they may change.

MicroMUSE, a popular simulated environment based at MIT, was first conceived in 1990.

TinyFugue, the TinyMUSE client, is available via anonymous FTP to chezmoto.ai.mit.edu and may be found in the pub/muse directory as tf.33a5.tar.gz.

MuseNet Worlds

There are a growing number of TinyMUSE worlds on the Net, of which those listed here represent merely a sample. A number of educational TinyMUSE worlds were incorporated into a single overarching structure known as MuseNet (the Multi-User Science Education Network); any of these worlds may be reached via telnet to any of the affiliated sites.

With the TinyFugue client, you can instantly open bamf portals between any of these worlds, allowing your character to toggle between worlds at a whim. To see a list of available worlds, simply type /listwords from within TinyFugue. To open a connection to another MuseNet world, type /world world-name, and then type ESC-B to bamf through the portal.

The current list of MuseNet worlds includes MicroMuse, BridgeMuse, MariCopa, CyberLib, and EcoMuse. MuseNet worlds can be reached via telnet at any of the following addresses:

musenet.bbn.com
micro.bbn.com
muse.usmee.maine.edu
micro.usmee.maine.edu
bridges.usmee.maine.edu
pico.usmee.maine.edu
femto.usmee.maine.edu
cyberion.usmee.maine.edu
nano.usmee.maine.edu
atto.usmee.maine.edu

Things Specific to MUSEs

The MUSE environment allows for classes of programming capability to be distributed by the MUSE Directors, according to the talent and drive of individual players. The learning curve is therefore broken into a series of plateaus, allowing players to progress at their own speed. The following things are specific to MUSEs.

Commands

There are a few common commands that MUSEs have, in addition to those described in the "Overview of Common Commands" section, earlier in this chapter.

The money command shows your current number of credits and the value of all your assets.

The news command displays the current newsfile, which you should check regularly.

Classes

In TinyMUSE worlds, programming capabilities (powers) and virtual civic duties are conjoined rather formally in a hierarchic structure of roles: Visitor, Citizen, Guide, Official, Corporation, Administrator, and Director (the specific duties and powers of each class are determined by the Directors of any given MUSE, and may be set to affect all lower-ranked users, all equally ranked users, or all users). This system tends to ensure that those players entrusted with powerful characters act in a responsible and accountable manner.

Moving around in the virtual environment and playing with other people's creations is an enjoyable pastime, but the real action begins when you decide to become a MUSE Citizen. At this point, you receive a real character (having been known as guest up until now), and some building privileges. Your character, provided by the officials of the MUSE, will have a name and an associated password, and probably very little else.

The function

class(player)

can be used to access a player's class in MUSE programs.

You can also use functions that access player's powers:

controls(player1, player2, power)

returns 1 if player1 has the specified power over player2. Otherwise it returns 0.

haspow(object, power)

returns 1 if the object has the specified power. Otherwise it returns 0.

Zones

MUSEs have specialized rooms called zones. A zone is a group of rooms acting as if it were one big room. Messages that are sent to a room in the zone can be heard throughout the zone. For instance, you can create a long hallway, composed of three rooms, such as the West End of the hallway, the Middle of the hallway, and the East End of the hallway. Players can be located in any of these three rooms. Then, you can group the three rooms into a zone room. Certain messages that are sent to the zone can be heard by everyone in the hallway rooms. In this manner, you can create large rooms that seem to have a depth to them. You can create a ballroom or a large dance floor using a zone.

To link a room into a zone, use the command:

@zlink room = zone-object

And to emit a message to everyone in the zone, use:

@zemit zone-object = message

There are also a few functions you can use in MUSE code that relate to zones. The function

zone(object)

operates on a given object. If the object is a room, the room's zone is returned. If the object is an exit, thing, or player, the DBREF of the zone that the object is in is returned.

Additionally, the function

zwho(zone-object)

returns a list of the DBREFs of all the players in the zone, and the function

inzone(zone-object)

returns a list of all the rooms that have been z-linked to the zone.

Interactive Narration: "Monster Island" Example

In an object-oriented environment, directing players where you want them to go can be tricky. If done inartistically, linearity can be easily overdone, making things seem like a slow-moving sequence of still images. The trick is to balance the decision to "opt out" of a storyline with various "lures in" to the storyline. It also doesn't hurt to make every room alive with incidental action.

The following environment is excerpted from Tod Foley's "Monster Island," a 1920's pulp adventure MUSE narrative with a fairly strong overarching plotline. The story begins in a dark, secluded bay...

Blackmoor Bay(#248Rpv)

The waters of Blackmoor Bay are a deep indigo. Dark waves lap the sandy shore in a mesmerizing rhythm, and a chilly seabreeze sends a shiver up your spine. Rumors claim that this Cove is home to a host of lost seafaring souls, sailors whose ships were destroyed by the merciless might of The Great Sea...

Contents:
ship(#252SeoK)
Obvious exits:
Shore  Sea

A combination of locks were used to keep people from traveling straight out into the sea. The @fail message for this exit describes the biting wind and stinging spray. Although there are a few clues lying around on the shore, the objective is for players to get out to sea.

enter ship
ship(#252SeoK)

The ship is stocked and ready to sail, despite the fact that no crew can be found. The hull is old and the sails slightly torn, but she seems seaworthy enough. Care to set sail?

Obvious exits:
bay  climb mast

Typing climb mast leads you to the crowsnest, where you can see the entire surrounding area (and perhaps discern another clue); it also allows you to jump straight into the cold waters of Blackmoor Bay, just for fun. The desire was to structure this adventure so that one party could come along fairly soon after the previous one, so the ship had to stay here. If you examine the code, you see that that's exactly what it does. The @va register waits to hear the magic words "set sail" to issue you the exit name:

ex here
ship(#252SeoK)

This dilapidated old vessel looks like she's weathered a few storms, but she's rigged and ready to sail. You see no movement onboard. Dare you enter?

Owner: Speedy  Credits: 1
Type: Thing      Flags: sticky enter_ok opaque key
Zone: Universal Zone
Created: never
Modified: never
Idesc:The ship is stocked and ready to sail, despite the fact that no crew can be found. The hull is old and the sails slightly torn, but she seems seaworthy enough. Care to set sail?
Va:$set sail:@PEmit %N=You take the helm, piloting the ancient vessel northward to the mouth of the Bay. The Sea looks especially rough for this time of year... What's your call - `sea' or `bay'?
Contents:
Speedy(#5Pevcn)
Home: Blackmoor Bay(#248Rpv)
Location: Blackmoor Bay(#248Rpv)
Exits:
bay(#372Ev)
sea(#371EDv)
climb mast;up;climb(#251Ev)

First we head out to sea...

sea
You boldly set forth into the fierce and mysterious Sea...
The Great Sea(#250RvJ)

You head out into The Great Sea, fierce winds blowing in your hair, salty spray hitting your face... you begin to fear for your safety as the sky darkens and the waves grow higher... you have no idea which direction you're facing anymore...

Obvious exits:
<I>sland  <B>ay

After a second or two, we see...

You fear a storm is approaching...

And after another second or two...

The sky begins to draw dark as the clouds above gather in disturbing thickness...

The pressure's really getting to you by now, isn't it? Well, the clue in the crowsnest is a scrawled note reading "Ye better pray, matey." And, in true literal fashion, players who type anything beginning with p-r-a-y will be rewarded by the following line of code (from register @va of The Great Sea):

Va:$pray*:@PEmit %N=Your prayers have been answered, %N. The sky begins brightening as the clouds part, and a lovely rainbow arches overhead. You see a single white dove heading toward an island that wasn't there a minute ago... ;@tr me/vb

All in all, it really hasn't taken very much work—two rooms and two things—to get the players fairly immersed in the adventure. They've experienced a little thrill and a small miracle, and feel as though they're far from "home." At this point, we could allow players a chance to move on through other exits and travel to other realms. By linking exits to the rooms of fellow MUSErs, the Sea becomes Great indeed. Once the players commit to debarking upon the island, however, the narrative picks up in full swing:

island
River Mouth(#373R)

The river is narrow, the water dark, and the smell is horrid. You push aside some of the hanging vines that obscure your view, and peer ahead. Overhead, several carrion-birds circle slowly, patiently waiting...

Obvious exits:
<S>wamp  <J>ungle  Sea

One easy way to create the feeling of "life" in environments like these is by using @wait commands in the @adesc line, like this:

Adesc:@Wait 5=@Emit A mutant rodent on the north bank is startled by your passage. It freezes, limbs locked, staring at you.;@Wait 15=@Emit A slimy tentacle suddenly erupts from the water. It grasps the small mammal, which quickly sinks its teeth into the attacker's squishy flesh. Thus released, the little rat-thing scampers away into the underbrush, and the tentacle retreats silently into the brackish water.

You can also make use of the rand() function to vary the local wildlife a little bit. After picking up a machete from the swamp to the north (you'll understand why in a moment), we'll move south into the jungle:

Jungle(#376R)

The vegetation is immense and unusual, and the sounds you hear around you are like no animals you can identify. You feel as though you are being watched by some lurking malevolence...

Obvious exits:
<E>ast  <N>orth

After a few seconds, we see...

The jungle is getting too thick to push your way through... Branches tear your clothes and scratch your face... You have to stop and rest for a minute...

Now there are two moves players can make. The first is to use the machete we got from the swamp (note that if the player came here first, this area would seem pretty useless, causing them to go across the river to the swamp room, where they'd find the machete). Used here, the machete will hack a way through the trees for us. But there's another clue hidden in the words above; let's see what happens if we type rest:

rest

You settle back against a tree and catch your breath. This jungle-cutting is no easy feat! The smooth curve of the trunk behind you feels comfortable, and you close your eyes, drifting into a much-deserved slumber.

...
You dream of a better life...
...
One with much less excitement and regular paychecks...
...
Dream on...

You are awakened by a deafening roar from the east. What could you have been thinking? You scramble to your feet and scan the surrounding area, looking for anything you'd hope not to see...

Scary!  But if the player waits just a little while longer, they'll be rewarded again:
The roar is not repeated, and you cannot pinpoint its
source, but there's a tall tree nearby with a man's jacket stuck in the highest branches.
Huh -- what's this?  Only one way to find out:
climb tree

You pull yourself to the top of the tall tree, trying not to look down too often. At last you reach a point where you can climb no further.

Top of Tall Tree(#379R)

You are hanging in a precarious position from the top of one of the tallest trees on the island. From here you can see your ship and most of the river valley. You notice that many of the ancient trees are bent or broken at odd

angles...
Contents:
Jacket(#382S)
Obvious exits:
down

Where's that jacket?

look jacket

This khaki jacket has been shredded by some amazingly powerful attacker. It's covered with dark brown stains, and seems to have something in the left pocket...

take jacket

You can't pull the jacket loose from the branches, but you manage to reach into the pocket... It feels like a small notebook...

take notebook

You grab the notebook quickly, and a few pages scatter to the wind.

read notebook
Small Notebook(#383SD)

It's the battered journal of an adventurer named (something illegible) Westcott. Most of the pages are either missing or too badly damaged by the elements to read, but the last entry is fairly clear. "Most of my crew have deserted me," writes Westcott, "and I cannot say I blame them, for it is true what they say of this island—it is inhabited, nay, RULED, by a gigantic reptilian creature. I have therefore decided to name this place Monster Island."

You get the picture. We'll leave off right there, just to keep you wondering.

MUCK, MUSH and MUSE Reference

This section provides a detailed reference to MUCKs, MUSHes, and MUSEs. It lists at-commands, common functions, flags, and other mud commands and structures.

Concept Reference

As an aid for your memory, this section summarizes some basic mud concepts.

Control

In general, you can examine, modify, or use any object you control, and you control only the objects you own (unless you're a Wizard or an Official). The single exception to this rule is an unlinked exit; anyone can link to it, causing the exit to be @chown'ed to them, and effectively stealing the exit from its original owner. Builders should be aware of this.

Costs

Certain commands cost credits to perform.

Command

Cost

page

1 credit each

@dig

1 credit each

@link

1 credit if you did not own the exit, plus 1 to the previous owner

@open

1 credit, plus 1 more if the exit is linked at the same time

@create

10 credits or more (up to 505 credits)

@wait

10 credits each

@find

10 credits each

@search

10 credits each

@announce

250 credits.

@trigger

Anywhere from 1/64th to 1/16 of a credit

@force

Anywhere from 1/64th to 1/16 of a credit

Certain commands demand deposits, which are refunded when the object is destroyed.

Credits

In the enlightened words of Moulton (Barry Kort), "Credits are really chits for CPU cycles." In other words, don't take anything about them too personally—they're not even really fake money. You receive an allowance of credits every day you connect with the mud. You may also borrow money, or sell the objects you create.

Drop-To

When an @link is used on a room, it also creates a drop-to location. From then on, any object dropped in the room will go to that location (unless the room is STICKY). If the room is STICKY, the drop-to will be delayed until the last person has left.

Enactor

For any action that occurs, the enactor is the object that causes a given action to occur. If an object initiates an action by an @force or @trigger, it is the enactor of the specified action. If one of your objects initiates an action by an @asucc, @afail, or @aenter, you are the enactor; the action will occur just as if you had typed it yourself. Interactive Design Note: When an action begins running, the name of its enactor is plugged into the %N and %n variables.

$ and ! Events

These extremely useful events enable you to define new verbs and "automatic" commands. Stored in any register of any class of object, they wait until their specific text pattern comes along, and then they execute their listed actions.

$ events wait until their pattern is matched by any typed command (by any player in the room):

$pattern:action1[;action2][;...]

! events are similar, except that they listen for "spoken" words instead of typed commands:

!pattern:action1[;action2][;...]

In either case, the pattern may include wild cards. If it does have wild cards, the strings matching them is plugged in as temporary variables, and may be referenced in the action part of the command. The first such variable will be called %0 or v(0), the second %1 or v(1), and so forth.

Exits

Exits are created by the @open command, but they will only be automatically linked to a given room if this is specified. If unspecified (or if the exit is created from within another type of object), you must then use an @link command to link the exit to where it goes. If you ever find yourself in a place with no obvious exits, you may be inside a thing. The leave command will get you out.

Failure

Failure has different meanings in different contexts. You fail to use a thing when you cannot take it (due to locks, for instance). You fail to use an exit when you cannot go through it. You fail to use a room when you cannot look at it.

Home

To teleport instantly to your home, type home at any time. To set a new one, use the @link command (the target room must either be yours or have its LINK_OK flag set). All players and things have homes; this is the place where STICKY objects go when you drop them. For things, the default home is the room in which they were created. To @link an exit that sends players back to their own homes:

> @link exit-name=home

Linking

You can only @link to rooms you control, and rooms that are set LINK_OK. An @link performed on a thing sets the object's home.

me

You can use the term me to refer to your character.

Names

To have an object refer to a players' name, use the variable %N in your command statement. If, for some strange reason, you wish not to capitalize the name, use %n instead.

NULL Exits: Bogus Commands

It's easy to come up with "bogus commands" by creating unusable exits. Here's an example that seemingly grants the power of flight:

> @open fly
> @link fly=here
> @lock fly=me&!me
> @fail fly=You suddenly rise, flying high above the ground!
> @ofail fly=rises up overhead, flying through the air!

The exit was linked so that no one could steal it, and locked so that no one could successfully use it (since it's impossible to be both "me" and not "me"). Since nobody can go through this "exit," it always fails. The @fail message is displayed to the player, and the @ofail message (preceded by the player's name) is shown to everyone else.

Numbers

All objects in the mud are known by a database reference number, called a DBREF for short. The DBREF of any object you own shows up whenever you look at the object; others do not see it. To have an object refer to the DBREF of another object, use the variable %# in your command statement.

Objects

There are only four types of objects in muds: rooms, exits, things, and players.

The first letter following an object's ID number indicates its type (R, E, T, or P). Rooms are objects that can contain other objects and linked exits. Exits are the means by which objects move between rooms and things. Things are inanimate objects that can be carried. Players are animate objects that can move and carry (contain) other objects.

Pronouns

Mud objects can be made to refer directly to players, by pronoun as well as by name. This is one of the areas where normal English grammar becomes a little tricky to program, so a number of special variables has been set aside as pronoun-substitution characters. There are five "sexes" available in most mud worlds: male, female, neuter, plural, and "spivak" (a genderless system that lops off S's and H's). Objects without sex of any kind will have their names used instead of pronouns; but this makes for inelegant narrative. For instance: "Speedy shines the apple on Speedy's chest and bites into it with a gleam in Speedy's eye." Bleagh. The results of the shown variables for all five sexes are as follows:

Variable

Type

Example

%S, %s

Subjective pronoun

he, she, it, they, e

%O, %o

Objective pronoun

him, her, it, them, em

%P, %p

Possessive pronoun

his, her, its, their, eir

%A, %a

Absolute possessive pronoun

his, hers, its, theirs, eirs

Stack

The stack for any object consists of the contents of the numbered stack variables: v(0) through v(9). You can set these contents in various ways; they may be edited directly, entered as actions in an @trigger command, or replaced by wild card substitutions.

In MUCK, the stack is the an actual stack of things. You create MUF programs that manipulate the stack.

Substitutions

Several types of % variables (variable substitution characters) have already been discussed (see "Names," "Numbers," and "Pronouns"). There are a few others reserved for use, which make programming quite a bit easier. The values of an object's V-registers may be accessed by the variables %va through %vz.

Success

Success has different meanings in different contexts. You succeed in using a thing when you take it. You succeed in using an exit when you go through it. You succeed in using a room when you look around.

V-Registers

V-registers are the main means of programming objects. Each object has 10 numbered stack variables, v(0) through v(9), and 26 V-registers, named v(va) through v(vz). Each V-register can hold a number, a character string, or an executable command.

Verb Commands

Most verb commands come in three forms:

verb (what the enactor sees)

overb (what others in the room see)

averb (the action triggered when the verb event happens)

Tips For Programmers

You can easily spend a few years using the commands given in the last section, and create thousands of masterpieces of textual art (and many have done just that!). There are, however, a good number of advanced features that prove invaluable when it comes to fine-tuning the behavior of your mud objects, both as individual units and—even better—as interconnected parts of an interactive environment. This section provides a reference for many of those features and functions.

Your first interactive environment may consist of nothing more than one densely coded room full of chatty objects, or you may choose to bite off a dozen connected rooms. In either case, you still have a little way to go.

When you create a room and place a couple of objects in it, you tend to begin developing a theme of sorts. This theme may be as loose as "fantasy," or as tightly focused as "a rowdy roadside bar located in a traveling tent, sometime during the early seventies." Follow these thematic threads and pick out the most important items, places, and characters. As you continue creating these initial elements of your environment, certain objects will, by their very nature, imply others. Be careful—these other objects will imply others beyond them, and the process may begin to exponentiate beyond reckoning (resulting in nothing but a bad case of programmer's shock!). If you don't develop things a little at a time, you're bound to get trampled under your own ideas. This can lead to hastily constructed mud environments that are of poor quality.

So as not to draw the ire of the wizards, you might stick to a small series of related rooms at first, adding objects and attributes a little bit at a time. Having kept a list of related objects and ideas, begin adding one or two objects at a time into your area. After creating and describing these new objects, go around your entire area again and add a level of detail.

Here are some guidelines to help:

  1. Limit yourself to a certain number of initial objects, say 10 or 12.

  2. @create them and @desc them, and @link your exits.

  3. Add @ofails, @adescs, and such to enhance the narrative.

  4. Jot down any other ideas you have on a nearby piece of paper.

  5. Think about how these objects might interact with players, and with each other.

  6. Take a break! Then add more to your creation in an iterative fashion.

It is also important to remember that all your objects take up space in the database, so be considerate and thoughtful when you create new areas and objects. Avoid creating low quality objects that just clutter up the database. Strive for interesting rooms and innovative objects that mesh with the theme and tone of the mud.

At-Commands Reference

In this section, the term action is frequently used. Any basic command or at-command may be used as an action. These actions occur sequentially if separated by semicolons. For example:

> @wait 5=say Hi!;@Emit %N sounds funny.;say Do you think I sound funny?

will wait for 5 seconds and then display:

Speedy says "Hi!"
Speedy sounds funny.
Speedy says "Do you think I sound funny?"

Note that you may have to enclose your action list in braces if your messages contain commas or semicolons.

At-Commands

Some commands in this section are only available on certain types of muds. These commands are listed as such. Certain commands may also only be available to wizards or MUSE officials, and they are likewise denoted.

@aahear object=actions

At All Hear. Sets the actions triggered when the @listen string is matched by a pose or utterance from the object itself or from a player.

MUSH and MUSE only.

@aclone object=actions

Sets the actions triggered by the newly cloned copy when the object is cloned.

MUSH and MUSE only.

@aconnect object=actions

Sets the actions triggered when someone connects into the mud. On a room or object in the room, it's triggered by connection within the room.

MUSH and MUSE only.

@addparent object=parent

Gives the object a new parent. The parent must be controlled by you or be set BEARING. The object inherits attribute definitions from its parents. It also inherits attribute values, if the attributes in question have the INHERIT option set.

MUSE only.

@adesc object=actions

Sets the actions triggered when the object is looked at.

MUSH and MUSE only.

@adisconnect object=actions

Sets the actions triggered when someone disconnects from the mud. On a room or an object in the room, it's triggered by a disconnection within the room.

MUSH and MUSE only.

@adrop object=actions

Sets the actions triggered when the object is dropped.

MUSH and MUSE only.

@aefail room|object|player=actions

Sets the actions triggered when someone fails to enter the room, object, or player.

MUSH and MUSE only.

@aenter room|object|player=actions

Sets the actions triggered when the room, object, or player is entered.

MUSH and MUSE only.

@afail object=actions

Sets the actions triggered when an attempt to use the object fails.

MUSH and MUSE only.

@ahear object=actions

Sets the actions triggered when the object's @listen string is matched.

MUSH and MUSE only.

@aleave room|object=actions

Sets the actions triggered when a player or other object leaves the specified room or object.

MUSH and MUSE only.

@alfail room|object=actions

Sets the actions triggered when someone fails an attempt to leave the room or object.

MUSH and MUSE only.

@alias player=alias

Sets the alias by which to reference the player.

MUSH and MUSE only.

@allquota number

Sets the builder's quota for all players to the number entered. Individual players can check their own quotas with the @quota command (see @quota later in this section).

Wizards and Officials only.

MUSE only.

@amhear object=actions

Sets the actions triggered when the object's @listen string is matched by a pose or utterance from the object itself.

MUSH and MUSE only.

@amove object[=message]

Sets the message emitted if the object moves by any means.

MUSH and MUSE only.

@announce message

Broadcasts the specified message to every player connected. Costs 250 credits. Players can block out announcements by setting themselves NO_WALLS. Abbr.: @ann.

MUSE only.

@apage player=actions

Sets the actions triggered when you are on-line and receive a page.

MUSE only.

@apay object=actions

Sets the actions triggered when someone or something gives credits to the object.

MUSH and MUSE only.

@apemit object=actions

Sets the actions triggered when the object gets an @pemit.

MUSH and MUSE only.

@asfail room=actions

Sets the actions triggered when someone fails to use an @slock.

MUSE only.

@asucc object=actions

Sets the actions triggered when the object is successfully used.

MUSH and MUSE only.

@aufail object=actions

Sets the actions triggered when someone fails to use the object due to @ulock.

MUSH and MUSE only.

@awhisper object=actions

Sets the actions triggered when the object receives a whisper.

MUSH and MUSE only.

@broadcast message

Broadcasts the given message throughout the mud. Nonblockable.

MUSE only.

Wizards and Officials Only.

@boot player
Disconnects the player from the game.
Available on MUCK, MUSH and MUSE.

Wizards and Officials Only.

@charges object=#charges

Limits the number of times an action can be used.

MUSH and MUSE only.

@chown object=player

Changes the ownership of the object to the specified player, turns on the object's HAVEN flag, and turns off the object's INHERIT flag.

Available on MUCK, MUSH and MUSE.

@chownall player1=player2

Transfers the ownership of all of player1's possessions to player2.

MUSH and MUSE only.

Wizards and Officials Only.

@clone object

Creates a duplicate of the object in the current room.

MUSH and MUSE only.

@columns #columns

Sets the number of columns that WHO prints. The default is 80.

MUSE only.

@cost object=#credits

Sets the number of credits that must be given to the object to trigger @pay, @opay, and @apay.

MUSH and MUSE only.

@cpattr new-object/new-attribute=old-object/old-attribute

Copies an attribute definition from the old object to the new object. The names of the two attributes used need not be the same.

MUSE only.

@create object-name[=#credits]

Creates a new object whose name is the specified object-name. The command costs #credits or 10 credits, whichever is greater. The object's "actual" value will become (#credits / 5) - 1.

Available on MUCK, MUSH, and MUSE.

@dbck

Shows any disconnected rooms and clears the free list.

MUSE only.

@dbtop item

Shows the top list for the specified item in the database. Do @dbtop (without an argument) to see what objects are available to list.

MUSE only.

@decompile

Outputs a series of commands that can be fed back into the mud to redefine and reset all of an objects' registers and flags. This command can be used to save an object to disk, edit it, and read it back in via the TinyFugue /quote macro. When using @decompile for this purpose, be sure to set /wrap off in TinyFugue so that lines are not broken every 80 characters. @decompile displays several commands, including @set (to set flags), @defattr (to define attributes), and @nset (to set attribute values).

MUSH and MUSE only.

@defattr object/attribute[=option1 option2 ...]

Creates or modifies a user-defined attribute on the object. Any options specified will dictate the behavior of the attribute. The new attribute may be set by typing: @set object=attribute:value, or with the usual shorthand: @attribute object=value.For example, @defattr Book/title=osee defines an attribute called title which anyone can see upon doing an examine command (this is the meaning of osee--see @osee), and @title Book=Muse Tutorial places the words Muse Tutorial there. Now the function [get(book/title)] returns Muse Tutorial.

MUSE only.

@delparent object=parent

Removes the parent from the object. The parent must be controlled by you, or set BEARING.

MUSE only.

@describe object[=text]

Sets the text seen when the object is looked at. Abbr.: @desc.

Available on MUCK, MUSH, and MUSE.

@destroy object

Sets the object "non-protected" and returns the creator's investment. This command may be aborted by an @undestroy within 10-15 minutes.

MUSH and MUSE only.

@dig room-name[;alternate-names][=exits[,return-exits]]

Creates a room, giving it the specified room name. The optional portions allow alternate names and auto-linked exits.

Available on MUCK, MUSH, and MUSE.

@does object=actions

Like a v-register, but removes 1 charge from the object when triggered.

MUSE only.

@doing message

Sets the player's @doing message, which is displayed in the WHO list.

MUSH and MUSE only.

@doomsday

Set by @destroy, @undestroy, @protect, and @unprotect, doomsday is a number in xtime() format, specifying the system time before which an object should not be destroyed. Objects with the GOING flag set will be destroyed during the first @dbck after the time given.

MUSE only.

Only Officials may set the doomsday attribute directly.

@drop object[=message]

Sets the message seen when someone drops the object. If entered without a message, it clears any existing message.

Available on MUCK, MUSH, and MUSE.

@dump

Dumps the database for storage (vital to the continued survival of the mud).

Available on MUCK, MUSH, and MUSE.

@edit object/attribute={old-string},{new-string}

Replaces the first occurrence of the old-string by the new-string. The attribute can be any attribute on the object that holds a string value (for example, @desc, @succ, @adrop, @listen, @ahear, @va, @vb, and so forth). If the strings contain only alphabetic characters, the curly braces may be omitted.

Available on MUCK, MUSH, and MUSE.

@efail object=actions

Sets the message shown to a player who fails to enter the object.

MUSH and MUSE only.

@elock object=lock

Sets the enter lock for the object. Only players or things satisfying the lock may then enter the object.

MUSE only.

@emit message

Emits the message to everything in the room. The message can't start with a player's name (in order to prevent spoofing).

MUSH and MUSE only.

@enter object[=message]

Sets the message seen when a player enters the object.

MUSH and MUSE only.

@entrances room|object

Lists all the entrances into the room or object. You must control the room or object.

Available on MUCK, MUSH, and MUSE.

@fail object[=message]

Sets the message seen when an attempt to use the object fails. If entered without a message, it clears any existing message.

Available on MUCK, MUSH, and MUSE.

@find [name]

Displays the name and number of every object you control whose name matches the specified name. Costs 10 credits.

Available on MUCK, MUSH, and MUSE.

@force player|object=actions

Forces the specified player or object to perform the actions, as though the player or object entered the actions itself. Objects you own can @force you if set INHERIT.

Available on MUCK, MUSH, and MUSE.

Only Wizards or Officials may @force players.

@foreach list=actions

Executes the actions (which may be a semicolon-separated list of commands) once for each item in the list (whose elements are separated by spaces). If a %0 occurs in the actions, @foreach substitutes each element of the list, in order, for the %0. Since the %0 is evaluated each time the command passes through the command queue, you will need several %'s if the %0 is embedded in function calls.

MUSE only.

@getalias player

Tells you the player's alias, if any.

MUSE only.

@giveto player=#credits

Privately gives an amount of money to the player.

MUSE only.

@halt object

Stops a process or a runaway machine. To stop one particular object, type: @force object=@halt.

MUSH and MUSE only.

@hide

Removes you from the WHO list this session. Costs 10 credits.

MUSE only.

@huhto player[=E-Mail-Address]

Initiates or terminates the automatic logging of failed commands attempted by players in rooms owned by player. The log is periodically mailed to the specified E-Mail-Address. The use of HuhLogs enables a Builder to improve the choice of exit-names and trigger verbs in the Builder's realm, in order to better respond to commands most frequently attempted by visitors.

MUSE only.

Wizards and Officials only.

@idescribe object=message

Sets the message seen when the object is entered or looked at from the inside.

Available on MUCK, MUSH, and MUSE.

@leave object[=message]

Sets the message shown to a player upon leaving the object.

MUSH and MUSE only.

@lfail object[=message]

Sets the message shown to a player who fails to leave the object.

MUSH and MUSE only.

@link object=room

For things and players, makes the specified room Home. For rooms, makes the specified room the drop-to room. For exits, makes the specified room the exit's target room (the exit must be unlinked and in your control, or LINK_OK). Costs 1 credit.

Available on MUCK, MUSH, and MUSE.

@listen object=string

Listens for the given string to trigger @ahear, @amhear, and/or @aahear. If the string is matched, the object's contents also hear the message.

MUSH and MUSE only.

@llock object=lock

Sets the leave lock for the object. Only players or things satisfying the lock will be able to leave the object.

MUSE only.

@lock object=lock

Sets the lock on the object. Only players or things satisfying the lock will be able to "succeed" with object (i.e., pick up a thing, go through an exit, trigger @succ, @osucc, @asucc registers, and so forth).

Available on MUCK, MUSH, and MUSE.

@move object[=message]

Sets the message shown to the object itself when it moves by any means.

MUSH and MUSE only.

@name object=new-name [password]

Changes the object's name. For a player, it requires the player's password.

Available on MUCK, MUSH, and MUSE.

@necho message

Shows a message to you only, but also allows n-phrasing, so you can type multiple spaces and other characters that don't normally come out with @echo. If this command is used in an attribute, it still must be @nset.

MUSE only.

@nemit message

Emits the given message, but does not parse its argument. This can be useful for emitting strings with spaces, brackets, or parentheses in them, without worrying about functions being evaluated or spaces being removed.

MUSE only.

@newpassword player=password

Changes the player's password. The player is informed of the change. If you forget your password, log on as a guest and talk to a Wizard or an Official.

Available on MUCK, MUSH, and MUSE.

Wizards or Officials only.

@npage player=message

Pages the player without parsing the message.

MUSE only.

@npemit object=message

Emits the specified message to the player, but does not parse its argument. Useful for emitting strings with spaces, brackets, or parentheses in them, without worrying about functions being evaluated or spaces being removed.

MUSE only.

@nset object=attribute:actions

Sets the attribute to the given actions, but does not parse its argument. May be used for setting attribute values with leading or embedded spaces, or with brackets or parentheses, without worrying about functions being evaluated or spaces being removed.

MUSE only.

@nuke player

Recycles the player's character, after which it no longer exists.

MUSE only.

Wizards and Officials only.

@oconnect object=message

Sets the message shown to everyone but the specified object, when a person connects to the mud.

MUSE only.

@odescribe object[=message]

Sets the message that is seen by the other players in the room when a player looks at the specified object. The message is prefaced by the name of the triggering player. Without a message, the command clears any existing message. Abbr.: @odesc.

MUSH and MUSE only.

@odisconnect object=message

Sets the message shown to everyone but the specified object when a person disconnects from the mud.

MUSE only.

@odrop object[=message]

Sets the message that is seen by the other players in the room when a player drops the specified object. The message is prefaced by the name of the triggering player. If the object is a room, this sets the message that is displayed to other people when someone enters the room. Without a message, it clears any existing message.

MUSH and MUSE only.

@oefail object[=message]

Sets the message shown to the other players in the room if a player fails to enter the specified object.

MUSH and MUSE only.

@oemit object=message

Sets the message to be emitted to everything in the room except the object itself.

MUSH and MUSE only.

@oenter object[=message]

Sets the message that is seen by the other players in the room when a player enters the specified object. The message is prefaced by the name of the triggering player. Without a message, it clears any existing message.

MUSH and MUSE only.

@ofail object [=message]

Sets the message that is seen by the other players in the room when a player fails an attempt to use the specified object. The message is prefaced by the name of the triggering player. Without a message, it clears any existing message.

Available on MUCK, MUSH, and MUSE.

@oleave object[=message]

Sets the message that is seen by the other players in the room when a player leaves the specified object. The message is prefaced by the name of the triggering player. Without a message, it clears any existing message.

MUSH and MUSE only.

@olfail object[=message]

Sets the message that is seen by the other players in the room when a player fails to leave the specified object. The message is prefaced by the name of the triggering player. Without a message, it clears any existing message.

MUSH and MUSE only.

@omove object[=message]

Sets the message seen by all other objects in the room when the specified object moves by any means.

MUSH and MUSE only.

@opay object[=message]

Sets the message that is seen by the other players in the room when a player or thing pays the specified object. The message is prefaced by the name of the triggering player. Without a message, it clears any existing message.

MUSH and MUSE only.

@open direction[;other-directions] [=#room]

Creates an exit in the specified direction(s). If a room number is specified, the exit is linked to that room. Otherwise, the exit remains unlinked. Anyone may use @link to specify where an unlinked exit leads. Costs 1 credit, plus 1 credit more if the room number is also specified.

Available on MUCK, MUSH, and MUSE.

@osfail room=message

Sets the message shown to everyone in the room, except the enactor, when the enactor fails to use an @slock.

MUSE only.

@osuccess object[=message]

Sets the message that is seen by the other players in the room when a player or thing succeeds in using the specified object. The message is prefaced by the name of the triggering player. Without a message, it clears any existing message. Abbr.: @osucc.

Available on MUCK, MUSH, and MUSE.

@password old-password=new-password

Changes your password. Abbr.: @pass.

Available on MUCK, MUSH, and MUSE.

@pay object[=message]

Sets the message shown to the player who pays the specified object. Without a message, it clears any existing message.

MUSH and MUSE only.

@pbreak

Shows list of players, broken down into classes.

MUSE only.

Wizards and Officials only.

@pemit player=message

Emits the message to a specified player. The message may not start with the name of a player or of an object in the room.

MUSH and MUSE only.

@poof object

Teleports the object into itself and then destroys it (if possible). The object disappears from the scene immediately, though it is not actually destroyed for several more minutes.

MUSE only.

@poor

Resets all players' credits to 0.

MUSE only.

Wizards and Officials only.

@powers player|thing

Lists the authorized powers of the player or thing.

MUSE only.

@protect object

Sets the @doomsday attribute on the object to -1, in order to keep the object from being destroyed with @destroy.

MUSE only.

@ps

Lists the queued commands that have not yet been executed.

Available on MUCK, MUSH, and MUSE.

@quota

Displays your current builders' quota.

MUSH and MUSE only.

@quota *player=#quota-amount

Resets the player's builders' quota to the specified quota amount.

MUSH and MUSE only.

Wizards and Officials only.

@recycle object

Recycles the object, which saves space in the database. Remember your cyber-ecology!

Available on MUCK, MUSH, and MUSE.

@relink exit=#room

Relinks the exit to a different room number.

MUSE only.

@remit object=message

Emits the message to the contents of the object. The object is generally a room.

MUSE only.

@runout object=actions

Sets the actions triggered when the object's charges reach 0.

MUSH and MUSE only.

@rwho start|stop|status

Starts, stops and shows the status of the RWHO server. When stopped, the RWHO command will not operate.

MUSE only.

@search [player] [class=restrictions]

Searches the mud database and lists the objects that meet the player's search criteria. If the player argument is supplied, only objects owned by that player are listed. If the class argument is supplied, only objects of a certain class are listed. Costs 10 credits. The command @search flags=RHD lists all rooms (the R flag) set HAVEN and DARK (the R and H flags). The command @search type=rooms lists all rooms owned by the player.

MUSH and MUSE only.

@searchobj object=text

Searches an entire object and its attributes for the specified text. It then lists out each matching attribute. You may include wild card characters.

MUSE only.

@selfboot

Automatically performs an @boot on you three times, to clear up double logins into the mud. This means that you and your doubles (only) will be disconnected. Afterwards, you can reconnect to the mud.

MUSE only.

@set

Used to set attributes and flags on objects. May be used in various ways:

@set object=flag

Sets the specified flag on the object.

@set object=! flag

Resets the specified flag on the object.

@set object=attribute:value

Sets an attribute value on the object.

@set object=! attribute:value

Resets an attribute value on the object.

@attribute object=value

Short form of: @set object attribute:value.

@new-attribute new-object=old-object/old-attribute

Copies an attribute from one object to another object.

Available on MUCK, MUSH, and MUSE.

@sex player=gender

Sets the gender of the player. The player's gender is used for pronoun substitution. Options: unassigned, male, female, neuter, spivak, plural. The default is unassigned. Pronouns cannot be used in reference to players unless their gender is set to one of these choices. Visible to all.

MUSH and MUSE only.

@sfail room=message

Sets the message shown only to the player who fails to use the @slock. The player's name is not prefixed to the message.

MUSE only.

@shutdown

Shuts down the mud.

Available on MUCK, MUSH, and MUSE.

Wizards and Officials only.

@slock room=arguments

Speech lock. Sets the speech lock on the room, where only the players specified in the arguments may speak in the room. The owner may talk in the room, and those with the power to spoof, even if they are not on the list. This command only affects rooms. The room that the @slock is on must be set AUDITORIUM: @set room=A.

MUSE only.

@startup object=actions

Sets the actions to be performed in the event that the mud crashes and gets rebooted. By using @startup, you can retrigger objects that need to be running continuously.

MUSH and MUSE only.

@stats [player]

Displays all the objects in the game broken down by types.

Available on MUCK, MUSH, and MUSE.

Officials can supply a player name to count only objects owned by that player.

@success object[=message]

Sets the success message for the specified object, which is displayed to the player whenever a player successfully uses the object. Without a message, it clears any existing message. Abbr.: @succ.

Available on MUCK, MUSH, and MUSE.

@sweep

Lists all the objects and players that are listening in the room you are currently in, as well as in the objects you are carrying. In these listings, player denotes a connected player that hears all occurrences in the room, puppet denotes a puppet belonging to a connected player, relaying all occurrences in the room to the owner, messages denotes an object that is listening for specific occurrences in the room, and commands denotes an object waiting for a specific command.

MUSH and MUSE only.

@switch

Evaluates a conditional expression and performs different actions based on the results of that evaluation. May be used in two ways:

@switch condition={pattern1},{yes-actions},{no-actions}

Corresponds to the IF-THEN-ELSE programming structure.

@switch condition={pattern1},{yes-actions1},{pattern2},{yes-actions2},...,{default-actions}

Corresponds to the CASE or SWITCH programming structure.

MUSH and MUSE only.

@teleport thing=#room
@teleport #room

Teleports the given thing to the specified room. If the thing is omitted, the command teleports you to the specified room. You must own or control the thing or its current location. You can only teleport objects into rooms or objects you own or that are set JUMP_OK. If the target room has a drop-to, the object will go to the drop-to room instead. Abbr.: @tel.

Available on MUCK, MUSH, and MUSE.

Officials can teleport objects into players' inventories.

@trigger

Passes control and data (on the stack) between items. If you create attributes that are triggered by other commands or actions, this command can be used to trigger them. Many tricky things can be done with simple command combinations. Abbr.: @tr.

MUSH and MUSE only.

@tz player|object=#hours:y|n

Sets a player's time zone. The #hours is a numerical value representing the number of hours the player's time is ahead of or behind Greenwich Mean Time (GMT) (also referred to as Universal Coordinated Time (UTC), or London Time). The y or n refers to whether or not U.S. style Daylight Savings Time is used in your area. Objects that do not have a @tz set on them will use their owner's @tz. However, a player may set the @tz register on any object individually. If neither the object nor the object's owner has a @tz set, the mud will default to the local time at the mud's server site.

MUSE only.

@ufail object=actions

Sets the message shown to a player who fails to use an object due to an @ulock.

MUSH and MUSE only.

@ulock object=lock

Sets the Use Lock for the object. Only players or things satisfying the lock will be able to trigger $ and ! events on the object.

MUSE only.

@undefattr object/attribute

Removes the specified attribute definition from the object, if it was set with @defattr. If object has children with the attribute, they lose the definition and any stored values, so use this command with great caution.

MUSE only.

@undestroy object

Aborts an @destroy process on the object if entered within 5-10 minutes of the original @destroy command.

MUSE only.

@unhide

Restores your name in the WHO list. Players are reset to @unhide each time they connect.

MUSE only.

@unprotect object

Removes the @doomsday attribute on the object, allowing it to be @destroyed.

MUSE only.

@unlink exit
@unlink here

Removes links from exits. The first version shown removes a link from the specified exit. The second removes the drop-to on the room. Be careful, though; anyone can relink an unlinked exit, thereby becoming its new owner (you will, however, be reimbursed for your 1 credit).

MUSH and MUSE only.

@unlock object

Removes the lock on the object.

MUSH and MUSE only.

@va object=actions
@vb object=actions
     .
     .
     .
@vz object=actions

Sets the v-register on the object to the specified actions. Every object has 26 built-in registers, va through vz. Anything may be stored on a v-register. If a v-register contains a semicolon-separated list of actions (for example, @va object=action1;action2;action3), these actions will be executed in order when the register is triggered.

MUSH and MUSE only.

@wait #seconds=actions

Queues actions. The actions are placed on the queue and are executed no earlier than #seconds from the time it is queued. The actions may be a list of commands in curly braces.

MUSH and MUSE only.

@whereis player

Displays the location of the specified player. If you want to remain unlocatable, set yourself DARK. The located player receives a message informing him or her that you have successfully or unsuccessfully located them.

MUSE only.

@who_flags object=flags

Controls the output of WHO commands. Capital letters indicate "full" output; lowercase letters indicate "truncated" output:

A, a = Alias
C, c = Class
F, f = Flags (h: hidden, H: haven, N: set NO_WALLS)
I, i = IdleTime
N, n = Name
O, o = OnTime
H, h = Hostname.

The default is NfoiC.

MUSE only.

@who_names list-of-names

Restricts the WHO search and display to the specified names.

MUSE only.

@wipeout player

Destroys all the player's possessions.

MUSH and MUSE only.

Wizards and Officials only.

Flag Reference

In the mud, you can change the states, qualities, or abilities of other objects. Although many of these states can be mimicked at textual levels (by the creation of triggered text strings, for example), many are so far-reaching in importance that they have been removed to the level of flags. Flags may be thought of as switches on the object, which may be set in one direction or the other. The on position is indicated by the appearance of the flag's associated letter in the object's DBREF. The flag is off if the flag's letter doesn't appear.

All flags may be set and unset in the same way:

@set object=<flag>

Sets the flag.

@set object=!<flag> to reset (unset)

Resets, or unsets, the flag.

Flags

Abode
Flag:  A
@set here=ABODE

Allows players to set their homes to that location. Players can also set object's homes to that location.

MUCK only.

Bearing
Flag:  b
@set object=BEARING

Allows players to @addparent or @delparent their objects to or from the specified object. If not set, the specified object can neither bear new children nor lose old ones.

MUSE only.

Builder
Flag:  B

On some muds, only players that have this flag set are allowed to build anything.

Change Ownership Allowed
Flag:  C
@set object=CHOWN_OK

Allows players to transfer ownership of the specified object to another player. To set it, you must be carrying the object. To set this flag on a room or exit, you must be in the room. Once set, the new player may gain ownership of object by using @chown.

Available in MUCK, MUSH, and MUSE.

Connected
Flag:  c
@set player=CONNECTED

Shows whether player is connected or not. This flag only applies to players.

MUSH and MUSE only.

Dark
Flag:  D
@set object=DARK

Sets the object Dark. If a room is DARK, a look sees the room's description, but does not display the objects that the room contains. If a thing is DARK, look does not list that thing in the room's contents. Players who don't want to have their location found via @whereis may set themselves DARK. Puppets cannot be DARK, but an object set puppet and DARK enters "debug" mode, and relays to its owner everything it does and hears.

Available in MUCK, MUSH, and MUSE.

Destroyable
Flag:  d
@set object=DESTROY_OK

Allows any player to destroy the specified object as long as the object is not locked against them. This is good for creating things like notes, allowing the recipient to destroy the note after reading it, instead of having to look for you to destroy it.

MUSH and MUSE only.

Enterable
Flag:  e
@set object=ENTER_OK

Allows players to enter the specified object. Players must be ENTER_OK if they want to be able to receive things from other players via the give command.

MUSH and MUSE only.

Exit
Flag:  E

Available in MUCK, MUSH, and MUSE.

Floating
Flag:  f
@set room=FLOATING

When set on a disconnected room, this flag suppresses the disconnected room message. Should be used only by experienced builders because floating rooms can easily be forgotten or misplaced.

MUSH and MUSE only.

Going
Flag:  G
@set object=GOING

Used internally; automatically set on objects that are @destroyed. If you change your mind about @destroying an object, use @undestroy to unset it quickly!

MUSE only.

Haven
Flag:  H
@set object=HAVEN

Sets the object to be a haven. A haven player ignores all messages from other players. A haven object is halted, and its register commands is not triggered. If a room is a haven, you cannot kill in that room.

Available in MUCK, MUSH, and MUSE.

Hide
Flag:  h
@set object=HIDE

Used to mark players who do not want their names to show up on the WHO list. Set by @hide and reset by @unhide.

MUSE only.

Inherit
Flag:  I
@set object=INHERIT

Causes the object to inherit any special powers of its owner. Otherwise, the object has no special powers.

MUSE only.

Jump Allowed
Flag:  J
@set room=JUMP_OK

Allows players to @teleport into the room.

Available in MUCK, MUSH, and MUSE.

Key
Flag:  K
@set object=KEY

Sets the object to be a key. Puppets may not take the object, and the object returns to its home when its holder teleports away (except that the owner of the object can teleport with it).

Available in MUCK, MUSH, and MUSE.

Light
Flag:  l
@set object=LIGHT

Allows the object to be seen in a room that is set DARK.

MUSH and MUSE only.

Link Allowed
Flag:  L
@set object=LINK_OK

Allows anyone to link exits to the object (but not from it). Anyone can also set the object as their home.

Available in MUCK, MUSH, and MUSE.

Mucker
Flag:  M
@set object=MUCKER

When set on a player, it allows the player to create MUF programs in MUCK.

Available in MUCK.

Wizards only.

Opaque
Flag:  o
@set player=OPAQUE

Prevents other players from seeing what you are carrying in your inventory. Players can still see objects you are carrying that they own.

MUSE only.

Player
Flag:  P

Available in MUCK, MUSH, and MUSE.

Puppet
Flag:  p
@set object=puppet

Causes the object to grow eyes and ears; the object will relay all it sees and hears to its owner.

MUSH and MUSE only.

Quiet
Flag:  q
@set me=QUIET

Blocks out all the set and triggered messages that you get when your objects are set or triggered. This is useful if you have a lot of machines running continuously. It will also keep you from hearing shake and crumble and deposit back messages when you destroy objects.

MUSE only.

Room
Flag:  R
@set object=room

Identifies the object as a room; automatically set when you @dig the room. Once set, it cannot be changed.

Available in MUCK, MUSH, and MUSE.

Slave
Flag:  s
@set player=SLAVE

Disables the player from doing anything except to pose; player cannot talk, page, build, get, or drop objects.

MUSE only.

Officials only.

Sticky
Flag:  S
@set object=STICKY

Sets an object or room to be sticky. A thing that is sticky goes home when dropped. On room that is sticky, the drop-to is delayed until the last person leaves.

Available in MUCK, MUSH, and MUSE.

Terse
Flag:  t
@set object=TERSE

Sets an object or player to be terse. An object will not shake and crumble when destroyed. On a player, room descriptions won't be displayed when the player enters a new room (contents and exits are still displayed). This is good when you want to move about quickly, or don't want to read the room description. Beware: You might miss important information in some descriptions.

MUSH and MUSE only.

Transparent
Flag:  T
@set exit=TRANSPARENT

Allows players to look through the exit: they will first see the exit's description, followed by the description and contents of the room on the other side.

MUSE only.

Vehicle
Flag:  V
@set object=vehicle

Allows an object to contain players. Vehicles have certain restrictions placed on them, to prevent players from using vehicles to get around locks or go places they shouldn't.

Available in MUCK.

Visible
Flag:  v
@set object=VISIBLE

Allows any player to examine the object and see all the object's attributes as if they owned it. They cannot make any changes to object.

MUSE only.

Visual
Flag:  v
@set object=VISUAL

Allows any player to examine the object and see all the object's attributes as if they owned it. They cannot make any changes to object.

MUSH only.

Wizard
Flag:  W

Denotes a player that is a wizard. Wizards cannot be killed. They can use special wizard commands, and they are not subject to the same restrictions as normal players.

Available in MUCK, MUSH, and MUSE.

Zombie
Flag:  Z
@set object=zombie

Allows objects in MUCK to have the @force and the FORCE MUF primitive used on them.

Available in MUCK.

Attribute Options Reference

Mud objects have attributes, which are registers in which you can place text or commands. The basic and at-commands generally impact directly upon one or more of the built-in attributes, such as @succ, @osucc, @asucc, and so forth. The @defattr command can be used to create entirely new attributes.

But there is still another level of mud code we can explore! A broad set of functional modifiers known as attribute options may be applied to @defattr commands. These options allow you to change how your objects' attributes respond to their environments in subtle and far-reaching ways.

To create or modify a user-defined attribute and/or install an option, type:

@defattr object/attribute=attribute-option

Some of these attribute options are only available on MUSEs.

Attribute Options

Dark

A dark attribute is not visible in an examine command, and cannot be obtained by a get function.

Date

A date attribute stores date and time information, if the information is entered in xtime() format. Anyone who examines the object will see the correct date and time for their own timezone.

Function

A function attribute can create a user-defined function. You can enter any text or function into the attribute register, and it is executed whenever someone attempts to call the function (the function must first be defined on the object). For example, assume the object named testobj has already been created. You can define functions on it as follows:

> @defattr testobj/mult60=function inherit
Set.
> @mult60 blee=[mul(60,v(0))]
Set.
> say [mult60(3)]
180
> @defattr testobj/foo=function inherit
Set.
> @foo testobj=Everyone with [v(0)]: go to the [v(1)]!
Set.
> say [foo(coats,closet)]
You say "Everyone with coats: go to the closet!"
Inherit

An inherit attribute will pass its value down from parent to child. Child objects may have these values overwritten, but if these new values are erased, the original inherited value will appear again. This option is set on most of the built-in attributes.

Osee

An osee attribute can be seen by anyone who examines an object on which the attribute has a value, even if the object is not set to be visible. Attributes with a built-in osee option include last, sex, and race.

Unsaved

An unsaved attribute will not retain its contents when the mud is rebooted. The IT attribute carries the unsaved option.

Wizard

A wizard attribute can be @set only by the object's owner (or by a Wizard or Official). If you define an attribute with the wizard and inherit options, its child objects may be given to other players—even allowing other players to @chown them—and the new owners will not be able to change that attribute.

MUF Function Reference

This section describes the functions available for use in the MUF programming language (used on MUCKs). It is based on the MUF Reference Manual.

Notation

A special function notation is used to denote the values used on the stack, and any variables that are pushed back onto the stack. The notation

function(value1 value2 | result)

means that the given function first pops value2 from the top of the stack and then pops value1 from the stack. It then processes these values in some fashion and produces a result. This result is then pushed onto the stack. The value pushed onto the stack is denoted by the item following the vertical bar, if any. Usng this syntax, the addition function would be:

+ (integer1 integer2 | sum)

A function that does not put anything back onto the stack will not have anything after the vertical bar:

pop (val |)

Parameter Types

Throughout this section, the following terminology is used to indicate parameter types:

Terminology

Indicates

int

integer

str

string

dbref

DBREF

var

variable

boolean

either 0 or 1

value

any value

result

any value

MUF Functions

Arithmetic Functions

The following functions are available for arithmetic:

Function

Description

+ (int1 int2 | sum)

Adds int1 to int2

- (int1 int2 | difference)

Subtracts int2 from int1

* (int1 int2 | product)

Multiplies int1 by int2

/ (int1 int2 | integer-result)

Integer-divides int2 by int1

% (int1 int2 | remainder)

Modulo of int2 divided by int1

Comparison Functions

The following functions are available for comparison. They push a boolean result of either 0 or 1 back onto the stack.

Function

Description

< (int1 int2 | boolean)

Less than

<= (int1 int2 | boolean)

Less than or equal to

> (int1 int2 | boolean)

Greater than

>= (int1 int2 | boolean)

Greater than or equal to

= (int1 int2 | boolean)

Equal to

@ (var | value)

Accesses var and places its value onto the stack.

! (var value | )

Places the given value into the variable var.

addprop(item-dbref property-str property-value-str int| )

Sets the given property on the given item. The property is set to the given property value. If this string is null, the property is set to the given integer. All four parameters to this function must be on the stack (for example, you cannot omit certain ones).

and(value1 value2 | boolean)

Performs Boolean AND on value1 and value2 and pushes the Boolean result.

atoi(str | int)

Converts a string into an integer. If the string is not a number, 0 is pushed onto the stack.

call(program-name)

Starts executing a different MUF program. The program must have been compiled already. The called program inherits the value of me, loc, and trigger.

contents(container-dbref | first-item-dbref)

Pushes the DBREF of the first item contained in the container onto the stack. You could then use the next function to scan through the rest of the items in the container.

copyobj(original-dbref | copy-dbref)

Creates a copy of the original thing and pushes the copy's DBREF onto the stack.

dbcmp(dbref1 dbref2 | boolean)

Compares two DBREFs and pushes the Boolean result.

dbref(int | dbref)

Changes the integer into a DBREF. dbref(54) is the same as #54.

desc(item-dbref | desc-str)

Pushes the description attribute (@desc) of the item onto the stack.

drop(item-dbref | drop-str)

Pushes the drop attribute (@drop) of the item onto the stack.

dup(val | val val)

Duplicates the top of the stack.

exit

Exits from the MUF word being executed.

exit?(dbref | boolean)

Checks if the item is an exit object, and pushes the Boolean result.

exits(item-dbref | exit-dbref)

Pushes the DBREF of the first exit object in the exit list of the given item onto the stack. You could then use the next function to scan through the rest of the exits in the exit list.

explode(str1 str2 | str1 ... strN int)

Breaks str1 into individual strings, delimited by the delimiter in str2. The individual strings are pushed in reverse order onto the stack, and then an integer indicating the number of individual strings is pushed onto the stack. For example, if str1 was "This is a test" and str2 was a space character, " ", the stack would be "test" "a" "is" "This" 4, after this function. The null string, "", cannot be used as str2.

fail(item-dbref | fail-str)

Pushes the fail attribute (@fail) of the item onto the stack.

flag?(item-dbref str | boolean)

Uses the given string parameter as the name of a flag to check if the given flag is on or off for the item. Pushes 1 if it is on and 0 if it is off.

getlink(item-dbref | link-dbref)

Pushes whatever the item is linked to onto the stack. If the item is an exit, it pushes whatever the item is linked to. If the item is a player, it pushes the DBREF of the player's home. If the item is a room, it pushes the room's drop-to, if any. If the item is not linked to anything, #-1 is pushed.

getpropstr(item-dbref prop-name-str | prop-str)

Looks up the property named prop-name-str in the item, and pushes the string corresponding to that property. Pushes the null string if the property does not have a value.

getpropval(item-dbref prop-name-str | prop-int)

Looks up the property named prop-name-str in the item, and pushes the integer corresponding to that property. Pushes 0 if the property does not have a value.

if (boolean) statements [ else statements ] then

Tests the Boolean value. If the value is true, the statements after the if, up until the next then (or the next else, if the else is present), are executed. If the value is false, the statements between the else and next are executed. Execution then resumes after the word then. The if statement pops the Boolean value from the stack. As a helpful hint, it may be better to think of the then keyword as an endif.

instr(source-str pattern-str | index-int)

Searches for the pattern string in the source string. Pushes the index of the first occurance of the pattern in the source, or -1 if the pattern is not found.

int(item | int)

Converts the variable item or object item into an integer.

intostr(int | str)

Converts an integer into a string. The integer could also be a DBREF.

location(item-dbref | location-dbref)

Pushes the DBREF of the location of the given item onto the stack.

match(str | item-dbref)

Checks the given string against the player's objects, the objects in the room, and the exits in the room. Pushes the first object that contains the given string onto the stack. Pushes #-1 if the string is not matched in any object.

moveto(item-dbref location-dbref | )

Moves the item to the given location.

name(item-dbref | name-str)

Pushes the name attribute (@name) of the given item onto the stack.

next(item-dbref | next-item-dbref)

Pops the given item and pushes the next item in the list of contents (if the item is an obect) or list of exits (if the item is an exit) onto the stack.

not(value | boolean)

Performs the Boolean NOT on the value, and pushes 1 if the value evaluates true and 0 if the value evaluates false.

notify(player-dbref message-str | )

Sends the given string to the given player.

notify_except(room-dbref player-dbref message-str | )

Sends the given message to everyone in the given room except for the specified player. The excepted player can be #-1, in which case the message is sent to everyone in the room.

number?(str | boolean)

Pushes 1 if the string consists of a number, 0 otherwise.

odrop(item-dbref | odrop-str)

Pushes the odrop attribute (@odrop) of the item onto the stack.

ofail(item-dbref | ofail-str)

Pushes the ofail attribute (@ofail) of the item onto the stack.

ok?(value | boolean)

Pushes 1 if the value is a valid object, 0 otherwise.

or(value1 value2 | boolean)

Performs Boolean OR on value1 and value2 and pushes the Boolean result.

osucc(item-dbref | osucc-str)

Pushes the osucc attribute (@osucc) of the item onto the stack.

over(value other-value | value other-value value)

Copies the second-to-top value on the stack.

owner(item-dbref | owner-dbref)

Pushes the DBREF of the owner of the specified item onto the stack.

pick(value1 ... valueN ith-int | value1 ... valueN ith-value)

Copies the ith value from the top of the stack and pushes it onto the stack.

player?(item-dbref | boolean)

Pushes 1 if the item is a player, 0 otherwise.

pop(value | )

Pops the top of the stack.

program?(item-dbref | boolean)

Pushes 1 if the item is a program, 0 otherwise.

pronoun_sub(item-dbref str | new-str)

Uses the given item to convert pronoun substitutions (%n, %p, %o, and so forth) in the given string to the pronouns corresponding to the item. The new string is then pushed onto the stack.

random( | int)

Pushes a random integer from 0 to MAXINT onto the stack.

read( | str)

Reads a string from the user and pushes it onto the stack.

remove_prop(item_dbref property-str | )

Removes the given property from the given item.

rinstr(source-str pattern-str | index-int)

Searches for the pattern string in the source string. Pushes the index of the last occurance of the pattern in the source, or -1 if the pattern is not found.

rmatch(item-dbref str | item-dbref)

Checks the given string against all the objects associated with the given item. Pushes the object that matches the given string onto the stack. Pushes #-1 if no object matches the string.

room?(item-dbref | boolean)

Pushes 1 if the item is a room, 0 otherwise.

rotate(value-i value-i+1 ... valueN ith-int | value-i+1 ... valueN value-i)

Moves the ith value to the top of the stack.

set(item-dbref flag-str | )

Turns on the given flag on the given item.

setdesc(item-dbref str | )

Sets the description attribute (@desc) of the given item to the given string.

setdrop(item-dbref str | )

Sets the drop attribute (@drop) of the given item to the given string.

setfail(item-dbref str | )

Sets the fail attribute (@fail) of the given item to the given string.

setname(item-dbref str | )

Sets the name attribute (@name) of the given item to the given string.

setodrop(item-dbref str | )

Sets the odrop attribute (@odrop) of the given item to the given string.

setofail(item-dbref str | )

Sets the ofail attribute (@ofail) of the given item to the given string.

setosucc(item-dbref str | )

Sets the osucc attribute (@osucc) of the given item to the given string.

setsucc(item-dbref str | )

Sets the succ attribute (@succ) of the given item to the given string.

strcat(str1 str2 | str1str2)

Concatenates the top two strings on the stack and pushes the result.

strcmp(str1 str2 | int)

Pushes 0 if the two top strings are equal, or a non-zero number if they are not equal. Case-sensitive.

strcut(source-str index-int | first-str second-str)

Breaks the given source string into two parts, and pushes these two parts back onto the stack. The string is broken at the character after the given index integer. Example: information 6 strcut would push inform ation back onto the stack.

stringcmp(str1 str2 | int)

Pushes 0 if the two top strings are equal, or a non-zero number if they are not equal. NOT case-sensitive.

strlen(str | int)

Pushes the length of the given string onto the stack.

strncmp(str1 str2 numchars-int | int)

Compares the first numchars characters of the two strings on the top of the stack. Pushes 0 if the two top strings are equal, or a non-zero number if they are not equal. Case-sensitive.

subst(source-str pattern-str replacement-str | new-str)

Takes the source string and changes all occurances of the pattern string to the given replacement string. The resulting new string is then pushed onto the stack.

succ(item-dbref | succ-str)

Pushes the succ attribute (@succ) of the item onto the stack.

swap(value1 value2 | value2 value1)

Switches the two top values on the stack.

thing?(item-dbref | boolean)

Pushes 1 onto the stack if the item is a thing, otherwise pushes 0.

time( | seconds-int minutes-int hours-int)

Pushes the time onto the stack in the form of three integers representing the seconds, minutes, and hours at that current time.

variable(int | variable)

Converts the given integer into a variable. There are three predefined variables: me corresponds to variable number 0, loc is variable number 1, and trigger is variable number 2. Thus the code: 0 variable is equivalent to: me.

MUSH and MUSE Function Reference

This section presents functions that are available for use in MUSH and MUSE programs.

A large number of intricate operations can be performed by mud objects, including many basic and advanced mathematical operations. You can access these operations by using function calls. Function calls can also be used to perform character-string and logical operations, and to generate information on the state of the database and its contents. They return their data almost instantly, allowing you to use it in your commands statements and action lists. By incorporating a few of these function calls in your objects, you can really create some impressive stuff.

Functions

abs(number)

Returns the absolute value of the number.

add(a, b)

Returns the sum of a and b.

arccos(number)

Returns the arccosine of the number.

arcsin(number)

Returns the arcsine of the number.

arctan(number)

Returns the arctangent of the number.

art(word)

Returns the appropriate article of the following word; returns a if the initial letter of the next word is a consonant, and an if it's a vowel.

band(a, b)

Returns the bitwise AND of a and b (which are signed decimal integers).

base(number, oldbase, newbase)

Converts the number from the oldbase to the newbase. Bases must be between 2 and 36. Digits above 9 are represented by letters a = 10, through z = 35. For example, base(14,10,2) returns 111,. base(aa,16,10) returns 170.

bnot(number)

Returns the bitwise NOT of the number (which is a signed decimal integer)

bor(a, b)

Returns the bitwise OR of a and b (which are signed decimal integers).

bxor(a, b)

Returns the bitwise XOR of a and b (which are signed decimal integers).

change(string1, string2, index)

Changes the character at the given index in string1 to string2. Characters are numbered starting at 1.

children(object)

Returns a list of the object's children, in a format suitable for @foreach.

cjust(string, width)

Returns the string, center-justified, in a field of the given width.

comp(n, m)

Returns 0 if n = m, -1 if n < m, and 1 if n > m. Non-numeric strings all equal 0.

con(object)

Returns the first thing in the contents list of the object. Similar to the Lisp car() function.

cos(number)

Returns the cosine of the given number.

cr(player)

Returns the number of credits belonging to the player.

delete(string, index, numchars)

Returns the remainder of the given string after deleting numchars characters beginning with the character at the given index. Characters are numbered starting at 0.

dist2d(x1, y1, x2, y2)

Returns the distance between (x1, y1) and (x2, y2) as if plotted on a 2-dimensional graph.

dist3d(x1, y1, z1, x2, y2, z2)

Returns the distance between (x1, y1, z1) and (x2, y2, z2) as if plotted on a 3-dimensional graph.

div(a, b)

Returns a divided by b (this is integer division with no remainder).

entrances(object)

Returns a list of exits leading into the object, in a format suitable for use by @foreach.

even(argument)

Returns 1 if the argument is an even number, otherwise 0.

exit(object)

On a room, returns the first exit in the room. On a thing, returns its home.

exp(number)

Returns the number raised to the power of e (reverse ln).

extract(string, wordnumber, numwords)

Returns the substring from string starting at word number wordnumber and containing numwords words. Words are numbered starting at 1.

fadd(a, b)

Returns a + b, where a and b are floating point numbers.

fcomp(a, b)

Returns 0 if a = b, -1 if a < b, and 1 if a > b. Non-numeric strings equal 0.

fdiv(a, b)

Returns a / b, where a and b are floating point numbers.

first(string)

Returns the first word of the string.

flags(object)

Returns a string consisting of the current flags on the object.

flip(string)

Returns the string with its characters reversed.

fmul(a, b)

Returns a * b where a and b are floating point numbers.

fsqrt(number)

Returns the floating-point square root for the given number. If the number is negative, 0 is returned.

fsub(a, b)

Returns a - b, where a and b are floating point numbers.

get(object, attribute)
get(object/attribute)

Returns the specified attribute on the given object.

gt(number1, number2)

Returns 1 if number1 is greater than number2, otherwise returns 0.

hasflag(object, flag)

Returns 1 if the object has the specified flag, otherwise 0.

host(user)

Returns the hostname of user. If the user is not connected, nonexistent, or hidden from you, -1 is returned.

idle(user)

Returns the time in seconds that the user has been idle. If the user is not connected, nonexistent, or hidden from you, -1 is returned.

if(test, action)

Evaluates the test, and then performs the given action if the test is true; otherwise, it does nothing. The test is false if it evaluates to 0, -1, or to the null string. Otherwise it's true.

ifelse(test, action1, action2)

Evaluates the test, and then performs action1 if the test is true and action2 if test is false. The test is false if it evaluates to 0, -1, or to the null string. Otherwise, it's true.

isdigit(argument)

Returns 1 if the argument is a digit, 0 if the argument is a letter or a symbol.

land(a, b)

Returns the logical AND of a and b.

lattr(object)

Returns a list of the attributes on the given objects that have a non-null value.

lattrdef(object)

Returns a list of the attributes defined (with @defattr) on the object.

lcon(object)

Returns a space-separated list of items from the object.

lexit(object)

Returns a space-separated list of exits on the object.

link(object)

On an exit, returns the exit's destination; on a player or thing, returns its home; and on a room, returns the room's drop-to room.

linkup(object)

Returns a list of DBREFs of objects linked to the given object.

ljust(string, width)

Returns the string, left-justified, in a field of the given width.

ln(number)

Returns the natural log of the number.

lnot(number)

Returns the logical NOT of the number.

lnumber(number)

Returns a list of consecutive numbers from 0 to (number-1). The number cannot be larger than 250.

loc(object)

Returns the current location (room number) of the object.

log(number)

Returns the logarithm base 10 of the number.

lor(a, b)

Returns the logical OR of a and b.

lt(number1, number2)

Returns 1 if number1 is less than number2, otherwise returns 0.

lwho()

Returns a list of DBREFs of connected users. It costs 50 credits for an object to use this function.

lxor(a, b)

Returns the logical XOR of a and b.

match(string1, string2)

Returns 1 if string1 matches string2; otherwise returns 0. String2 may contain wild cards.

mid(string, index, numchars)

Returns numchars characters from the string, starting at the specified index.

mod(a, b)

Returns a mod b (the remainder after integer division).

mul(a, b)

Returns a multiplied by b.

name(object)
name(#DBREF)

Returns the name of the object. The object itself or a DBREF can be used as the argument.

nearby(object1, object2)

Checks to see if object1 and object2 are nearby each other; and returns 1 if they are, 0 if they aren't, and -1 if there is a problem identifying the objects. Two objects are considered nearby if they are in the same room, or if one is inside the other one.

next(object)

Returns the next thing in a list.

number(object)

Returns the DBREF of the object.

objectlist(object)

Returns a list of space-separated DBREFs taken from the list of objects beginning with object. For example, here's a way to tell everyone in the room what you're carrying: @foreach objectlist(con(me))=say I've got my %0!.

objectmem(object)

Returns number of bytes used by the object in the database.

objectn(object)

Returns the correct objective pronoun for the object (him, her, or it). If the object is neither male nor female, the function returns it.

odd(argument)

Returns 1 if the argument is an odd number, 0 if even.

onfor(user)

Returns the amount of time in seconds that the user has been on-line in the mud. If the user is not connected, nonexistent, or hidden from you, -1 is returned.

owner(object)

Returns the DBREF of the object's owner.

parents(object)

Returns a space-separated list of the object's parents, in a format suitable for @foreach.

pi()

Returns pi.

playmem(player)

Returns the total number of bytes used in the database by all objects owned by the player.

plural(number, suffix)

Returns the given suffix if the number does not equal 1; otherwise returns a null string.

pos(string1, string2)

Returns the position in string2 where string1 first appears.

poss(object)

Returns the correct possessive pronoun for the object (his, her, or its). If the object is neither male nor female, the function returns its.

pow(a, b)

Returns a to the b'th power, where a and b are floating point numbers.

quota(player)

Returns the builder's quota of the player.

quota_left(player)

Returns the unused builder's quota of the player.

rand(number)

Returns a random number between 0 and (number-1).

remove(string, wordnumber, numwords)

Returns the remainder of the string after removing numwords words starting at word number wordnumber. Words are numbered starting at 1.

rest(string)

Returns everything but the first word of string.

rjust(string, width)

Returns the string, right-justified, in a field of the specified width.

room(object)

Checks to see where the object is, and returns the room number. This works no matter how deeply nested the object is within rooms and things.

rtime([seconds])

Returns a time readout that can be altered by the specified amount of seconds. You can add the optional argument to xtime() to alter the current rtime. If the seconds argument is omitted, the current time is displayed.

s(string)

Performs pronoun substitution on the string.

scomp(string1, string2)

Compares the ASCII values of string1 and string2. Returns 0 if string1 = string2, -1 if string1 < string2, and 1 if string1 > string2.

sgn(a)

Returns 1 if a > 0, -1 if a < 0, and 0 if a = 0.

simp(floating-point-number)

Returns a rounded-off version of a floating-point number.

sin(number)

Returns the sine of the given number.

spc(number)

Returns a string consisting of the given number of spaces.

strcat(string1, string2)

Returns the concatenation of the two strings.

string(character, number)

Returns a string made up of the given character, repeated the given number of times.

strlen(string)

Returns number of characters in the string.

sqrt(number)

Returns square root of the number, rounded down to the nearest integer. If the number is negative, the function returns the square root of the number's absolute value.

sub(a, b)

Returns a minus b, where a and b are integers.

subj(object)

Returns the correct subject pronoun for the object (he, she, or it). If the object is neither male nor female, this function returns it.

tan(number)

Returns the tangent of the given number.

time()

Returns the current system time and date in alphanumeric format (although the exact value returned depends on your @tz setting). time() first checks the @tz value on the object calling the function, and if none is present it checks the @tz value of the object's owner.

time(tz)

Returns the current system time and date, using tz as the timezone value. The tz argument represents a number of hours before or after GMT, and can include an optional :Y or :N suffix to indicate whether or not U.S. style daylight savings time should be considered.

truth(a)

Returns 0 if a is a null string or 0, otherwise returns 1.

type(object)

Returns the object type of the object (room, exit, thing, or player).

v(argument)

Returns the value of the variable specified as its argument. Some of the possibilities include:

v(0) ... v(9)

Returns the appropriate stack value.

v(va) ... v(vz)

Returns the contents of the appropriate object register.

v(#)

Returns the DBREF of whoever caused the action.

v(N)

Return the object name of whoever caused the action, with its first letter capitalized.

v(n)

Returns the object name of whoever caused the action.

v(!)

Returns the DBREF of the object calling v().

v(attribute)

Returns the value of the appropriate attribute.

wcount(string)

Returns the number of words in the given string.

wmatch(string, argument)

Locates the position of the given argument in the string, where the given string is a series of words and/or numbers, separated by spaces. Returns 0 if the argument is not in the string. Not case-sensitive.

Lock Reference

Locks are used to make the successful use of objects possible or impossible, depending upon various things (for example, who's doing the attempting, what they're carrying, what room the attempt is occurring in, and so forth). There are many types of locks, including regular locks (@lock), enter-locks (@elock), leave-locks (@llock), and use-locks (@ulock). You can apply the full variety of lock options to any one these lock types.

Lock options are applied by the use of punctuation in lock command statements. The following examples refer to the @lock, but the same options can be applied to all types of locks.

Any lock may be combined with any other in a Boolean expression, by using & (and), | (or), and ! (not) symbols. You can also use parentheses () to group objects into logical elements. The lock in question will be "satisfied" if the Boolean expression evaluates to true.

Locks

@lock thing=object

Ordinary Lock. Checks against the player or object that tries to pick up the locked object (or walk through the locked exit), but also checks against all objects carried by the enactor.

@lock thing=+object
"Carry Lock."

Checks only against objects carried by the enactor, not against the enactor itself.

@lock thing=@object
"Indirect Locks."

Checks exactly as specified by the other object's lock.

@lock thing==object
"Is Lock."

Checks against the enactor only, not against objects the enactor carries.

@lock thing=@(object=attribute:value)
"Object Attribute Lock."

Checks the value of an attribute on another object (rather than on the enactor).

@lock thing=*player
"Player Lock."

Locks object for a specific player.

@attribute object=$pattern:/lock/actions
"Register Lock."

Locks a specific $ or ! event. Different from an @ulock, which locks all $ and ! events on the object.

Object Design Worksheet

The following worksheet might come in handy for your complex objects.

OBJECT NAME: ____________________________________  OBJECT NUMBER: ____
OBJECT TYPE: ___________________  OBJECT'S OWNER: ____________________
LINKED TO: _____________________  LOCKED TO: ___________  COST: ______
REGISTER                   CONTENTS/NOTES                      OPTIONS
======== ===================================================== =======
DESC     _____________________________________________________ _______
ODESC    _____________________________________________________ _______
ADESC    _____________________________________________________ _______
IDESC    _____________________________________________________ _______
SUCC     _____________________________________________________ _______
OSUCC    _____________________________________________________ _______
ASUCC    _____________________________________________________ _______
FAIL     _____________________________________________________ _______
OFAIL    _____________________________________________________ _______
AFAIL    _____________________________________________________ _______
DROP     _____________________________________________________ _______
ADROP    _____________________________________________________ _______
ODROP    _____________________________________________________ _______
ENTER    _____________________________________________________ _______
AENTER   _____________________________________________________ _______
OENTER   _____________________________________________________ _______
LEAVE    _____________________________________________________ _______
OLEAVE   _____________________________________________________ _______
ALEAVE   _____________________________________________________ _______
VA       _____________________________________________________ _______
VB       _____________________________________________________ _______
VC       _____________________________________________________ _______
VD       _____________________________________________________ _______
VE       _____________________________________________________ _______
VF       _____________________________________________________ _______
VG       _____________________________________________________ _______
VH       _____________________________________________________ _______
VI       _____________________________________________________ _______
VJ       _____________________________________________________ _______
VK       _____________________________________________________ _______
VL       _____________________________________________________ _______
VM       _____________________________________________________ _______
VN       _____________________________________________________ _______
VO       _____________________________________________________ _______
VP       _____________________________________________________ _______
VQ       _____________________________________________________ _______
VR       _____________________________________________________ _______
VS       _____________________________________________________ _______
VT       _____________________________________________________ _______
VU       _____________________________________________________ _______
VV       _____________________________________________________ _______
VW       _____________________________________________________ _______
VX       _____________________________________________________ _______
VY       _____________________________________________________ _______
VZ       _____________________________________________________ _______
FLAGS (circle):
Chown_ok  Dark  destroy_ok  enter_ok  Haven  Inherit  Jump_ok  Link_ok No_walls  opaque  puppet(of:___________)  visible
ATTRIBUTE OPTIONS (circle):
dark  date  function(__________________)  inherit  lock  osee  unsaved  wizard
MISCELLANEOUS: _______________________________________________________

How To Program a MOO

MOO stands for MUD Object-Oriented. The original MOO was TinyMOO, developed by Steven White. TinyMOO was then expanded and developed further by Pavel Curtis, who called his version LambdaMOO. Almost all of the MOOs running today are LambdaMOOs.

MOOs are similar to TinyMUD-based muds, such as MUCK, MUSH, and MUSE, but they have enough differences to warrant their own section. Some of the differences are fairly cosmetic, such as certain commands having slightly different names and syntax More importantly, though, MOOs differ from other TinyMUD-based muds in the underlying paradigm: MOOs are object-oriented.

In procedural environments, the data and the functions that operate on that data are separate. In object-oriented environments, objects contain both the data and the functions that operate on the data. This allows functionality to be grouped into more cohesive units. It also allows objects to be aware of "themselves." In MOO, an object contains attributes that store the data and verbs that define functions that operate on the data.

Objects can also inherit functionality from other objects in MOO. You can create generic objects that behave in a certain manner, and then create specific sub-types of these generic objects. You can then write functions on the specific objects, and perhaps override functions defined on the generic objects.

Popular MOOs

Here are some popular MOOs.

Name

Machine Name

Internet Address

Port

Diversity University

erau.db.erau.edu

155.31.1.1

8888

Jay's House MOO

jhm.ccs.neu.edu

129.10.111.77

1709

LambdaMOO

lambda.parc.xerox.com

192.216.54.2

8888

MediaMOO

purple-crayon.media.mit.edu

18.85.0.48

8888

ZenMOO

cheshire.oxy.edu

134.69.1.253

7777

LambdaMOO is the flagship MOO. It resides at Xerox PARC. Its chief maintainer, Pavel Curtis, maintains the MOO server code.

MediaMOO is a MOO devoted to media research. If you work in the media field—perhaps as an English professor, a journalist, or someone researching virtual reality—you may want to sign up on this MOO.

These addresses are current as of August, 1994. Keep in mind that they may change.

Basic Concepts

This section on MOOs assumes that you have read the previous sections on MUCKs, MUSHes, and MUSEs, since many of the concepts in MUCKs, MUSHes, and MUSEs can also be found in MOOs. Most of the commands available in TinyMUD-based muds have corresponding analogues in MOOs.

Basic Values

MOOs, like other types of muds, have the basic values of numbers and strings. Numbers are always integers, and strings are enclosed in double-quotes. MOOs also have lists, which can be a list of any type of value. MOOs also have special values called errors. These errors are simply codes that can be used to check to see if some action is performed successfully. In the event of an error, the error code can be used in some manner. Lastly, MOOs have objects. Objects are a combination of functionality (verbs) and data (properties).

Object Numbers

Each object in a MOO has a database reference number, just like each object in a TinyMUD-based mud, except that instead of it being called a DBREF, it is called an object number. Object numbers are completely synonymous with object names; in fact, you can use object numbers instead of object names. For instance, if a potted plant was object number 735 and a table was object number 675, you could type put #735 on #675 instead of put potted plant on table.

Inheritance

Objects can inherit values from other objects. For instance, you can create a car, and define various actions on it, such as drive. Then you can create a sports car that derives from the generic car, and performs special actions, such as revving the engine. It can also override the functionality of the object it is derived from, such as overriding the drive function to do something special that pertains to sports cars.

In this example, the generic car is called the parent object, and the specialized object that derives from it, the sports car, is called a child object. Child objects can override the functionality of their parent objects. If they don't, the default parent object's functionality is used. Objects can have children, and those children can have other children objects, and so forth.

Verbs

Verbs are the functions that objects can have that enable them to perform operations on their attributes, calculate things, and respond to actions and events. They are similar to attributes that define action lists, but they are more powerful because you can inherit from them.

Verbs are actually little programs that are defined on an object. The generic thing object has several predefined verbs already written on it, and you can add to these predefined functions, or override them to perform specialized tasks. Verbs defined on a parent object are also defined on their children, unless they are overridden.

Verbs are denoted using a colon with their object:

object-name:verb-name
object-number:verb-name

So, if you have a chair that has a sit verb defined on it, you can refer to that verb as:

chair:sit

If the chair is object #788, you can also use:

#788:sit
Properties

A property is a value that is stored on an object. It is similar to an attribute in TinyMUD, except that TinyMUD attributes can contain actions, whereas MOO properties are simply slots to store information about the object. Properties are typeless; that is, they can store any type of data field: numbers, strings, lists, and even other objects.

You refer to properties by using a period with their object:

object-name.property
object-number.property

You set these properties with the @property command:

@property property-name value

For example:

@property deck.numcards 52
Messages

Messages are properties that end with the suffix _msg. These messages are special kinds of properties. These messages correspond to certain kinds of verbs. For instance, a message corresponding to a fly verb might be called a fly_msg. Most of the string attributes, such as an object's description, are actually messages that have been defined on those objects.

Inspecting Objects

You can see an object's description in MOO in the same manner as in TinyMUD, by using the look command:

look object

If you examine the object, you can obtain the description, verbs, and properties on the object:

@examine object

Further information can be obtained using the show command. This command displays the object's name and number, its parent object's name and number, its owner's name and number, and a list of verbs and properties defined on the object:

@show object

The messages on an object can be viewed using:

@messages object

The dump command lists the programs associated with each verb defined on an object. It does not check for inherited verbs.

@dump object

To get the program listing for a specific verb, use:

@dump object:verb-name

You can also use:

@list object:verb-name

Basic Commands

Let's digress for a moment and present commands in MOO that have equivalent commands in TinyMUD-based muds.

Many MOO commands are similar to TinyMUD-type commands. Here is a list of basic TinyMUD commands and their MOO equivalents. If you haven't read the "Overview of Common Commands" section in this chapter, and the sections on MUCKs, MUSHes, and MUSEs, you may want to go back and read those sections first.

Command

TinyMUD command

MOO Equivalent

acting

: (colon)

same

dropping

drop object

same

examining

examine object

@examine object

getting

get object

same

going home

home

same

inventory

inventory

same

killing

kill object

not present

listing players

WHO

@who

looking

look object

same

moving

go place

same

paging

page player = message

page player "message"

quitting

QUIT

@quit

talking

" (double-quote)

same

whispering

whisper player = message

whisper "message" to player

At-Command Equivalencies

For a quick introduction, here is a list of TinyMUD at-commands and their MOO equivalents. For more detail, consult the "MOO Reference Manual" sections on "At-Commands" and "Messages," given later in this chapter.

TinyMUD At-Command

MOO Equivalent

@create object = cost

@create object named "name"

@desc object = description

@describe object as "description"

@dig room-name

@dig room-name

@dig exit-name to place

@drop object = message

@arrive exit is "message"

@fail object = message

@take_failed object is "message"

@nogo exit is "message"

@find

@audit

@link

None. Use @dig.

@name

@rename

@ofail object = message

@otake_failed object is "message"

@onogo exit is "message"

@open

None. Use @dig.

@osucc object = message

@otake_succeeded object is

"message"

@oleave exit is "message"

@oarrive exit is "message"

@succ object = message

@take_succeeded object is "message"

@leave exit is "message"

@arrive exit is "message"

MOO Programming

Now that you have had an introduction to basic MOO concepts, and you have seen which other TinyMUD-based commands have equivalencies in MOOs, you can delve into MOO programming.

If you have programmed in the C programming language, you will find yourself quite familiar with the programming constructs in MOOs, because they are almost exactly the same.

This section assumes you have had some prior experience using the C programming language. As such, it presents the programming concepts in a quick overview fashion, rather than an extensive tutorial on computer programming.

Expressions

Expressions evaluate to either true (non-zero) or false (zero). They are used for comparisons, conditional statements, and so forth.

The simplest expressions are literal values:

number
# object-number
"string"
error-code
variable

Next, you can create lists of expressions using:

{ expr, expr, ... expr }

These values can then be put together in more complex expressions:

Expression

Meaning

expr.name

Property access.

expr.(name)

Property access, where name is a string denoting the property.

expr:name(arguments)

Call a verb.

expr:(name)(arguments)

Call a verb, where name is a string denoting the verb.

function(arguments)

Call one of the built-in MOO functions.

expr[expr]

Index into a string or list.

expr[expr .. expr]

Get a slice of a string or list.

name = expr

Set a variable.

expr.name = expr

Set a property.

expr + expr

Add two expressions.

expr - expr

Subtract expressions from another.

expr * expr

Multiply two expressions.

expr / expr

Divide one expression by another.

expr % expr

Return the remainder of one expression divided by another.

- expr

Add two expressions.

expr == expr

Compare two expressions for equality.

expr != expr

Compare two expressions for inequality.

expr < expr

See if one expression is less than another.

expr <= expr

See if one expression is less than or equal to another.

expr > expr

See if one expression is greater than another.

expr >= expr

See if one expression is greater than or equal to another.

expr && expr

Determine the logical AND of two expressions.

expr || expr

Determine the logical OR of two expressions.

! expr

Determine the logical NOT of an expression.

expr IN expr

Test for set inclusion.

b-expr ? t-expr | f-expr

Test b-expr. If true, return t-expr. If false, return f-expr.

Most of these are the same as in the C programming language. Note that the tertiary expression (given last) contains a vertical line (|) in MOO, as opposed to a colon (:) in C.

Statements

You can use the expressions to create statements.

The simplest statement is the null statement, a semi-colon (;), which does nothing.

The conditional statement has the following syntax:

if (expr)
   statements
elseif (expr)
   statements
else
   statements
endif

The else-if and else clauses are optional. You need to use them only when you want to test further conditions or perform an action if the expression is false, respectively.

The list iteration statement has the following syntax:

for name in (expr)
   statements
endfor

and the numeric iteration statement is:

for name in [expr .. expr]
   statements
endfor

In this regard, the iteration statements are closer to the Pascal programming language than to the C programming language.

The indefinite iteration statement is:

while (expr)
   statements
endwhile

To return a value from a verb, use:

return expr;

or

return ;

Finally, to fork a task:

fork name (seconds-expr)
   statements
endfork

This last statement evaluates the expression to a number of seconds. After waiting that many seconds, a separate task will execute the given statements. Execution simultaneously continues with the statements, if any, after the endfork.

Entering Verbs

To program a verb on an object, use the @program command:

@program object:verb

This puts you into the MOO editor. You can type in your verb program, one statement per line. The program is interpreted as a list of strings. At the end, you type a period on a line by itself

.

to tell the MOO that your verb program is complete. The MOO then error-checks it. If it is correct, the program becomes the new program for that verb on that object.

If you are entering a verb program and you want to abort the editing, type

@abort

on a line by itself. The editor will terminate, and the verb will remain unchanged.

MOO Reference Manual

This section is a reference to MOOs. It lists at-commands, common functions, messages, and other information pertaining to MOOs.

At-Command Reference

@addalias alias to object
@addalias alias to object:verb

Adds an alias to the name of the object or the verb on an object, respectively. For example, if you want a Corvette that you create to also be known as a car, you can use this command to add the alias "car" to the Corvette.

@add-entrance exit-obj-number

Links the given exit object to the current room as an entrance.

@add-exit exit-obj-number

Links the given exit object to the current room as an exit.

@add-feature feature-object

Adds the specified feature object to you. Features are objects that provide additional functionality to you. For example, one common feature is one where you can begin a line with a minus symbol (-), followed by a name and some text, and it will perform a directed say command at that person:

> -George Hey there!
You say [to George] "Hey there!"

You can find out the object number of this feature on your MOO by using the @features command, and thus add it to your feature list.

@args object:verb direct-obj
@args object:verb direct-obj preposition
@args object:verb direct-obj preposition indirect-obj

These three commands set the direct object, preposition, and indirect object specifiers on the given object's verb.

@audit

Prints out a list of everything that you own.

@check-chparent object to new-parent-obj

Sees if the specified parent object is already the parent of the given object.

@check-property object.property

Sees if the specified property already exists on the given object.

@chmod object permissions
@chmod object:verb permissions
@chmod object.property permissions

Changes the permissions on the object, verb, or property, respectively. The permissions are given by a string. The valid object permissions are r, w, and f. The valid verb permissions are r, w, x, and d. The valid property permissions are r, w, and c.

@chparent object to new-parent

Changes the parent of the specified object to the new parent object. The object will inherit all the verb and property definitions of the parent object.

@classes

Lists the classes available for you to use. You might want to check this out when you are first starting.

@clear-property object.property

Changes the property to use value of the parent object's property instead of itself.

@contents object

Lists the contents of the given object.

@copy object:verb to new-object:new-verb

Copies the arguments, code, and other associated information of the specified object's verb to the new object's verb.

@count

Displays the number of objects that you own. Remember that your character itself is an object that you own.

@create class-name named "object-names"
@create parent-obj named "object-names"

Creates a new object. The first form specifies one of the generic classes to use as the new object's parent. The second form uses the given parent object as the new object's parent. The object names string is a list of comma-separated aliases for the name of the object. The first item in the string will be used as the name of the new object, and the rest of the items in the string are aliases for that object.

> @create $thing named "Vehicle"
> @create Vehicle named "Dodge Viper,viper,car"
@describe object as description

Sets the description on the object.

@dig "place"
@dig exits-to|exits-from to "place"
@dig exits-to|exits-from to room-obj-number

Creates a room. The first form simply creates a room with that name, and tells you the object number of the newly created room. The second form also creates exits to and from the newly created room. The exits-to links the current room to the new room, and the exits-from links the new room back to the current room. You must own the current room in order to link to it. If you do not own the current room, you should take note of the exit object numbers and get the owner of the current room to @add-exit and @add-entrance the exit objects to their room.

@disinherit child-object [ from parent-object ]

Removes a child object from the parent object. You must own the parent, but you do not have to own the child object.

@display object

Displays information about the object in a formatted manner. See the MOO help on your system for a detailed description of the options available.

@display-option

Allows you to customize the formatting of the @display command. See the MOO help on your system for a detailed description of the options available.

@dump object

This command displays the verbs and properties that have been defined on the given object.

@edit object:verb

Enables you to edit the verb on the given object. This command puts you into the MOO editor.

@edit-option

Enables you to customize the editor that is invoked when you enter a verb program using @program, or compose a mail message, and so forth. See the MOO help on your system for a detailed description of the options available.

@eject object [ from room ]

Removes the object from the current room, or the specified room if that is given. Objects thus removed are sent home.

@entrances

Lists the entrances into the current room. You must own the current room in order to see this.

@examine object

Displays a more detailed description of the given object. The description contains the object's full name, object number, aliases, owner's name, and object number, its description, its contents, and readable verbs defined on the object.

@exits

Lists the exits from the current room. You must own the current room in order to see this.

@features

Lists the features on your system that you can use. You can add these features to your player object by using the @add feature, and you can remove features from your player object by using the @remove feature.

@forked

Lists the forked tasks that you own.

@gag object

Prevents you from seeing messages or text from the specified object, which is usually a player. This is useful when you want to ignore someone who is being annoying or generating a lot of output.

@gaglist

Lists the objects you currently have gagged.

@gender object

Sets the gender of the specified object.

@go place
@go room-obj-number

Teleports you to the specified place or room number. On some MOOs, a route is computed and you walk room by room to the destination rather than being magically teleported there.

@hide

Removes your character from appearing in the WHO list. However, you will still show up if someone specifically uses your name in a command such as @whois.

@kids object

Lists the children of the specified object.

@kill task

Enables you to kill off a task. See the MOO help on your system for a more detailed description of this command.

@lastlog [ player ]

Displays the last login times of the players in the database. If you specify a player name, it displays the last time that player was connected to the MOO.

@linelength number

Sets the length of a line on your screen. The MOO will use this length to break up text that is displayed to you. However, it is better to use a client program that provides this functionality than for you to have the MOO do it for you, since the MOO does it slower.

@list object:verb

Displays the code for the given object's verb.

@more

Sets your display to print out long messages in a page-by-page fashion. This command uses the @pagelength value to determine how long your screen is. If a displayed message is longer than your page length, the display is halted and you will see an indicator that there is more to follow.

@opacity object is number

Sets the opacity for the given object, usually a container. The opacity number is one of three values. If the number is 0, the container is transparent, and you can see into it. If the number is 1, the container is opaque, and you cannot see into it when the container is closed. If the number is 2, you cannot see into it even if it is open.

@pagelength

Sets the number of lines you want to have displayed to you at one time when long messages are sent to you. Also see @more.

@parents object

Displays the name and object number of all of the given object's ancestors.

@password old-password new-password

Changes your password from the old value to the new value.

@program object:verb

Allows you to enter code for the given object verb. This command puts you into the MOO editor. For details on the commands available for use in the MOO editor, consult the editor help on your MOO system.

@property object.property [ initial-value ]

Sets the given object's property to the specified initial value. If the initial value is omitted, the property is initially set to 0.

@quit

Exits you from the MOO.

@quota

Displays your builder's quota, which indicates how many objects you can create.

@recreate old-object as parent-obj named "names"

Changes the given old object to a new object with a new parent and a new set of names and aliases. The aliases are a comma-separated list of names, the first of which is taken to be the name of the new object. This command enables you to recycle older, unused objects you own into new ones.

@recycle object

Destroys the given object. You must own the object.

@remove-entrance entrance

Removes an entrance from the current room.

@remove-exit exit

Removes an exit from the current room.

@remove-feature feature-object

Removes a feature from your features list.

@rename object to name,alias,...,alias

Changes the name of the given object to a new name. The aliases are a comma-separated list of names, the first of which is taken to be the name of the new object.

@rename object:verb to new-verb-name

Renames a verb on an object to a new name.

@rmalias alias from object
@rmalias alias from object:verb

Removes an alias from an object or an object verb.

@rmproperty object.property

Removes a property from an object.

@rmverb object:verb

Removes a verb from an object.

@sethome

Sets your home to the current room.

@show object
@show object:verb
@show object.property

Displays detailed information about the given object, verb, or property.

@suggest

Makes a suggestion to the owner of the current room.

@ungag object

Removes an object, usually a player, from the list of objects you have gagged.

@unlock object

Removes the lock on the given object.

@verb object:verb

Creates a verb on the given object.

@version

Displays the version number of the MOO.

@whereis player

Displays the current location of the specified player.

@who [ player ... player ]

Displays the list of people that are currently using the MOO. If one or more specific players are given, information for only those players is displayed. If a specified player is not connected, the last connection time of that player is displayed.

@whois player

Displays the real-life name and e-mail address of the specified player.

@wrap [ on|off ]

Turns line wrapping on or off, as specified.

Message Reference

MOOs have a message implementation that is similar to the attribute systems in MUCKs, MUSHes, and MUSEs (such as @drop and @odrop). These at-commands set the messages displayed when certain events happen. In MOO, these messages are a bit more consistent than in the older TinyMUD-based muds.

This section lists the messages that can be set in MOO.

To set one of these messages, use the following syntax:

@message-name object is "text"

For example:

> @drop vase is "You drop the vase. It shatters into a million pieces."

Messages that begin with @o are displayed to other players (besides the enacting player), with the name of the enacting player included in the text of the @o message.

The messages are listed alphabetically as pairs of messages—the primary message and its corresponding @o message. For each message, if the message has a default, the default message text is given for that particular message. This default message is given in parentheses after the message name.

Messages
@arrive

Displayed to the player right after successfully using the exit.

@oarrive ( %N has arrived. )

Displayed to others in the destination room when the player successfully uses the exit.

@close ( You close %d. )

Displayed to the player who closes a container.

@oclose ( %N closes %d. )

Displayed to others in the room when the player closes a container.

@drop_failed ( You can't seem to drop %t here. )

Displayed to the player who fails to drop something.

@odrop_failed ( %N tries to drop %t but fails! )

Displayed to others in the room when the player fails to drop something.

@drop_succeeded ( You drop %t. )

Displayed to the player who drops something.

@odrop_succeeded ( %N drops %t. )

Displayed to others in the room when the player drops something.

@ejection ( You expel %d from %i. )

Displayed to the player who ejects something from the room.

@oejection ( %D is unceremoniously expelled from %I by %n. )

Displayed to others in the room when the player ejects something from the room.

@empty ( It is empty. )

Displayed as the container's contents when the container is empty.

@leave

Displayed to the player right before successfully using the exit.

@oleave ( %N has left. )

Displayed to others in the source room when the player successfully uses the exit.

@nogo ( You can't go that way. )

Displayed to the player who fails to use an exit.

@onogo (no default)

Displayed to others in the room when the player fails to use an exit.

@open ( You open %d. )

Displayed to the player who opens a container successfully.

@oopen ( opens %d. )

Displayed to others in the room when the player opens a container successfully.

@open_fail ( You can't open that. )

Displayed to the player who opens a container unsuccessfully.

@oopen_fail (no default)

Displayed to others in the room when the player opens a container unsuccessfully.

@put ( You put %d in %i. )

Displayed to the player who puts something into a container.

@oput ( puts %d in %i. )

Displayed to others in the room when the player puts something into a container.

@put_fail ( You can't put %d in that. )

Displayed to the player who fails to put something into a container.

@oput_fail

Displayed to others in the room when the player fails to put something into a container.

@remove ( You remove %d from %i. )

Displayed to the player who removes something from a container.

@oremove ( removes %d from %i. )

Displayed to others in the room when the player removes something from a container.

@remove_fail ( You can't remove that. )

Displayed to the player who fails to remove something from a container.

@oremove_fail

Displayed to others in the room when the player fails to remove something from a container.

@take_failed ( You can't pick that up. )

Displayed to the player who fails to take something.

@otake_failed

Displayed to others in the room when the player fails to take something.

@take_succeeded ( You take %t. )

Displayed to the player who succeeds in taking something.

@otake_succeeded ( picks up %t. )

Displayed to others in the room when the player succeeds in taking something.

@victim_ejection ( You have been expelled from %i by %n. )

Displayed to the player who is ejected from a room.

Error Reference

Error

Meaning

E_NONE

No error

E_TYPE

Type mismatch

E_DIV

Division by zero

E_PERM

Permission denied

E_PROPNF

Property not found

E_VERBNF

Verb not found

E_VARNF

Variable not found

E_INVIND

Invalid indirection

E_RECMOVE

Recursive move

E_MAXREC

Too many verb calls

E_RANGE

Range error

E_ARGS

Incorrect number of arguments

E_NACC

Move refused by destination

E_INVARG

Invalid argument

E_QUOTA

Object ownership quota exceeded

Built-In Function Reference

MOOs come with a set of built-in functions you can access in your MOO programs. These built-in functions are described in this section. For more detailed information, consult the specific topic help documentation on your MOO.

In addition to these basic built-in functions, many MOOs have packages of utility functions that are also very helpful, such as math utilities, string manipulation, list manipulation, e-mail systems, news systems, democracy and voting systems, and so forth. You may want to look at your MOO help for such utilities by typing help utilities or help core-index.

Throughout this section, the following terminology is used to indicate parameter types and return values.

Terminology

Indicates

num

integer

str

string

obj

an object

list

a list of values

void

no return value

value

any value

result

any value

num abs(num)

Returns the absolute value of the given number.

void add_property(obj, property-name-str, initial-value, info-list)

Adds the specified property to the given object and all of its descendants The property will have the given initial value, and its property information will be set to the given property information list. If any of the arguments are invalid, the error E_INVARG is returned. If the programmer does not have write permission on the object, E_PERM is returned. If the object does not have a property with the specified name, E_PROPNF is returned.

void add_verb(obj, info-list, args-list)

Creates a new verb on the given object. The new verb's owner, permissions, and name (or names) is specified by the information list. The new verb's direct object, preposition, and indirect object are specified in the argument list. If any of the arguments is invalid, the error E_INVARG is returned. If the programmer does not have write permission on the object, E_PERM is returned.

list callers()

Returns a list of the verbs that have called the current task. Similar to a trace of the verbs that have successively called other verbs, resulting in the current task being executed.

obj caller_perms()

Returns the currently-executing verb's caller's permissions.

void clear_property(obj, property-name-str)

Clears the specified property on the given object. Clear properties return the value of the parent's property when accessed, as opposed to their own value. If the programmer does not have write permission on the object, the error E_PERM is returned. If the object is not valid, E_INVARG is returned. If the given object defines the specified property, as opposed to inheriting it, E_INVARG is returned. If the object does not have a property with the specified name, E_PROPNF is returned.

list children(obj)

Returns a list of the children of the given object.

void chparent(obj, new-parent-obj)

Changes the parent of the given object to the given new parent object. If the given object is not valid, E_INVARG is returned. If the new parent object is not fertile (has its "f" bit set) or is not owned by the owner of the given object, E_PERM is returned.

str connection_name(obj)

Returns the name of the connection being used by the player.

list connected_players()

Returns a list of the object numbers of the players currently connected to the MOO.

num connected_seconds(player-obj)

Returns the number of seconds the given player object has been connected to the MOO.

obj create(parent-obj [, owner-obj)

Creates a new object that has the given parent object as its parent. If the owner object is not specified, the owner is the programmer. If the owner object is #-1, the object is its own owner. If the owner object is a valid object, it becomes the owner of the newly created object. The new object's name is the empty string, its location is initialized to nothing (#-1), and it has no contents. The various property flags are set to zero. In addition, the new object inherits other properties from its parent object. The parent must be fertile (have its "f" bit set) or must be owned by the programmer. Otherwise, the error E_PERM is returned. If the player creating the object cannot do so because of a quota limitation, the error E_QUOTA is returned.

str crypt(str)

Encrypts the given string and returns the encrypted string.

str ctime([time-num])

Uses the given time number to create a string that specifies the time. If the time number is not given, the current time is used. The format of the string is DDD MMM XX HH:MM:SS YYYY TZN, as in Tue Jul 19 12:00:00 1994 EST.

void delete_property(obj, property-name-str)

Deletes the specified property from the given object and all of its descendants. If the programmer does not have write permission on the object, the error E_PERM is returned. If any of the arguments are not valid, E_INVARG is returned. If the object does not have a property with the specified name, E_PROPNF is returned.

void delete_verb(obj, verb-name-str)

Deletes the specified verb from the object and all of its descendants. If any of the arguments are invalid, the error E_INVARG is returned. If the programmer does not have write permission on the object, E_PERM is returned.

list eval(str)

Evaluates the given string as though it were a piece of MOO code. The returned value is a list. The first item in the list is either 1, indicating that the code did not have compilation errors, or 0, indicating that it did. The second item in the list is either the result of the evaluation if there were no compilation errors, or a string denoting the compiler error messages if there were such errors.

num idle_seconds(player-obj)

Returns the number of seconds the given player object has been idle on the MOO.

num index(subj-str, pattern-str [, CASE-MATTERS})

Finds the first occurrence of the pattern string in the given subject string, and returns the index of this first occurrence of such pattern in the subject. Case is significant only if the optional CASE-MATTERS specifier is given.

num is_clear_property(obj, property-name-str)

Returns 1 if the property on the object is clear, 0 otherwise. Clear properties return the value of the parent's property when accessed, as opposed to their own value. If the programmer does not have read permission on the object, the error E_PERM is returned. If the object is not valid, E_INVARG is returned. If the object does not have a property with the specified name, E_PROPNF is returned.

num is_player(obj)

Returns a non-zero value if the given object is a player, otherwise returns 0. If the given object is not valid, E_INVARG is returned.

void kill_tasks(task-id-num)

Stops the given task by removing it from the list of queued tasks.

num length(list)

Returns the number of items in the given list.

num length(str)

Returns the length of the given string.

list listappend(list, value, [, index-num])

Inserts the given value into the given list at the end of the list. If the optional index number is specified, the value is inserted after the value in the list with that index. Lists are always indexed beginning at 1.

list listdelete(list, index-num)

Deletes the index-th item from the list, and returns the new list. If the given index is out of range of the list, the error E_RANGE is returned.

list listinsert(list, value, [, index-num])

Inserts the given value into the given list at the beginning of the list. If the optional index number is specified, the value is inserted before the value in the list with that index. Lists are always indexed beginning at 1.

list listset(list, value, index-num)

Sets the index-th item in the given list to the given value.

list match(subj-str, pattern-str [, CASE-MATTERS])

Searches for the first occurrence of the pattern in the subject. If found, a list of information pertaining to the match is returned. The pattern can contain special MOO regular expressions. For more details, consult the MOO help.

num max(num1, num2, ..., numN)

Returns the maximum of the given set of numbers. If any argument is not a number, E_TYPE is returned.

obj max_object()

Returns the highest object number of the currently existing objects.

num min(num1, num2, ..., numN)

Returns the minimum of the given set of numbers. If any argument is not a number, E_TYPE is returned.

void move(obj, location-obj)

Moves the given object to the given location. Various permissions are checked to make sure that the object has permission to move to the specified location.

void notify(player-obj, str)

Displays the given string to the given player.

obj parent(obj)

Returns the parent object of the given object.

result pass(args, ....)

Calls the verb defined on the parent object with the same name as the current verb. This enables programmers to define verbs that add onto the actions of parent object verbs.

list players()

Returns a list of the object numbers of all the players that are in the database.

list properties(obj)

Returns a list of the names of the properties defined on the given object. If the object is not valid, the error E_INVARG is returned. If the programmer does not have permission to read the properties, E_PERM is returned.

list property_info(obj, property-name-str)

Returns a list containing information about the specified property on the given object. The list that is returned has the form { owner, permissions }. The owner is the owner of the property, and permissions is a string denoting if the property is readable, writable, or child-owner-inheritable (r, w, and c, respectively). If the programmer does not have read permission on the object, the error E_PERM is returned. If the object is not valid, E_INVARG is returned. If the object does not have a property with the specified name, E_PROPNF is returned.

list queued_tasks()

Returns a list denoting the tasks owned by the programmer, whether they are forked, suspended, or reading user input.

num random(num)

Returns a random number from 1 to the given number. If the argument is a negative number, the error E_INVARG is returned.

str read([player-obj])

Suspends the current task, waits for the user to enter a line of text, then resumes execution by returning the text line as a string. Fails if the task has already been suspended.

void recycle(obj)

Recycles the given object. The object is permanently destroyed. If the programmer does not own the object, the error E_PERM is returned. If the object is not valid, E_INVARG is returned. The given object's parent becomes the parent of the given object's children.

num rindex(subj-str, pattern-str [, CASE-MATTERS])

Finds the last occurrence of the pattern string in the given subject string, and returns the index in the subject that matches the first character of the pattern. Case is significant only if the optional CASE-MATTERS specifier is given.

list rmatch(subj-str, pattern-str [, CASE-MATTERS])

Searches for the last occurrence of the pattern in the subject. If found, a list of information pertaining to the match is returned. The pattern can contain special MOO regular expressions. For more detail, consult the MOO help.

num seconds_left()

Returns the number of seconds left before the currently-executing task will be terminated due to time constraints.

str server_version()

Returns a string denoting the version of the MOO server.

list setadd(list, value)

Adds the given value to the given list. The list is considered to be a set of values—thus, the value is not added to the list if it already exists in the list.

list setremove(list, value)

Removes the given value to the given list. If the value occurs more than once in the list, only the first occurrence of the value is removed from the list.

void set_player_flag(obj, value)

Sets the player status of the given object to the specified value. If the value is non-zero, the object is a player. If the value is 0, the object ceases to be a player. If the object is not a valid object, E_INVARG is returned.

void set_property_info(obj, property-name-str, info-list)

Sets the specified property on the given object to the specified property information list. This list has the format { owner, permissions }, where the owner is the owner of the property and permissions is a string denoting if the property is readable, writable and child-owner-inheritable (r, w, and c, respectively). If the programmer does not have write permission on the object, the error E_PERM is returned. If the object is not valid, E_INVARG is returned. If the object does not have a property with the specified name, E_PROPNF is returned.

void set_task_perms(obj)

Changes the currently-executing verb's permissions to be the same as the given object's.

void set_verb_args(obj, verb-name-str, info-list)

Sets the argument list of the specified verb on the given object. This list has the form {direct-obj, preposition, indirect-obj}. If the object is not valid, the error E_INVARG is returned. If the programmer does not have write permission on the object, E_PERM is returned. If the specified verb name does not exist on the given object, E_VERBNF is returned.

void set_verb_code(obj, verb-name-str, code-list)

Sets the code listing associated with the specified verb on the given object. If the object is not valid, the error E_INVARG is returned. If the programmer does not have read permission on the object, E_PERM is returned. If the specified verb name does not exist on the given object, E_VERBNF is returned.

void set_verb_info(obj, verb-name-str, info-list)

Sets the information list associated with the specified verb on the given object. The list has the form { owner, permissions, names }, where owner is the owner of the object, permissions denote whether the verb is readable, writable, executable, or in debug mode (r, w, x, and d, respectively), and names denote synonymous names of the verb. If the object is not valid, the error E_INVARG is returned. If the programmer does not have write permission on the object, E_PERM is returned. If the specified verb name does not exist on the given object, E_VERBNF is returned.

num sqrt(num)

Returns the square root of the given number. If the given number is negative, the error E_INVARG is returned.

num strcmp(str1, str2)

Compares the two strings. If str1 is lexicographically less than str2, a negative number is returned. If str1 is lexicographically greater than str2, a positive number is returned. If the two strings are equal, 0 is returned.

str strsub(subj-str, pattern-str, replacement-str [, CASE-MATTERS])

Replaces the given pattern string in the given subject string with the given replacement string. If the optional CASE-MATTERS specifier is given, case is significant when the pattern matches substrings in the subject.

void suspend(seconds-num)

Suspends the currently-executing task for at least the specified number of seconds. Afterwards, the task resumes execution.

num task_id()

Returns the task identifier for the currently executing task.

num ticks_left()

Returns the number of seconds left before the currently-executing task will be terminated due to time constraints.

num time()

Returns the number of seconds elapsed since January 1, 1970.

obj toobj(value)

Converts the given value to an object number. Numbers are converted to object numbers. Strings that represent numbers are converted to object numbers, also. Such strings can begin with a # symbol. Lists return the E_TYPE error.

num tonum(value)

Converts the given value to a number. Objects are converted to their object numbers. Strings are converted to their numeric values. If the value is a string, but does not represent a number, 0 is returned. If the value is a list, the error E_TYPE is returned.

str tostr(value)

Converts the given value to a string. If the given value is a list, the string {list} is returned.

num typeof(value)

Returns the type of the given value. This number will be one of the following constants: NUM, STR, LIST, OBJ, or ERR.

num valid(obj)

Returns a non-zero number if the given object is a valid object and 0 if the given object is not a valid object. A valid object is one that has been created and not recycled.

list verbs(obj)

Returns a list of the names of the verbs defined on the given object. If the object is not a valid object, E_INVARG is returned. If the programmer does not have permission to read the object, E_PERM is returned.

list verb_args(obj, verb-name-str)

Returns the argument list of the specified verb on the given object. This list has the form {direct-obj, preposition, indirect-obj}. If the object is not valid, the error E_INVARG is returned. If the programmer does not have read permission on the object, E_PERM is returned. If the specified verb name does not exist on the given object, E_VERBNF is returned.

list verb_code(obj, verb-name-str)

Returns a listing of the code associated with the specified verb on the given object. If the object is not valid, the error E_INVARG is returned. If the programmer does not have read permission on the object, E_PERM is returned. If the specified verb name does not exist on the given object, E_VERBNF is returned.

list verb_info(obj, verb-name-str)

Returns a list of the information associated with the specified verb on the given object. The list has the form { owner, permissions, names }, where owner is the owner of the object, permissions denotes whether the verb is readable, writable, executable, or in debug mode (r, w, x, and d, respectively), and names denote synonymous names of the verb. If the object is not valid, the error E_INVARG is returned. If the programmer does not have read permission on the object, E_PERM is returned. If the specified verb name does not exist on the given object, E_VERBNF is returned.

Summary

You are now completely prepared to create environments of astounding complexity and lifelike responsiveness. All the tools in the world, however, won't help you if you wander around from area to area without completing anything coherent. The creation of coherent, consistent, and entertaining interactive environments is a nascent artform, one that requires not only programming capability but artistic sensibility as well.

What is a mud? In a strict sense, it is a highly structured imaginative exercise—that is, a game—which involves the simulation of a fictional reality on a literary and dramatic level. The goal of interactive narrative is to allow the participants to project their various alter-egos into your world-specific simulations, discovering problems and resolutions with a high degree of internal consistency.

A fledgling devotion somewhere between art and science, interactive narrative design relies upon a tricky sort of relativistic thinking—the attainment of an object-and-pattern-oriented skill set, which in itself is a new and exciting development. This mental skill set draws its inspirations from the fields of game theory and computer programming, as well as the more traditional narrative arts. But unlike the traditional novelist or playwright, whose stories progress in a linear fashion from event to event, a mud builder cannot simply decide which interesting turn the plotline "should" take next. Here in the living electronic world, players are free to move through your story in any variety of ways, and you should be ready to give that freedom to them. Consider all your possible "branch-points" and combinations of story elements, and draw a practical but flexible conceptual framework to encompass their interplay.

With a little brainstorming and a few handy commands, it's possible to flesh your design out in short time; creating intricate mazes of interacting elements. Try to alternately tighten and release your control over the plotline as the players proceed; rely instead on your descriptive and programming skills; you don't want players to feel restricted within the conceptual confines of your narrative. By concentrating on the quality and detail of your interactive elements, you will shift the players' attention—and more importantly, your own—from the structural mechanics of interactive stories to the stories themselves.

After spending a bit of time as a mud programmer, you should really be getting the hang of it. You should be able to settle into a groove that feels natural and economic for you, using these pages as your handbook. Soon after that, you'll be interacting with the text, on it, and in it!

Previous Page TOC Index Next Page Home