Unofficial MOO Programming Tutorial
=====================================================

  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 Lists

Finding 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. ----------------


A) Introduction

Who the hell am I?

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.....

What the hell is a MOO?

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.

What the hell is MOO programming?

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.

What will this document cover?

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.

What Level is this document for?

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 ;) )

Is this Document for any particular MOO?

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.

Where can I find information?

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.


B) Introduction to MOO coding.

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.

Parents and Children.

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.

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.

Permissions (Part 1)

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 -c

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.


C) Staring to Code

Starting to Write a Verb

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.

Write a Simple Verb

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)

Arguments and Default Values.

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. @join 
 Any        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

Assigning and Comparing Values.

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)

Returning a Specific Value

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 and Iteration

IF...ELSE

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

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.

Summary

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.


Useful MOO verbs and How to Use them.

Introduction

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.

Things With Strings

This section is devoted to various things you can do with strings.

Comparing 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

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 "

Matching Players

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.!");

Adding Strings Together

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 Strings

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"

Splitting Strings into Words.

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 ;)

Finding The Length of a String

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 ;)

Encrypting Strings

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)

Replacing words in a String

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".

Reading a String of input from a player

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.

Reversing a string

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


Things with Lists

Lists can be thought of as a collection of items, including other lists. However, there is a LOT that you can do with them.

Adding things to lists

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.

Removing things from lists

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"}

Finding If Something is in a List

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())

Indexing a list

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.

Finding the Length of a List

You can find the length of a list in exactly the same way as a string.

Random Elements

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"

Displaying a List

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);

Reversing A 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"}

Reading a List of Input

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.


Things with Objects

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  - Gives you a list of the verbs on an object.
@props  - Gives you a list of the properties on an object.
@prop . [value] [permissions] - Creates a property on an 
object.
@list : - Lists the code in a verb
@show . - Shows the contents of a verb.


(See the later sections on permissions for more details on this.)


Moving Objects

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.

Checking The Parents Of An Object

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.

Changing The Parent Of An Object

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".

Listing the verbs on an object

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);

Listing the Properties on an Object

This does the same as the 'verbs' verb, but instead it returns a list of the properties on an object.

LIST = properties(object);

Checking if an Object has a property.

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.

Checking if an Object has a verb

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"))

Checking if an Object has a CALLABLE Verb

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"))


Miscellaneous Verb Stuff

Suspending a verb

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);

Calling a verb that starts with an '@'

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!)

Returning a list of ALL players

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 ;)

Passing from one verb to another

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.


Permissions - Security Stuff

Disclaimer Bit

I was a bit nervous when I came to write this bit. I don't want people hacking MOO's and saying, "But it was in a tutorial!" So, I have decided to give a basic background to permissions, rather than "How To Hack A MOO"

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.

Verb Permissions

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

Permissions that Verbs Run With

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 ;)


That's about it

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.