===================================================== Unofficial MOO Programming Tutorial For Lambda Core 1.8.0p5 Copyright Notice: This document is copyright Craig Roberts, aka Wildcard. It may be freely distributed and copied as long as this copyright notice is left unchanged. This document may also be translated into any language as long as this copyright notice is left unchanged. Ammendments may be made to this document, as long as they are indicated as changes, and this copyright notice is left unammended. (c) Craig Roberts 1997, 1998 ===================================================== Contents: ========= A) An Introduction Who the hell am I? What the hell is a MOO? What the hell is MOO programming? What will this document cover? What level is this document for? Is this document based on any MOO? Where can I get more information? B) Introduction to MOO Coding Parents and Children Properties Permissions (Part 1) C) Starting to Code Starting to write a verb Write a Simple Verb Arguments and Default Values Assigning and Comparing Values Returning a Specific Value Selection and Interation If...Else For and While Loops D) Useful MOO verbs and how to use them. Introduction Things with Strings Comparing Strings Tostr Matching Players Adding Strings Together Indexing Strings Splitting Strings into Words Finding the Length of a String Encrypting Strings Replacing Words in a string Reading a String of Input from a Player Reversing a String Things with Lists Adding Things To Lists Removing Things From Lists Finding If Something is in a List Indexing ListsFinding the Length of a List Picking Random Elements From a List Displaying a List Reversing a List Reading a List of Input Things with Objects Moving Objects Checking the parents of objects Changing the Parent of an object Listing the Verbs on an object Listing the Properties on an object Checking a Property Exists Checking a verb Exists Checking is a CALLABLE verb exists Miscellaneous Verb Stuff ------------------------ Suspending a Verb Calling a verb that starts with an '@' Returning a list of all players Passing from One verb to another Permissions - Security Stuff ---------------------------- Disclaimer Bit Verb Permissions That's about it. ----------------
I am a 20 year old student from North Wales in the UK. I have been using MOO for just over a year. You can find me on the following MOO's which I like:
MOO Address Port ---------------------------------------------- Mindscape mindscape.ml.org 2112 <- My own MOO. NecroMOO necro.mcc.ac.uk 7777 HotelMOO hotel.cmoo.com 8888 JungleMOO hrclinux.wmin.ac.uk 7777 ParkMOO parkmoo.dds.nl 7777
As well as coding in MOO, I am also gaining experience in coding in several other languages - C, Pascal, 8088 Assembler and Java (Although not to an extremely high degree). At the moment I am studying a HND in Media Technology.
So, enough about me, on with the manual.....
MOO can stand for many things. I always think of it as a "Multi User Object Orientated" environment. A "Text based virtual reality." People from all over the world can connect to a MOO via Telnet or someother more dedicated "MU*" client.
When connected, the person (Hereon referred to as Player) can interact with people also connected. On most MOO's players can automatically build objects such as rooms. But, it is also possible, thanks to the MOO server, to write new programs (Hereon referred to as Verbs) that can modify the Environment.
Everything that runs on a MOO is a verb. There are many other "help" files which go into introducing the basics of MOO, so I won't go on too much here.
In basic terms, MOO Programming is the creation of verbs that can affect the Virtual Reality. Players, normally, can't program straight away. You need what is known as a "Programmers Bit" which you need to ask a Wizard for.
When you become a Programmer, you will have access to more commands, and you can start to influence the environment with your own code. For many people, myself included, this is the fun part of MOO. Thanks to the brilliant server by Pavel Curtis, MOO programming is extremely easy to learn the basics of.
As a programmer/wizard myself, I find many people asking questions on how to start writing MOO code. As MOO is the first time that many of them have tried to code, the Official Manual by Pavel Curtis is a bit daunting. This document hopes to cover levels of programming for Beginners. It will not cover everything that you can do in MOO, as this would take thousands of pages, however, I hope it will be beneficial to people new to programming,
This document will contain examples, rules and hints on writing verbs. It is not designed as a replacement for Pavel Curtis' manual. More of a supplement.
This document will also cover "In DB" stuff. I.E. Not just what the server contains, but what comes with the CoreDB too. Therefore, if your MOO does not have a particular utility - sorry, it's not my fault. However, if you are a player on Mindscape (mindscape.ml.org 2112) then all of this document should work.
This document is written with the beginner / intermediate programmer in mind. So, there are other ways of writing the code shown here. There always will be different ways of doing things. In other words, I want to help people get into coding, not put them off by using complex coding techniques (Plus, putting this here stops me being flamed by other coders ;) )
As is mentioned above, this document is designed with the general database in mind, I.E. The one that most people have. (Lambda). However as is also mentioned, I may sometimes use verbs or utilities that are not found on other MOO's. But, most of the information is generic.
What? This isn't enough? Well, as I mentioned before, this document is a sort of supplement for the official LambdaMOO programming manual by Pavel Curtis. So, once you have digested this document, I would suggest downloading a copy. Most MOO web pages seem to have a copy or link these days. Also, there are many MOO programming tutorials out there. A quick search will return loads.
Well done. You got past the legalese, and through the introduction. So, let's start by going into some detail about what MOO code is, how it works, and what kinda stuff we can do with it.
MOO code is an object orientated programming language in its own right. Object Orientated means that it is based on Parent Classes and Properties. The "children" of an object can run and access verbs and properties found on the objects which make up their parents. So, if you have a child of #1 (which ALL objects are) then you can run verbs written on #1.
Example:
All players are CHILDREN of #6 (generic player). The generic player has a verb called "@join" This verb is not found on all players, but is found on the parent.
---------- --------------- ----- |PROPERTIES|---| #6 |---|VERBS| ---------- --------------- ----- | | | | --------------- | V | Player | V ---------------
Whatever verbs and properties are stored on a parent, are inherited by it's children. Although the child does not own the verb, it can (usually) call or use them. So, when a verb or property is changed on a parent, all the children experience the same change.
This stops Wizards having to re-write loads of verbs just for new players. The same rule is applied to ALL parents.
Properties are variables which are stored on an object. For example, the NAME property on the player. Properties are usually owned by the owner of the child object. However, this is not always the case - Example, the .password property is owed by the ArchWizard. This is to stop players directly changing passwords or trying to hack players passwords.
The permissions of props are as follows (More information is given later in the manual)
R - Readable by the General MOO Populace W - Writeable by the General MOO Populace C - Change the Ownership of the Prop to the owner of the child (Normally set)
Properties are ALWAYS indicated by a period. Eg, #object.property
They can also come in various types:
Integer - A WHOLE number - 1,2,3,4,5 etc Floating Point - A fractional number - 1.00, 1.02, 4.23 etc String - A collection of Alpha Numeric Values "This is 1 string" List - A collection of all or one of these - {"List". 1, 1.23} Boolean - An integer 1 or 0. Anything above 1 acts as if it was 1
Properties can also be manipulated via Verbs. This is an important part of MOO coding, as it allows people to store things, and for the owners of the children to change descriptions etc.
This is an introduction to Permissions. I will go more into depth with this later in the document. Verbs run with the permissions of the person who owns them, this is usually the person who initially created and wrote the verb
However, if you are a non-wizard (Which, I'll assume you are) then this is important to know. If you write a verb that changes a property, and then allow someone to create a child of it, then you MUST own the property on the child. You can not change stuff that you do not own. This is done in the following way:
When adding the property type this:
@prop object.property
The 'C' bit tells the server to change the ownership of the property to the owner of the new child. When you use the -c switch, you tell the server to make YOU the owner of the property on all children.
Otherwise, the ~C' bit is automatically set to 1. So, the owner of the child becomes the owner of the property.
Let's assume there is an object called #3424 with a parent #321 with a property called "names".
If the property is +c, then the owner of #3424 is the owner of the property on #3424.
If we were to do @show object:property on the #3424.names, we would see this:
#3424.names Owner: Wildcard Permissions: cr Value: {"Wildcard"}
Now, assume the "Slacker" owns the parent, and he has made the property "-c" when we use @show now, we see this:
#3424.names Owner: Slacker Permissions: r Value: {"Wildcard"}
I can no longer change the property, because Slacker owns it.
As I said above - Perms are a BIG part of MOO coding, especially if you are writing Wizard verbs. You need to understand these to stop players hacking their way around your verbs.
Firstly you need to create the object you want to put the verb on. Let's just write one on you for now. You need to create the verb, this is done by using a provided verb called '@verb'
@verb me:
When you have done this, the MOO should replay with a response such as:
Verb Added (0)
Now, we need to edit this verb. To do this you need to move intot he editor. Luckily, there is a verb already available called @edit. You may have used this already to edit your description etc. Well, to edit your verb use the same command:
@edit me:
This will move you into the editor. Type 'look' for a detailed list of the commands you can use here. The most important ones at this stage are 'say', 'compile', 'quit', 'list' and 'del'.
You input text into the editor by using the Say verb. Just like you would if you were just talking to someone.
Compile will tell the server that you want it to make the verb executable (if there's no errors)
Quit will move you out of the editor
List will list what you have currently typed.
And Del will delete either a specified line, or the current line.
Okay, lets take the verb that you have just added, and make it do something. So, when you are in the editor, type the following:
Say player:tell("Greetings, this is your first verb! Well Done!");
Like 'C' you MUST have the ';' at the end of the line. Otherwise you'll get an error.
When you finally get the message saying "Compiled" you can quit.
Now you can run the verb, just like any other. You should see:
Greetings, this is your first verb! Well Done!
So, how does this work? Well, you are calling a verb on the generic player called 'tell' most of the stuff you write will call some verbs already written. This is good as it means you don't have to re-write things all the time. So, this verb displays the string on the screen of the object it is called on.
Note: Callable verbs have the 'x' bit set. To do this, use @chmod (Type help @chmod for details)
When a verb is run, you sometimes need to give it something to work with. For example, '@join~ requires you to give the name of a player you want to join. This information you give it is called Arguments.
You can specify the arguments that you want your verb to run with using the '@args' command. Here is a list of most of the valid arguments:
Dobjstr Prepstr Iobjstr None none none - No arguments. Just type the verb name. This none none - Verb object e.g. 'Open safe' **This none This - These verbs can only be called. They can't run from the command line Any none none - Verb anything e.g. @joinAny from this - verb anything from object Etc.
When a player types a command for the MOO to parse, the MOO follows certain procedures. Here is the order in which the server looks for the verb to run:
Player Room Features Direct Object Indirect Object
To specify the arguements, use @args object:verb arguments. Any arguments not typed default to NONE
The verb also contains some default values, this is useful for manipulating information. The values are shown below:
Player - The person who ran the verb Caller - Normally the person who ran the verb, or owns the verb calling this verb. Argstr - Anything typed AFTER the verb name. Args - The argstr split into seperate words Dobjstr - The word(s) to the LEFT of the preposition Prepstr - The words to the RIGHT of the Dobjstr (at/all/from/etc) Iobjstr - Anything to the right of the Prepstr Verb - Whatever is typed to run the verb This - The object the verb was found on Iobj - Indirect Object Dobj - Direct Object
In MOO it is essential to assign values to variables. Whether these variables are properties, or just stored in code. The assignment of these values is easy.
"Variable = Value"
So, if we were storing a value of 3 in a variable called Number we would use the following line:
Number = 3; - Remember the ';'
It's just as easy to assign this value to a property (As long as the property exists)
Object.property = value;
So, now that we have assigned this value to a variable, how do we compare? Below is a list of operands which will compare values:
'==' - Checks that the values are equal '!=' - Checks that the values are NOT equal '> ' - Checks that the left value is greater than the right. '< ' - Checks that the left value is less than the right.
Example 1 == 1; returns 1 (It's true) 2 != 2; returns 0 (It's false) 4 > 2; returns 1 (It's true) 3 < 4; returns 0 (It's false)
Sometimes in MOO we need to return a value, maybe the verb we have written has been called by another verb. For example, the player:title() verb is called by the look verb. In the title verb we return a value for the look.
Let's assume that we have written a small verb that will return a number:
return 3; - This will return the number 3.
As we progress through this tutorial you will find return being used more and more. But, for now, as long as you understand that it returns a value to a calling verb, then you're doing well.
Selection? What the hells that I hear you cry. Well, its choosing. Telling the verb to do one thing is a certain thing is true, or another thing if it is false. To do this, we use a function call 'if..else' Basically, the If statement checks that a condition is true.
So, if we were to have 'if (2 < 3)' this would return true, so it would do everything BELOW the if statement, until it came to an 'else' or an 'endif'
Example:
if (2 == 2)
Player:tell ("Yep, 2 is equal to 2.");
Else
Player:tell ("Something's wrong. 2 isn't equal to 2!");
Endif
Note that the if, else and endif statements do NOT have ';' at the end.
The if statement is used a lot, especially in Wizard Verbs, this
statement is present in many of them:
If (player.wizard != 1)
Player:tell ("You aint a wizard. Clear off!");
Return;
Endif
So, if the person running this verb isn't a wizard, it returns nothing (return always ends the verb) and they can't run it.
If statements work by testing a value, if it is true, it returns a 1. So, rather than using 'if (player.wizard == 1), you can use 'if (player.wizard)'. It is also possible to check if something is NOT true. To do this, you use the '!' symbol.
If (!player.wizard)
This will return a 1 if the player is not a wizard, and a 0 if s/he is.
You can use IF to check if a value is equal to anything other than 0,
or an empty list, or an empty string.
'if (x != {})' - Check that X is not an Empty List
'if (x != "")' - Check that X is not an empty string.
You can also check if a string or list is empty or full, by using !x If x is empty, then the result is a 0 otherwise, the result is 1.
For loops are a method of iteration. That is, they loop, repeating the same thing, for as many times as is declared. A for loop will use a value determined from a property etc that can be changing at any point. For example:
The @who verb uses a FOR loop to collect the players names. The
reason being is that the number of players connected can change
constantly. So, if you want a verb to loop through a value, no matter
how much it changes, then use a for. Here's how you use one :
For who in (connected_players())
Player:tell(who.name);
Endfor
The above verb will loop for as many players are connected. The verb 'connected_players()' is built in to the server, so this returns a value. As the verb loops, the names of the players will be printed to the screen of whoever ran the verb.
A WHILE loop will run for a particular amount of time. A variable is set up BEFORE the loop begins. The loop then continues checking this until it fulfils the criteria coded.
Example:
X = 1;
While (x != 10)
Player:tell ("X is currently at a value of ", x);
X = X + 1;
Endwhile
So, this verb will tell the player the value of X at each repeat of the loop. It will then increment X by 1 each time. When X reaches 10, the loop quits.
In this chapter, we have learnt how MOO code works, what arguments you can use and what builtin values occur. You also now know about If..else, For and While. Now that you know how to write a verb, in the next chapter, I will simply give details of how different verbs do things.
This chapter is not meant to be a complete list of what verbs are available in MOO. It is basically a collection of the most useful verbs I have used, and what they can be used for. A lot of these verbs do not require lengthy descriptions, so in most cases, I will just give the name of the verb, how it works, and how you use it.
Most MOO's provide a series of utilities that can be used within verbs, the list of these verbs is too long to go into great detail about. So, if you need to do something that isn't mentioned here, ask a wizard or another programmer on your local MOO.
This section is devoted to various things you can do with strings.
There are 2 ways to compare strings. The easiest way is to simply use the "==" operand. However, this is not case sensitive, and so there is another way:
Strcmp - String Compare.
Example:
if (strcmp(string1, string2))
If the 2 strings are identical, then the strcmp will return a 1.
Tostr is a builtin function which will turn a given value in to a string. This is useful if you want to save something in a string property, or tell a person a value which your verb has reached. The verb is easy to use, yet is very powerful.
To use tostr, we simply call assign the result to a variable.
Example: X = tostr("This is a string ", 3 , " ");
This line will make the variable X equal to "This is a string 3 "
In most verbs, we need to be able to affect other players on the MOO. But, how can we tell that the object we are talking to is a player? Well, the $string_utils package contains a verb which interacts with the database of players, and can try to match any player to any string.
Example:
A verb with the arguments 'any none none'
Person = $string_utils:match_player(dobjstr);
The verb passes whatever was typed after the verb name, and before the preposition to the :match_player() verb. This verb then checks to see if that string can be matched to any player. If so, the player # number is assigned to 'Person'
With this variable now pointing to a valid player, we can tell that player whatever we want:
Person:tell ("See, I told you.!");
Although it is impossible to add strings and any other value together,it is entirely possible to add 2 or more strings together.
This is done as you would in maths:
X = "This" + " is " + " a " + " String ";
X is then assigned the value "This is a string."
Indexing is the name given to finding the position of any letter in a string. You can then use this value to select certain parts of the string.
Index() is a verb provided by the core server, and it works like this:
Index ("Foo Bar", "a");
This will return the number 6 as the first 'A' in the string is at the 6th character.
You can assign the value returned to a variable.
Another method of indexing is the use rindex() which is used in exactly the same way as index() except it returns the LAST instance.
So, rindex("Bah! This is a string", "i") will return "3"
Just like the command parser splits all input into separate words, called Args, it is possible to do this yourself in a verb. $string_utils comes with a verb called :words(). If you pass this verb a string, it will return a list of strings which contain individual words in the string.
Example X = $string_utils:words("This is a string.");
Will assign X with the value {"This", "is", "a", "string"}
By using []'s we can select one of these words from the list:
Z = X[3]; will return "a" as "a" is the 3rd element in the list.
The square brackets are using the same principle as INDEX.
This can come in extremely useful, in fact, it's one of the most common things I do ;)
The basic MOO server contains a builtin verb called 'length' with this it is possible to find the length of a string, or a list. When used with a string, it will return the number of words in the string.
Eg. X = Length("One two three");
This will make X become the value 3.
as is mentioned above, length can also be used for finding the length of lists. This is explained in the next chapter. Which is coincidently enough, about lists ;)
Lambda comes with a builtin UNIX style encryption verb called 'crypt'. This system is ONE WAY and so is practically impossible to hack. In fact, this is the same system that the password generator for players uses.
When you send a string to the Cryot verb, it uses a 2 letter key (called a SALT) to do the encryption. This key can either be chosen by the programmer, or the server itself can pick one.
When you want to check against the encrypted string, you CAN'T decrypt it. You must encrypt the string with the same key and THEN check.
Example:
X = crypt ("This String.") - This returns somthing like "GjFH.d8sf" Now if we want to compare an input to X we must encrypt the input.
Y = crypt ("This String.", x[1..2]);
This will encrypt the string with the first 2 letters of X (Which is the SALT) and so, in this case, there will be a match.
Crypt is not commonly used amongst non-wizard characters, but there are uses (For example - A Passworded Exit)
The server also comes with a builtin verb which will allow a
programmer to replace certain words with others. This verb is called
Strsub.
X = "This is a string. Foo Bah Baz!";
X = strsub (X, "Bah", "Bar");
This will result in X having the value "This is a string Foo Bar Baz" All incidents of "Bah" will have been replaced by "Bar".
It is necessary sometimes for a verb to accept input from the player running the verb. Maybe you've designed a configuration program for an object which will step the player through the config.
On the $command_utils there is a verb called Read() with this is it easy to ask the player to input information.
Example:
Player:tell ("Please input your name");
X = $command_utils:read();
X will now be assigned the value typed in by the player. Of course, you don't have to assign it to X, you can send it straight to the property.
The MOO also comes with an "interesting" verb in the DB. Found on the $string_utils object is a verb called reverse() and yes, it reverses the string.
Example:
X = "String";
player:tell ($string_utils:reverse(x));
Will result in the player being told: nirtS
Lists can be thought of as a collection of items, including other lists. However, there is a LOT that you can do with them.
There are several ways of adding things to lists. The easiest way is to just append the value to it. This is done using the '@' symbol.
Example:
X = {"Bah", "Herf"};
X = {@X, "Banarange"};
X is now equal to {"Bah", "Herf", "Banarange"}
However, this process will add the new element whether it already appears in the list or not. Sometimes, for example if you are creating a list of players (Not advisable on a large MOO) you don't want players already added to be re-added.
Fortunately, the MOO server provides a verb which will only add an element if it does NOT appear already. This verb is called ~setadd'
Example:
X = {"Bah", "Herf"};
X = setadd (X, "Bah");
Since "Bah" already appears in the list, setadd will not add it to the list again.
Sometimes, a verb will need to remove something from a list. This is made possible by 'setadds' counterpart - 'setremove'. This verb will remove all traces of an element.
Example:
X = {"Bah", "Foo", "Herf", "Bah"}
X = setremove (X, "Bah");
X is now equal to {"Foo", "Herf"}
It is often necessary to check whether an item is in a list. For example, you need to see if a person is connected.
This is exceptionaly easy in MOO.
Example:
If (player in connected_players())
Just like when we index strings, it is possible to index a list. This will give the position of the first incident of the item :
Example:
X = {"Bah", "HerF", "Banarange"}
Y = index (X, "Herf");
Y would now contain the value 2 because "Herf" is the second element.
Going one step further with this, just like the string, it is possible to choose on item from the list using the [square brackets]
If we were to include this line Below the 2 above:
Z = X[Y];
Then Z would equal the 2nd element of X. Which is "herf"
However, you can also become more selective with the "[]"'s routine. For example:
Z = list[1][2][3]
Here, Z would become the 3rd item of the second item of the first item.
Eg:
List = {"Bah", "Foo","Bar","Herf"}
List [2][3] = "o" - It's the 3rd letter of the 2nd item.
You can find the length of a list in exactly the same way as a string.
Using the 'Random' verb and a mixture of Indexing and length, it is possible to retrieve a random element from a list.
Random works by picking a number between 1 and the number given. So, if we pass it the length of a list, then it will pick a number valid in the list. Then by using the [ ] technique, we can pick that rendomly determined element.
Example:
X = {"Bah", "Herf", "Banarange"};
Random = random (length(X));
Item = X [Random];
So, in this verb, the 'Random' verb is being told to pick a number between 1 and the length of X (In this case 3) We then take that value, and use it to pick an element.
So, if the random verb returned a 2 then Item would be assigned "herf"
You can't just display a list to a player using 'player:tell()' this will give the result {list} so, you have to use one of 2 main ways. One is sloppy, and the other is workable.
The Sloppy way.
Use a FOR LOOP
For Item in (list)
player:tell (Item);
Endfor
The Better Way.
Or, you can use a verb on the $generic Player which will do this for you. The verb is called Tell_Lines. You simply use it like you would Player:tell.
Example
Player:tell_lines(List);
The $list_utils object comes with a verb called reverse() which does
as it's name suggests. You can use it to reverse the order of a list:
X = {"Bah", "Herf", "Foo"}
X = $list_utils:reverse (X);
X is now valued as {"Foo", "Herf", "Bah"}
Like with strings, it is sometimes useful to get the player running the verb to input some text. Using the same idea as before, a fromt end for a config verb, let's assume that the player wants a multi-line description.
The $code_utils package offers a verb called read_lines() this verb will continue running until is receives a line with only a "." on it.
Example:
Desc = $code_utils:read_lines();
This will give 'desc' the value of whatever lines you type. Suppose you typed:
Hello This is a test Of Read_lines() .
Desc will now equal {"Hello", "This is a test", "Of read lines"}
So, you can now index it, and select one specific value.
Objects are everything on the MOO. Everything that you can pick up, use etc is an object. In fact, you yourself are an object. So, it's unsurprising that objects are a huge part of MOO coding.
So, before I start outlining ways of screwing with objects, first I will give you some verbs which will be invaluable as a new MOO coder.
@verbs
(See the later sections on permissions for more details on this.)
A lot of MOO code is used for moving objects around. You for example, when you move into a room, you must obviously be moved. But, it's not simply a case of adding you to a .contents prop, changing your location and deleting you from old .contents. So, the MOO can do it for you.
There are 2 ways of moving an object. One will only move objects which YOU, the programmer, own. The other, will move anything. ** except wizards **
So, the first method is rarely used, but here it is for interest only ;)
Move (object, new.location)
But, the newer version which moves things if found on the #1 or $Root Class object (Which ALL objects are children of.) To call this moving verb, you run it on the object you want to move.
Object:moveto(new.location);
The object is then moved cleanly and easily.
Sometimes you need to check what parents an object has. There are 4 ways of doing this. Two use verbs on the $object_utils package and Two are "builtins"
The first builtin is children() which will return a list of the children of an object.
So, you could use - if (#436 in children(#43)) to check if #436 is a child of #43.
The other builtin in is Parents() which also returns a list, this time of the parents of an object. So, to check the same thing as above:
If (#43 in parents(#436)) will check if #43 is a parent of #436.
Now, here's the $object_utils ways of doing this:
If ($object_utils:isa( object, what your checking for)
So, for example, say you wanted to check that an object was a child of #435
If ($object_utils:isa(object, #435)
Would return a 1 if it was, or a 0 if it wasn't.
However, there is another way. The following verb returns a list of the ancestors of an object.
$object_utils:ancestors (object)
So, if you wanted to check that an object was a child of #435 you would use:
If (#435 in $object_utils:ancestors(object))
For most purposes, the :isa routine is the cleanest way of checking, but the :ancestors is useful if you want to return a list of parents.
As I have mentioned before, parents contain most of the verbs on an object. So, let's assume you want to change the parent of an object in a verb. There is a builtin verb provided by the server which will allow you to do this.
Chparent(object, new parent);
So, if we want to change the parent of #433 to a Generic Room, we use:
Chparent (#433, $room);
The verb will only change the parent of an object if the new parent is fertile. This stops you changing the parent of yourself to something like "Wizard".
It is possible, and occasionally necessary to find what verbs can be found on an object. For this, the server provides a builtin function which will return the list of verbs.
LIST = verbs(object);
This does the same as the 'verbs' verb, but instead it returns a list of the properties on an object.
LIST = properties(object);
Sometimes it is vital to check if a prop exists. Otherwise, if it doesn't then you'll get a huge error. An example of this is the "generic Garbage Object" which does not contain the property 'object_size' so, when you try and @audit $hacker, you can't - it crashes.
So, the simple fix for this is:
If ($object_utils:has_prop(object, property))
You can now do whatever you want to the prop as usual.
As with properties, it is sometimes useful to check that an object has a verb on it. This can be done in a VERY similar manner to the props.
However, the verb name must be given as a STRING. So, here's how it works.
If ($object_utils:has_verb(object, tostr("Verb name"))
Again, this is another way of checking verbs. However, this one only returns true if the verb is callable from another verb.
$object_utils:has_callable_verb(object, tostr("verb name"))
Let's say that for some reason you want a suspend in a verb. That is, you want it to pause for a few seconds, maybe to add realism. The MOO provides a builtin function which will allow you to do this:
Suspend(number of seconds);
One problem with MOO code in a verb is that it assumes the @ sign means append. This makes it a little difficult to call a verb which has '@' as it's first character.
However, it is possible:
Object:("verb name");
The verb will now run (IF IT'S CALLABLE!)
The MOO server also provides a verb which will return a list of all the players created on the MOO. This can be a cause of HUGE lag, so it's not advisable to use this often. The verb is called players() and that's all you have to do.
If (object in players())
Then the object is a valid player ;)
Sometimes you might like to customise a verb that you do not own. Say for example you wanted to modify the 'say' verb on a room, but still use the main part from the original. You could write it all again, or you could use pass(). The main use of pass() is to pass the arguments given to the calling verb, to the next instance of that verb in the heirarchy.
Example: pass(@args); - pass the arguments to the next instance of the verb.
So, if you do decide to become a MOO hacker, then that's your choice. I, personally, am against MOO hacking, and this part of the document is not a set of instructions on how to do it. Sorry.
There are 2 sections to verb Permissions. There are the permissions that the verb runs with, and the permissions of the verb itself (Whether it can be read, called etc)
Firstly I will talk about the 2nd type of permission.
When you write a verb, you may want it to be callable from another verb. Or, you might like to let people pass arguments to it.
Or, you might (For some REALLY weird reason) want people to be able to edit your code.
Or, you might want to stop people reading the source.
This is where the X,W and R flags come in.
You can toggle the flags using a verb called @chmod. To use this, simply type:
@chmod object:verb
So, let's say that you want to make a verb callable but not readable:
@chmod object:verb +x -r
As I mentioned above, verbs run with certain permissions. But which ones? Well, they run with the permissions of the programmer who wrote them (Or the person who owns the verb) who is usually the person who added and coded the verb.
This is why some verbs (eg. Using player:_create()) need to be change so a wizard owns them
Wizard verbs can read any property, move any object and basically do anything they want to. This is why Wizard verbs must be carefully written. So, for the budding Wizards out there, here's some simple ways to stop Non-wizards from using your verbs:
Set_task_perms(player); - Makes the individual tasks of the verb run with the players permissions.
If (!player.wizard) - Checks if the player is a wizard (Not VERY secure if the verb is callable)
The easiest way of ensuring that a non-wizard can't use wiz verbs is to use the following check at the beginning of your code:
If (!caller_perms.wizard)
Player:tell ("Bugger off!");
return E_PERM;
"endif
The above example is only really needed in callable verbs, for most cases, you can just check the players wizard bit with if (!player.wizard)
So, when the verb is run, or called, the person doing it must have a wiz bit ;)
Well, as the heading says, that's it. This document should have prepared you for writing some nice verbs. You are now ready to be able to read the Official Programming Manual by Pavel Curtis ;)
Another good way of learning MOO code is to list other peoples. Unless they have made the verb non-readable, you simply have to type:
@list object:verb
This will display a listing of the verb, and you can look through it and see how it works.
At this point I'd like to say THANKS to Slacker. For proof reading this thing, and giving hints which were carefully considered, and then ignored (JOKE) so, there you go.
So, GOOD LUCK with your coding - And why not come visit on Mindscape - mindscape.ml.org port 2112
Cheers.