How To Make A Virtual Meditation Garden

or: Oh, Hell, It's Another LambdaMOO Programming Tutorial

So you've got an account on a LambdaMOO, and you have an area that's been given to you to develop that you bend to your devious ends, and you have some ideas for what you want to do with it. BUT HOW?

In this tutorial I'll take you through some basic steps that will allow you to create a new area, create objects there, and set up some basic activities for people.

Creating the Garden

Let's suppose you want to create a meditation garden.

The first thing to do is figure out where you want it to be. It will have to adjoin one of the areas you already own. So let's say you've been assigned an apartment and you want the garden to be west of the a room named "the dining room" whose description is currently:

This is the dining room. A colorful quilt is hanging on the north wall. There's a door to the north which appears to be locked.
--> Go [e]ast to get to the living room or try to go [n]orth.
At this point you can create a place for you to build your garden by typing the following command:
@dig west,w|east,e to "the meditation garden"
Now let's go over what you just did and what each part meant. After you type the command, something like the following should appear on your screen:
the meditation garden (#1114) created.
Exit from jwgh's dining room (#374) to the meditation garden (#1114) via {"west", "w"} created with id #1115.
Exit from the meditation garden (#1114) to jwgh's dining room (#374) via {"east", "e"} created with id #1116.
This tells you that the command was successful and the object numbers of the items you just created. (The new location, its entrance, and its exit are all different objects.)

To verify that this worked, you can try going west to see if it takes you to the garden, then east to see if it takes you back out. It should.

Describing the Garden

If you go west into the meditation garden at this point, all you'll see is something like:

the meditation garden
You see nothing special.
That's no good, though. Hopefully you want your meditation garden to be very special! So describe it using the '@describe' command. First, enter the garden (if you're not there already); then type:
@describe here as "You've entered a meditation garden. A stream flows to a koi pond, making a pleasant burbling sound. It is so peaceful it is all over your screen!"
(Since you know the object number of the garden, you could also have used "@describe #objnum as "..."", using the object number instead of "here".)

If you try this command and then look (or leave and reenter the room) the new description should appear. Good! There's still one thing missing, though: the current description doesn't say how to leave the garden.

Often, rooms will have a separate line in the description that says what the various exits are from the location. But how to do multiple-line descriptions?

One way is to use the editor, but I don't actually use the editor much so I can't really say how that works--sorry! The other method is to use the following command (which again needs to be executed while you're actually in the location whose description you want to change):

@set here.description to {"You've entered a meditation garden. A stream flows to a koi pond, making a pleasant burbling sound. It is so peaceful it is all over your screen!", "--> To leave the garden, go [e]ast."}

Now if you look you should see:

You've entered a meditation garden. A stream flows to a koi pond, making a pleasant burbling sound. It is so peaceful it is all over your screen!
--> To leave the garden, go [e]ast.

Things to notice here:

Now try it out and see if it works!

If you go back east to the kitchen, you'll notice that the description there says nothing about the fact that you can now get to the garden from there. You can use the @set here.description command to fix that now. (here refers to the location you're in, and .description to the description property of the room. We'll be talking about other properties later.)

Describing exits

It might be nice if, when someone in your kitchen does a 'look west', they get a little message saying that the garden's in that direction. (If you try this now, you'll get that same old 'You see nothing special.' message.) This can be done using:

@describe west as "Through the door to the west you see a lovely meditation garden."

Describing what happens when someone enters or leaves the garden

Perhaps you would like to make it so that when people leave the kitchen for the garden a special message gets sent to them. There are several properties of exits that can be used for this purpose. Check out the following commands:

@set west.leave_msg to "You leave your worldly cares behind and enter the meditation garden."

@set west.oleave_msg to "leaves worldly cares behind and enters the meditation garden."

@set west.arrive_msg to "You arrive ready for some EXTREME MEDITATION, BAYBEE!"

@set west.oarrive_msg to "arrives, looking ready for some EXTREME MEDITATION!

If you now go west into the garden, you'll see:

You leave your worldly cares behind and enter the meditation garden.
You've entered a meditation garden. A stream flows to a koi pond, making a pleasant burbling sound. It is so peaceful it is all over your screen!
--> To leave the garden, go [e]ast.
You arrive ready for some EXTREME MEDITATION, BAYBEE!

Note that the message in the .leave_msg property appeared before you arrived in the garden, then the description of the garden appeared, then the .arrive_msg message came last.

Other people in the kitchen will see the .oleave_msg message:

[YourNameHere] leaves worldly cares behind and enters the meditation garden.
when you leave. Meanwhile, people already in the garden will see the .oarrive_msg message:
[YourNameHere] arrives, looking ready for some EXTREME MEDITATION!
upon your arrival.

Things to notice here:

Making A Statue For Your Garden

Perhaps you want a statue of Buddha in your garden. (One approach would be to simply add it to the garden's description ['in the center of the garden is a statue of Buddha'], but then other players wouldn't be able to interact with it.)

You can create a Buddha statue using the following command:

@create $thing called "statue of Buddha":"Buddha statue",Buddha,statue
I'll break this down: If you look at the statue right now you'll just get the standard "You see nothing special"-type message. You can give it a description using the @describe command:
@describe statue as "This is a large, golden statue of Buddha. It smiles at you benignly."
As with rooms, you can use "@set statue.description to {"line 1", "line 2", "line 3"}" to create a multiple-line description of the statue.

Locking The Statue Down

So you've dropped the statue (or if you haven't do so now) and it's in the garden where you want it to be. What's to keep someone from walking in and grabbing it? Nothing, that's what! So perhaps you should change that.

