RuthMOO: Programming the Environment

Contents

  1. RuthMOO: Getting Started
  2. RuthMOO: Settling In
  3. RuthMOO: Building the Landscape
  4. RuthMOO: Programming the Environment
    1. Becoming a Programmer
    2. The Flippable Coin: A Programmming Tutorial
    3. Objects, Properties, Verbs and Flags
    4. Verb Types and Arguments
    5. Data Types, Variables and Control Structures
    6. A Simple Example Verb
    7. Tools For Your Toolbox
  5. RuthMOO: Surviving and Thriving



Welcome to RuthMOO, an online community hosted at Brandeis University. This page is intended to introduce the basics of programming on the MOO. For more complete information on the MOO programming language please see the Lambda MOO Programmer's Reference Manual. If you do not have a background in programming you might find this document a bit dense, but it's packed with useful information.



1. Becoming a Programmer

At RuthMOO we encourage anyone who is interested in MOO programming to become a programmer. Before you can do any programming on a MOO you must first get your programmer bit (progbit). Before you can get a progbit at RuthMOO you must first complete a few simple tasks so that we know you have some idea of what you are doing.

If you are unsure how to accomplish any of these tasks please feel free to ask for help. These requirements are also outlined under the help topic: progbit.




The Flippable Coin:A Programming Tutorial

