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.
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.At this point you can create a place for you to build your garden by typing the following command:
--> Go [e]ast to get to the living room or try to go [n]orth.
@dig west,w|east,e to "the meditation garden"Now let's go over what you just did and what each part meant.
You can have multiple aliases for an exit or entrance. For instance, you might also want players to be able to type "back" or "b" (as well as "east" or "e") to return to the kitchen from the garden. In that case, you'd use "west,w|east,e,back,b". The LambdaMOO software will interpret everything before the "|" as an entrance to the new location and everything after it as names for the exit back to the dining room.
the meditation garden (#1114) created.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.)
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.
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.
If you go west into the meditation garden at this point, all you'll see is something like:
the meditation gardenThat'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:
You see nothing special.
@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.)
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."
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:
You can create a Buddha statue using the following command:
@create $thing called "statue of Buddha":"Buddha statue",Buddha,statueI'll break this down:
There are other generic objects you can base things you create on, such as $container (an object you can put stuff in and open and close). You may also be able to base your objects on some objects created by other people, but that's a topic which goes beyond the intended scope of this tutorial.
There are some automatic aliases built in--if the main name consists of multiple words (as statue of Buddha does) you can refer to the object by the first word, or first two words, and so on. So even if the "statue of Buddha" had no aliases it could still be referred to as "statue" or "statue of". (Try typing "drop statue of" to verify this.)
@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.
You'll probably want to do one of two things:
@lock statue with me
@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."
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:
@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.
@program statue:rub
player:tell("You reverently rub the statue's belly. it giggles!");Let's look at this a little closer.
player.location:announce(player.name + " rubs the statue of Buddha's belly. The statue giggles!");
.
As you might guess, this results in the player (the person who typed rub statue) getting sent the message "You reverently rub the statue's belly. It giggles!".
In any LambdaMOO program, player identifies the player who invoked the verb (the person who typed rub statue in this case).
Likewise, tell is a verb which can be performed on a player to send him or her a message. (The stuff in the parentheses () is what gets sent.)
An important note: The semicolon (;) at the end of the line indicates the end of the command. Leaving it off is a common error which will generally cause your program to be rejected by the LambdaMOO software.
If Beable rubs the statue's belly when the above is in effect, the message "Beable rubs the statue of Buddha's belly. The statue giggles!" will be displayed to everyone in the room (except Beable). To break things down a bit more:
Every player has a .location property that says where they are.
The "announce" verb sends a message to everyone at that location (other than the player who sent the command). As before, the stuff in the parentheses is what gets sent to them.
player.name contains the name of the player (notice it's another property that all players have), so the message starts with the player's name, which is then followed by the message in quotes. (Notice the space after the quote [" rubs the statue...]. If the space wasn't there, the message that got sent would be something like Kiborubs the statue... with no separation between the player's name and the rest of the message.)
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
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 noneThe "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:
@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:
if((prepstr == "on") || (prepstr == "about") <-- THIS IS WRONG!The problem here is that there are three left parentheses in the above (two before "prepstr == "on"" and one before "prepstr == "about"") but only two right parentheses. Not good!
My intent was to enclose the entire [...] || [...] sequence in a set of parentheses, but although I remembered to put in the extra opening parenthesis at the beginning I forgot the extra closing parenthesis at the end. Unfortunately, this simple mistake would have resulted in a program that didn't work. Beware of mistakes like this!
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)(The new bits of code are in boldface.)
/* 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 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.