You'll probably want to do one of two things:

  1. Make it so that only you can pick the statue up and carry it around. In this case, the appropriate command is:
    @lock statue with me
  2. Make it so that nobody can pick the statue up, yourself included. In this case, use:
    @lock statue with here

Once you've done either if these, if someone tries to pick the statue up they will get the informative but bland message, "You can't pick that up." (Other people in the room won't see anything.)

You can change this state of affairs using the @set command to change the take_failed_msg and .otake_failed_msg properties of the statue:

@set statue.take_failed_msg to "Keerist! This thing must be made out of solid gold! You almost herniate yourself trying to pick it up. Finally you give up."

@set statue.otake_failed_msg to "grabs the statue of Buddha and tries to pick it up, but after some grunting gives up."

Rubbing The Statue's Belly

So now you've got an immobile statue. It decorates the place nicely, sure, but wouldn't it be nice if you could do other things, like maybe rub its belly for good luck? OF COURSE IT WOULD!

Doing this requires a little programming. Not all players on a MUD have permission to do this, so you might have to check with your friendly neighborhood wizard to make sure you are Allowed.

However, assuming that that's not a problem, here's how you'd do it:

  1. Pick the name of the verb you want to use. In this case it's rub.
  2. Figure out how you want the verb to work. The simplest form is verb object ("kick robot" or "kiss hulk" or "rub statue"); that's what I'll use in this example. (There will be more a complicated example later.) In this case I want people to "rub statue".
  3. Use the '@verb' command to make the verb:
    @verb statue:rub this none none
    "statue:rub" means that the verb, hug, is attached to the statue object.

    this none none ...I'll discuss that later. Suffice it to say for now that all simple verbs of the verb object type will have "this none none" here.

  4. At this point you've got the rub verb but it doesn't do anything yet. To get it to do something you need to program it. So type
    @program statue:rub
  5. You're now put into programming mode; you won't be able to issue any commands until you either finish programming or you type "@abort". Type (or, better, copy and paste) the following program in:
    player:tell("You reverently rub the statue's belly. it giggles!");
    player.location:announce(player.name + " rubs the statue of Buddha's belly. The statue giggles!");
    .
    Let's look at this a little closer.
If all's gone well and you haven't gotten any errors, log in as a guest and see what happens when you rub the Buddha's belly.

If you want to later change how the ":rub" verb on the statue object works, you can simply issue the "@program statue:rub" command again--it will overwrite the previous program.

If you want to see how a particular verb currently is programmed, you can do so using the @list command: "@list statue:rub" gives you a listing of the program.

If you want to see all the properties and verbs you have set up on your statue, you can use the @dump verb: "@dump statue". Sometimes you can also @dump objects belonging to other people; this can be a useful way to figure out what methods other people have used to get their objects to work.

If you change your mind and decide you don't want people indiscriminately rubbing your statue's belly, you can get rid of the verb by typing:

@rmverb statue:rub

Meditating Through Programming: How To Increase Stress In Your Life

At this point people can meditate in your garden (just as they can anywhere else), but it's a strictly do-it-yourself affair--they have to type ":meditates on the essence of cherry pez while chanting 'kai-bo' over and over" or whatever. Since this is a special place for meditation, maybe you want to take some of the work out of the process for your visitors. Of course, this means extra work for you, but nobody said the path to enlightenment was easy.

Using what you already know, you could set up a new 'meditate' verb on the statue so people would type 'meditate statue' with whatever results you desired. The only problem with this approach is that it doesn't really make sense; what would "meditate statue" mean, exactly? (Why would anyone think to do it?)

