===================================================== 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:
Now, assume the "Slacker" owns the parent, and he has made the property "-c" when we use @show now, we see this:
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:
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:
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:
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:
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:
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:
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.
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 :
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:
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.
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:
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:
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 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:
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 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:
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:
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
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 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:
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.
(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:
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.
#3424.names
Owner: Wildcard
Permissions: cr
Value: {"Wildcard"}
#3424.names
Owner: Slacker
Permissions: r
Value: {"Wildcard"}
C) Staring to Code
Starting to Write a Verb
Write a Simple Verb
Arguments and Default Values.
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
Player
Room
Features
Direct Object
Indirect Object
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.
'==' - 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
Selection and Iteration
IF...ELSE
if (2 == 2)
Player:tell ("Yep, 2 is equal to 2.");
Else
Player:tell ("Something's wrong. 2 isn't equal to 2!");
Endif
If (player.wizard != 1)
Player:tell ("You aint a wizard. Clear off!");
Return;
Endif
'if (x != {})' - Check that X is not an Empty List
'if (x != "")' - Check that X is not an empty string.
FOR LOOPS
For who in (connected_players())
Player:tell(who.name);
Endfor
X = 1;
While (x != 10)
Player:tell ("X is currently at a value of ", x);
X = X + 1;
Endwhile
Summary
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
X = "This is a string. Foo Bah Baz!";
X = strsub (X, "Bah", "Bar");
Reading a String of input from a player
Player:tell ("Please input your name");
X = $command_utils:read();
Reversing a string
X = "String";
player:tell ($string_utils:reverse(x));
Things with Lists
Adding things to lists
X = {"Bah", "Herf"};
X = {@X, "Banarange"};
X = {"Bah", "Herf"};
X = setadd (X, "Bah");
Removing things from lists
X = {"Bah", "Foo", "Herf", "Bah"}
X = setremove (X, "Bah");
Finding If Something is in a List
Indexing a list
X = {"Bah", "HerF", "Banarange"}
Y = index (X, "Herf");
Finding the Length of a List
Random Elements
X = {"Bah", "Herf", "Banarange"};
Random = random (length(X));
Item = X [Random];
Displaying a List
For Item in (list)
player:tell (Item);
Endfor
Reversing A List
X = {"Bah", "Herf", "Foo"}
X = $list_utils:reverse (X);
Reading a List of Input
Hello
This is a test
Of Read_lines()
.
Things with Objects
@verbs
Moving Objects
Checking The Parents Of An Object
Changing The Parent Of An Object
Listing the verbs on an object
Listing the Properties on an Object
Checking if an Object has a property.
Checking if an Object has a verb
Checking if an Object has a CALLABLE Verb
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
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"
Verb Permissions
Permissions that Verbs Run With
If (!caller_perms.wizard)
Player:tell ("Bugger off!");
return E_PERM;
"endif
That's about it