This tutorial is designed to walk you through the process of creating an object with verbs and properties, suitable for use as a generic object, with explanations along the way. It is based upon the Generic Flippable Coin (#715) by fiasco@RuthMOO.

Back when I started doing MOO programming in 1996, I was looking for a simple project to try, and finally decided on a flippable coin (or Binary Decision Support System). This is by no means a unique object, many other people have coded flippable coinsonline, nor was it the first, nor even the best. On the other hand, it was designed from scratch by me, and taught me some important lessons about how MOO code works and how inheritance on MOOs can affect the way you code generic objects. I hope that you find it useful. Please feel free to adapt and use this code in any way you see fit. It is provided as is, without warantee.

Step 1

@create $thing named coin

You now have an object, a child of $thing, named coin. You'll notice among other handy features that it has a description and various messages that get displayed when you pick it up, drop it or give it to someone else. The first thing I realized was that while MOO objects by default have a single description, I wanted my coin to have two descriptions, one for each side of the coin. So the first thing I did was to describe the front of my coin:

@describe coin as "A small gold coin with an ornate capital S."

I then added a property to my coin which would hold the description of the other side:

@prop coin.reverse_description "The reverse of a small gold coin,
decorated with a fierce looking salamander."

Now I had my two descriptions, but no way to tell whether the coin was face up or face down, and no way to look at the description on the reverse. Since I knew the coin could only be in one of two states (since I was not going to allow it to land on edge), and since that state was going to be changing as the coin was used, I decided to add a property to track the state. I decided, arbitrarily, that if the state was 1 then the coin would be heads up. If it was 0, the coin would be heads down.

@prop coin.state 1

Step 2

Now that the coin has two descriptions, one for each side, and can tell which side is up, we have to let the user see the appropriate description. The verb that determines what the object's description is is description(), so we will need to create a specialized version of the description verb for our coin. We start by defining the verb on our object.

@verb coin:description tnt

To see the result of this, type: @display coin. (don't forget the period at the end), and you will see the verb description listed. However, if you @list coin:description you will see that it has not been programmed yet. We do that next.

@edit coin:description

This puts us into the editor where we can enter the following lines of code:

if (this.state)
  desc = this.description;
else
  desc = this.reverse_description;
endif
return desc;

Then we compile and exit the editor (if there are no errors). Now when you look at the coin you should see the description of its front side. But how do you see the description on the reverse? Remember that in the code we returned a different description value depending upon the value of the "state" property of our coin. If the value of coin.state is equal to one (or anything other than zero) then we will see the front. If it is equal to zero, we will see the reverse.

In order to test our description verb lets manually rest the value of coin.state:

@set coin.state to 0

Now when you look at the coin you should see the reverse description (if all went well), but that's a clumsy way to turn a coin over and only the owner of the coin or a wizard can do it. Now it's time to add a command line verb to let anyone flip our coin and have it come up with a random state. The verb we are going to add is flip. Once again we start by defining it.

@verb coin:flip this none none

Notice that this time, instead of using the arguments tnt (short for "this none this"), we have specified this none none. To use this verb we will type flip coin where coin matches this and no other arguments are expected. Now to program the verb.

@edit coin:flip

And enter the lines of code:

player:tell("You flip " + this.name + " into the air.");
this.state = !this.state;

Now when you flip coin, it will switch from heads up to tails up (and vice versa), which you can verify by looking at it after each flip. But we would really like to have its state be a random one instead of just flip flopping back and forth, and while we're at it, we'll make another change that will let other people in the room with us know that we just flipped the coin.

$you:say_action("%N % %t into the air.");
this.state = random(2)-1;

Now when you flip coin it will land on a random face. But let's back up and explain some of the changes. Easy one first: random(n) generates a random number between 1 and n, but we want either a 1 or a 0, so we do random(2) and subtract one from the result and then assign that value to this.state.

Now for all that %<> stuff in the message. These tags let us do pronoun substitution, customizing our messages for the person who sees them. %N is the name of the person who called the verb (the person who typed: flip coin in this case), %t is the name of the coin itself, and % lets us show the person who flipped the coin: You flip coin into the air. while everyone else sees: Habari_Guest flips coin into the air.

And finally there is $you:say_action. This verb does two important things: it actually does the pronoun substitution, and it also composes and sends three different messages:

To the player:
You flip coin into the air.
To the object:
Habari_Guest flips you into the air.
To everyone else:
Habari_Guest flips coin into the air.

If you look at the code on the Generic Flippable Coin (#715) you will see slightly different code which checks whether the player is holding the coin before she can flip it. Aside from that, and a few other minor tweaks, you have a working flippable coin. If you would like to let other people create children of your coin:

@chmod coin +f

This will make your object fertile. Now there is only one problem: coin.state. Because this property has its c flag set (@show coin.state), when someone creates a child of the coin, they will also own the child.state property. This all sounds right and proper except that when anyone does flip child they will get a permissions error. This is because the verb child:flip is owned by you, and when a verb executes, it does so using the permissions of its programmer and you (the programmer) don't have permission to change the value of a property (child.state) which is owned by someone else. In order to fix this we do:

@chmod coin.state -c

Now when people creates children of coin, the owner of coin will own the child.state property and the flip verb will work properly.

Please Note: If you make an object fertile and other people create children of it, and if you then later recycle the parent object, everyone's child of that parent will stop working. Before you @recycle a fertile object, please check @kids ObjectName and try to contact the owners of those child objects to let them know.

While you own your fertile object and have the right to dispose of them as you please, it is considered good manners to give people time to cope with the consequences. Alternative include giving the fertile object to a wizard or other player (you will need a wizard's assistance to do this). By doing so you can retain credit for your work but will no longer own the object.

If you are recycling objects in order to free up quota for another project, and some of these are fertile objects which people are using as parents, you should contact a wizard about getting your quota increased. Creating useful objects and code is something that should be rewarded!

Step 3

Ok, now you have a working object that people can create kids of. The only problem is that every single child will look and act the same as its parent. In order to make this a high quality generic object (as opposed to just being fertile) we need to make a few changes which will allow people to customize their children with minimal effort.

What we want to do is to allow people to customize the message displayed when their coin is flipped. We will do this by adding a message to the coin, just like the other messages that the coin inherited from $thing. First we add the property:

@prop coin.flip_msg "%N % %t into the
air."

Notice that we used "_msg" on the end of the property name. This will allow people to reset the flip message using: @flip child is "....". We also went ahead and set a default message value, the same as the string used by $you:say_action() in the flip verb. Now we just have to modify the flip verb so that it uses this message. We change the code in the flip verb to:

$you:say_action(this.flip_msg);
this.state = random(2)-1;

Now owners of children of coin can reset the child.flip_msg to reflect the behavior of flipping any sort of random binary state device, whether it's an erratically functioning light switch or a pancake.

Is this the only way to code a flippable coin? Absolutely not. Is it the best way? Only if it fits your specific needs and constraints, which is true of any programming design decisions. There is almost always yet another way to do whatever it is you are trying to do with MOO code. The important thing is to learn the different techniques and when and where to apply them, and to not forget that MOO programming is supposed to be fun.




2. Objects, Properties, Verbs and Flags

To understand how to program in MOO you have to understand how things are organized. Nearly everything on the MOO is an object, your character, your room, and even mailing lists. An object is a unit consisting of a set of properties and verbs. Each object is uniquely identified by its object number. Some important object numbers are: #0, the System Object, #1, the Root Object, #2, the Archwizard, #3, the Generic Room, etc.

There are also three special object numbers which do not actually refer to objects: #-1 ($nothing), #-2 ($ambiguous_match) and #-3 ($failed_match).

Some properties are built in and are found on every object, others are inherited from the object's parent and still others are defined on the object itself. Some important builtin properties include: name, location, parent and owner.

Inherited properties are those defined on an object's parent. When the child object is created it inherits the property from the parent and the value of that property on the parent. An example is the take_succeeded_msg prperty on $thing which has the value: "You take %t." Every child of $thing, when it is first created inherits the take_succeeded_msg property (among others) and the initial value of that property is the same as the value it has on its parent, $thing. This default value can be overwritten by setting the child's property to some other value (usually using @set). You can reset the property to its original inherited value ("clear" it) by using:

@clearproperty /

You can add properties to your own objects using:

@property .

Things to keep in mind when naming your properties: an object cannot have two properties with the same name. This includes the inherited properties. If you try to add a property name that is already defined on the object you will get an error message. Also, property names cannot have periods (.) in them, and shouldn't have quote marks, asterisks, or minus signs in them. In fact, it's a good idea to limit property names to letters, numbers and underscores.

The default initial value for properties is the integer 0. If the property is more normally going to hold a string, you would generally set the initial value to "", and if the property is supposed to hold a list, you would set it to {}.

Formore information on adding, deleting and setting properties on objects see the help topics: @property, @rmproperty and @set.

3. Verb Types and Arguments

In addition to properties, objects also have verbs. Verbs are the executable code associated with objects and which define how the object behaves. There are two ways in which verbs can get invoked: on the command line or from another verb. Some people distinguish between the two by calling the verbs that can only be used from the commandline, 'commands' and calling all the others 'verbs'.

Let's start with the command line. To invoke a verb from the command line you type the name of the verb and sometimes follow it with a set of words which are the arguments.

4. Data Types, Variables and Control Structures

5. A Simple Example Verb

6. Tools For Your Toolbox




Back to the RuthMOO home page.

This page maintained by S. J. Herdman.