Fortunately, there are other options. Verbs can be attached to pretty much anything, and that includes not only items like statues that you create but locations (and even players).

Moreover, when you type a verb ("look" for instance) the LambdaMOO software will automatically check to see if the verb is defined on the room you're in. This is convenient, because it means that if you define a verb (like "meditate") on the garden object it can be invoked without specifically mentioning the room (so players would only have to type "meditate" instead of "meditate here" or something).

So defining a meditate verb on the garden location is the way to go. The next question is, how do you want the verb to work? In the abstract, there are many different kinds of verb constructions that can be useful, from "sit on rock" to "throw Spot against wall" to "discard trash" to "sleep".

Some consideration will show that these verb constructions' structures in general have up to four parts. The verb comes first, then the direct object ("Spot" or "trash" in the examples) if any, then the preposition ("on" and "against" in the examples), then the indirect object ("rock" or "wall").

This structure is given as part of the verb decleration. You may recall that when we declared the "rub" verb it was declared this way:

@verb statue:rub this none none
The "this none none" describes the structure of the verb. In particular, The initial "this" says that the direct object must be the object itself (the statue in this case), there should be no preposition at all, and likewise there should be no indirect object. So when this verb is called it must be done as so: "rub statue" (and the only variation allowed is that another method of referring to the statue, such as its object number or full name, could be used).

Other structures are possible. If for instance you had declared another verb, hit, on the statue as follows: "hit any with this" it would have meant that the direct object could be anything, the preposition would have to be with, and the indirect object would have to be the object itself. So with that decleration you could type "hit spot with statue" (although what would actually happen if someone typed that would depend on the program you associated with the hit verb).

Returning to the garden, what structure do we want the meditate verb to have? You could set it up different ways, but there are two types of meditation I can think of off the top of my head:

Given those examples, the following decleration should do it (issue it while actually in the garden):
@verb here:meditate none any any

This says that the meditate verb won't take a direct object, but will accept any preposition followed by any indirect object. This is far more general than we actually want (it allows things like 'meditate around froot loops' and 'meditate through Lincoln Tunnel', neither of which makes much sense), but we can take care of that in the actual program.

On to the program.

This program will be a bit more complicated than the last one, and will take a little more thought.

The first thing that the program has to figure out is if the player typed in a preposition or not. (If they didn't, they must be using the standalone 'meditate' version of the verb. If they did, we can then make sure that they typed 'meditate on...' or 'meditate about...' and go from there.) Fortunately, there's a built-in word, prepstr, which will hold the preposition the player used if they used one, and it can be used to test whether or not a preposition was used at all:

if(prepstr)
 /* They used a preposition! */
else
 /* No preposition; they must have just typed 'meditate' */
endif
.

The lines beginning in "/*" and ending in "*/" are comments. They have no effect on what the program actually does. However, they allow you to make notes on what a program is supposed to do, and so they can be helpful in organizing your thoughts while you're writing a program. (They can also help you figure out what different parts of the program are supposed to do if you revise your program later, or if you show your program to someone else.)

if(prepstr) tests to see if prepstr contains anything. If it does, it contains the preposition in the command the user typed, and whatever commands come between the if(...) and else lines are executed; if it doesn't, then the user's command didn't include a preposition and any commands between else and endif are executed.

Currently there aren't any commands in either 'block' (there are only comments). So let's attack one of them. The second is simpler, so let's start there. What should happen if someone just types 'meditate'? Well, perhaps something as simple as:

 player:tell("You meditate. Yay!");
 player.location:announce(player.name + " assumes the lotus position and starts meditating.");

This is very similar to the statue:rub code: If Xibo were to type the command while the above code was in effect, he would see 'You meditate. Yay!' while everyone else in the room would see 'Xibo assumes the lotus position and starts meditating.' That seems about right, so let's plug this code into the appropriate block. The program now goes:

if(prepstr)
 /* They used a preposition! */
else
 /* No preposition; they must have just typed 'meditate' */
 player:tell("You meditate. Yay!");
 player.location:announce(player.name + " assumes the lotus position and starts meditating.");
endif
.

At this point, you might want to type in @program here:meditate and paste in the above code. Then type meditate so you can verify that this is working the way we want so far. (If you type meditate on Bach or something like that nothing will happen at this point, because we haven't done that part of the program yet.)

So, cool, that part of the program works. What now?

Well, if someone has typed in a preposition, the next thing to do is make sure that it was either 'on' or 'about'. The following does that:

 if((prepstr == "on") || (prepstr == "about"))
  /* The preposition was either 'on' or 'about'. */
 else
  /* The preposition was neither 'on' nor 'about'. */
 endif

As with the last time I used the if/else/endif sequence, I'm telling the LambdaMOO software to do one thing if a specific set of conditions holds and something else if not. The conditions are set out in the 'if' line. Let's look at it again:

 if((prepstr == "on") || (prepstr == "about"))

One way to look at this is to divide it into two parts, (prepstr == "on") and (prepstr == "about"), which are separated by ||:

So a partial English translation of what's going on here might be, "If the preposition was 'on', or if it was 'about', then do the stuff between the if and else lines; otherwise, do the stuff between the else and endif lines.

Common pitfalls:

So with all that understood, let's plug this bit of code into the appropriate part of the program and see where we are:

if(prepstr)
 /* They used a preposition! */
 if((prepstr == "on") || (prepstr == "about"))
  /* The preposition was either 'on' or 'about'. */
 else
  /* The preposition was neither 'on' nor 'about'. */
 endif
else
 /* No preposition; they must have just typed 'meditate' */
 player:tell("You meditate. Yay!");
 player.location:announce(player.name + " assumes the lotus position and starts meditating.");
endif
.
(The new bits of code are in boldface.)

The program has become a bit confusing already. We've got an if/else/endif block inside another if/else/endif block! It's not obvious which pieces of code happen under what circumstances.

I've done two things to make it less confusing. The first is that I've left the comments in, so if you want to know under what what circumstances a particular piece of code is executed under, you can just work your way up the program until you hit a comment.

The other is that everything within a particular 'block' (between an if and else or else and endif) is indented. If you look, you'll see that the commands within the 'innermost' if/else/endif are indented one space more than the commands in the 'outermost' if/else/endif, which in turn are indented one space more than the commands and comments that aren't in any conditional at all. This should make it a little clearer, when examining a particular line, to determine which block it is a part of.

Let's finish writing the program. At this point there are two pieces left to be written; the piece where someone has typed 'meditate on [something]' or 'meditate about [something]', and the piece where the command used a preposition other than 'on' or 'about'. Let's take the first piece first.

It would be useful to know what the player was meditating about, or in the terms of LambdaMOO what inderect object followed the preposition. Fortunately, there's a built-in expression that gives you. Just as prepstr gave you the preposition, iobjstr gives you the indirect object. (Similarly, dobjstr would give you the direct object, though that's not relevant for this particular program.)

So one approach at this point would be to code something like:

  /* The preposition was either 'on' or 'about'. */
  player:tell("Thoughts of " + iobjstr + " fill your mind.");
  player.location:announce(player.name + " assumes the lotus position and starts meditating.");

With this code in effect, if jwgh typed 'meditate on kibology' he would get sent the message 'Thoughts of kibology fill your mind.' while everyone else in the room would see 'jwgh assumes the lotus position and starts meditating.'.

That takes care of that part of the program. The only remaining case is when the player used a preposition other than 'of' or 'about'. In this case the program should tell the player that it doesn't know what the player is talking about:

  /* The preposition was neither 'on' nor 'about'. */
  player:tell("What kinda weirdo meditation are you trying to DO, mang?");

With this code, someone typing 'meditate below fish' will be told, 'What kinda weirdo meditation are you trying to DO, mang?'. (Other people in the room won't see anything.)

That takes care of all of the possibilities: Either the player used a preposition or didn't, and if it did then either the preposition was one of the right ones or it wasn't. So now I'll assemble all of the bits of the program and display it in all its glory (again with the new pieces of code in boldface):

if(prepstr)
 /* They used a preposition! */
 if((prepstr == "on") || (prepstr == "about"))
  /* The preposition was either 'on' or 'about'. */
  player:tell("Thoughts of " + iobjstr + " fill your mind.");
  player.location:announce(player.name + " assumes the lotus position and starts meditating.");
 else
  /* The preposition was neither 'on' nor 'about'. */
  player:tell("What kinda weirdo meditation are you trying to DO, mang?");
 endif
else
 /* No preposition; they must have just typed 'meditate' */
 player:tell("You meditate. Yay!");
 player.location:announce(player.name + " assumes the lotus position and starts meditating.");
endif
.

Go through it and see if you understand what all the different bits do. Then use the "@program here:meditate" command, paste it in, and try it out.


The Enb

You've now gone through my tutorial. At this point I've discussed the following topics: Hopefully you will find this all useful. Some of these topics are explored in more depth in other tutorials. Here are some I would recommend:

More Tutorials

Official Information