<html> <head> <title>Daleken Enhanced MUD Programs</title> <link rel="stylesheet" type="text/css" href="doc.css" title="Documentation Standard Style"> </head> <body bgcolor="#ffffff"> <table class="main" width="600" border="0"> <tr><td> <div align="right"> DalekenMUD 1.12 documentation. <br>Updated 7 June 2000. <br>Symposium <<a href="mailto:mwt02@uow.edu.au">mwt02@uow.edu.au</a>> </div> </td></tr> <tr><th class="heading"> <h1>Daleken Enhanced MUD Programs</h1> </th></tr> <tr><td> <p>This document describes all the enhancements that have been made to the original MOBProgram code. A knowledge of the workings of the original MOBProgram system is not required but you probably should read the document as not all sections of that document are covered in this file.</p> <p>My apologies for this document, it was written hastily in order that builders could start work on their own programs, further revisions are possible but like I always say "Don't hold your breath!".</p> <p><div align="right">-- Symposium 6/99</div></p> <p>In addition to the above, I should add that this document is often a little too technical for most people's needs and the important sections are a little sparce. This makes the rather simple process of writing a mud program a little daunting to beginners. I hope to write a few simple html pages with the core information on those pages, so hope remains!</p> <p><div align="right">-- Symposium 2/00</div></p> </td></tr> <tr><th class="heading"> <h2>Table of Contents</h2> </th></tr> <tr><td> <ul> <li><a href="#Background">Background</a></li> <li><a href="#Terminology">Terminology</a></li> <li><a href="#The Main Additions">The Main Additions</a> <ul> <li><a href="#New Triggers">New Triggers</a></li> <li><a href="#Object and Room Programs">Object and Room Programs</a></li> <li><a href="#New Parser">New Parser</a></li> <li><a href="#Sub Procedures">Sub Procedures</a></li> <li><a href="#Variables">Variables</a></li> <li><a href="#Expanded Substitution">Expanded Substitution</a></li> <li><a href="#Hard-coded Functions">Hard-coded Functions</a></li> <li><a href="#Regular Expression for Triggers">Regular Expression for Triggers</a></li> <li><a href="#The Wait Command">The Wait Command</a></li> <li><a href="#Return Values">Return Values</a></li> <li><a href="#Unique Identifiers">Unique Identifiers</a></li> </ul></li> <li><a href="#The New Syntax">The New Syntax</a> <ul> <li><a href="#Comments">Comments</a></li> <li><a href="#The IF Statement">The IF Statement</a></li> <li><a href="#The WHILE Statement">The WHILE Statement</a></li> <li><a href="#Substitutions">Substitutions</a></li> <li><a href="#Unique Identifiers">Unique Identifiers</a></li> <li><a href="#Special Substitutions">Special Substitutions</a></li> <li><a href="#Operators">Operators</a></li> <li><a href="#Sub Programs">Sub Programs</a></li> </ul></li> <li><a href="#The Differences between Mobile, Object and Room Programs"> The Differences between Mobile, Object and Room Programs</a></li> <li><a href="#Triggers">Triggers</a> <ul> <li><a href="#Regular Expression Syntax">Regular Expression Syntax</a></li> <li><a href="#Common Triggers">Common Triggers</a></li> <li><a href="#Mobile Triggers">Mobile Triggers</a></li> <li><a href="#Object Triggers">Object Triggers</a></li> <li><a href="#Room Triggers">Room Triggers</a></li> </ul></li> <li><a href="#Global Programs">Global Programs</a></li> <li><a href="#Functions">Functions</a></li> <li><a href="#Commands for Mobiles">Commands for Mobiles</a> <ul> <li><a href="#Getting Around the Restriction">Getting Around the Restriction</a></li> <li><a href="#The Commands">The Commands</a></li> </ul></li> <li><a href="#Miscellaneous Junk">Miscellaneous Junk</a> <ul> <li><a href="#Regarding CPU Slowdown">Regarding CPU Slowdown</a></li> <li><a href="#Other info">Other info</a></li> <li><a href="#Credits">Credits</a></li> <li><a href="#Example(s)">Example(s)</a></li> </ul></li> </ul> </td></tr> <tr><th class="heading"> <a name="Background"></a> <h2>Background</h2> </th></tr> <tr><td> <p>Once upon a time muds were pretty lifeless places, nothing much happened outside of a player's own imagination. One of the problems was that mobiles weren't terribly intelligent, they were all the same and they could be depended on to react the same way, if they did even react. The problem was that making a mob that little bit more special required a friendly relationship with a coder who would have to hard-code any intelligence, which meant either very few mobiles got smart, or, as is more common, mobiles stayed dumb.</p> <p>The solution proposed was to have mobiles have some sort of soft-coded programs that can be interpreted in game and can be loaded and saved through area files with all the other standard information. This system has vast benefits for the game, it makes the game more intelligent and it makes it easy for builders to create intelligent creatures in their areas.</p> <p>Further thought has since gone into the idea and the conclusion was that while mobiles having their own little programs was nice, much of the really cool ideas involved some far more complex things. Thus the idea to extend the system a little and add programs and triggers for objects and rooms, the two other major components of the MUD. And while we were at it, lets make the programming a little more flexible, not that it has to be difficult just a few extensions to give it a little more whzzz.</p> <p>Once again, the basic idea: let not only mobiles, but objects and rooms react to a myriad of mud events/situations by having them perform a list of commands which can be tailored to the moment through a simple and not so intimidating scheme usable by any creator. While this isn't universally understandable to builders this is one hell of a lot better than writing a lot of C code.</p> </td></tr> <tr><th class="heading"> <a name="Terminology"></a> <h2>Terminology</h2> </th></tr> <tr><td> <p>In this document there are a few standard terms used, this makes it easier to write and, once you become accustomed to the words, easier to read. First of all you will need to understand the terms, after all we aren't all coders.</p> <dl> <dt>Mob (Mobile)</dt> <dd>A creature/monster in the game.</dd> <dd>These can have programs and in the context of the program they are referred to as "the mob".</dd> <dt>Object</dt> <dd>An item in the game.</dd> <dd>Like mobs objects can have programs written for them.</dd> <dt>Room</dt> <dd>A location in the game, this is also a game construct and Rooms can have programs like mobs or objects.</dd> <dt>Builder</dt> <dd>A person who is creating an area.</dd> <dt>trigger</dt> <dd>An event in the game that causes a program to start.</dd> <dd>Triggers are dealt with in detail in this document later.</dd> <dt>program, MUDProg</dt> <dd>A MUD program, a series of commands which are interpreted by the game to be run by a mob, the whole point of the exercise.</dd> <dt>variable</dt> <dd>A programming idea where a specified symbol can represent some other value which is capable of changing as the program runs. <dd>A good analogy is algebra where <code>x + 6 = 13</code>, so <code>x = 7</code> in this case, although x could be completely different in a different situation.</dd> <dt>function</dt> <dd>A programming construct that is a part of a program which takes certain values (arguments) and after performing some operations, returns a value.</dd> <dt>act, act message</dt> <dd>The standard way that messages are sent to characters in the MUD.</dd> <dd>Act messages are used for virtually any output to a character that requires a name, a second player, a target object or messages that are sent to an entire room.</dd> <dd>Often there is an act message sent to a number of characters in a room, they each can get a different message.</dd> <dd>See <a href="act.html">act.html</a> for further information.</dd> <dt>game pulse (pulse)</dt> <dd>Just about every action on the MUD runs after a predefined interval, these are called pulses. The basic pulse is one quarter of a second and all actions, such as the resetting of areas is done on a multiple of these basic intervals.</dd> <dd>There are different types of pulses, game pulses are generally just referred to as pulses and other pulses are referred to by their names, such as the violence pulse which goes off every 3 seconds.</dd> <dd>refer to <a href="config.html">config.html</a> for all the pulses, also look in <code>const.h</code> and <code>update.c</code> for all timing information.</dd> </dl> </td></tr> <tr><th class="heading"> <a name="The Main Additions"></a> <h2>The Main Additions</h2> </th></tr> <tr><td> <p>In DalekenMUD the entire program system has had a reworking and it now hardly resembles the original code. The additions made have made it possible to create more intelligent creatures as well as some neat additions which add new dimensions to the base MOBPrograms.</p> <p>There is only one change that should be made to existing mobprograms, for details see the note on the 'rand' function below. (Search for the string 'rand')</p> <a name="New Triggers"></a><h3>New Triggers</h3> <p>A series of new triggers have been added to allow a wider range of situations in which a mobile will/can react.</p> <a name="Object and Room Programs"></a><h3>Object and Room Programs</h3> <p>Objects and Rooms can now react to situations like mobiles, there are triggers for these as well as being able to react on some of the same triggers as mobiles, Objects and Rooms can react to individual situations themselves.</p> <a name="New Parser"></a><h3>New Parser</h3> <p>IF statements have been expanded to allow nested IFs and WHILE statements, this expands the usefulness of a single program and avoids some of the restrictions/bugs of the old system.</p> <a name="Sub Procedures"></a><h3>Sub Procedures</h3> <p>Certain MOBPrograms (they as yet cannot be called on Objects and Rooms) can be triggered from within other programs on the same mob and can even be triggered by another mob. This allows a degree of communication between mobiles and also avoids the nasty long programs that were common previously.</p> <a name="Variables"></a><h3>Variables</h3> <p>Mobiles, Objects and Rooms can now store variables which allow them to remember things for a certain period. This allows some degree of state and further expands the capacity of programs.</p> <a name="Expanded Substitution"></a><h3>Expanded Substitution</h3> <p>The <code>$</code> codes have been expanded from the old system to allow substitution in the trigger strings, <blockquote> i.e. you can trigger on "p a rock hits $n on the nose!" </blockquote> Be warned about this type of trigger, once characters get access to the "setname" command, they wont appear as just their name, and immortals almost always have bizarre setnames that will cause this to break.</p> <p>Of course variables can be substituted in any position like the old <code>$</code> codes and you can of course use a function substitution to gain the name of <code>$n</code>...</p> <a name="Hard-coded Functions"></a><h3>Hard-coded Functions</h3> <p>Combined with the expanded substitution is the new method of functions. This allows simple arithmetic and functions. These new functions are used in the precessing of IF and WHILE statements and they can be substituted to get values throughout the program. String functions are also available, which can turn numbers into strings or find special fields like name and descriptions. There are lots of functions available, LOTS and LOTS and LOTS and...</p> <a name="Regular Expression for Triggers"></a><h3>Regular Expression for Triggers</h3> <p>Triggers now have the option of triggering on a regular expression. This allows more flexibility.</p> <a name="The Wait Command"></a><h3>The Wait Command</h3> <p>This command allows the program to be frozen for a time and to be continued later. The current state: variables and stack, are stored as an event and then the program is restarted after a period of time.</p> <a name="Return Values"></a><h3>Return Values</h3> <p>Programs now may return a value from the program. This value may have some affect on how the program continues around it. The value defaults to 1 which generally wont cause any additional affect. Refer to the trigger types below.</p> <a name="Unique Identifiers"></a><h3>Unique Identifiers</h3> <p>Every player and object now has a unique key value that ensures that it is individual. This can be accessed by mudprogs to ensure that a program is always directed at the correct target.</p> </td></tr> <tr><th class="heading"> <a name="The New Syntax"></a> <h2>The New Syntax</h2> </th></tr> <tr><td> <p>There are a few minor changes to the syntax of programs resulting from these enormous changes. Mainly the changes will influence how future programs are run, not impacting too much on already working programs. The same basic structure has been followed to a large extent, mainly there are additions.</p> <a name="Comments"></a><h3>Comments</h3> <p>All (decent?) programming languages have at least some support for comments. So here whenever a line starts with a <code>#</code> (hash) character, the rest of the line is ignored.</p> <a name="The IF Statement"></a><h3>The IF Statement</h3> <p>This follows the same form as previously:</p> <pre> "if" {some conditional statement} [ "or" {some conditional statement} ] . . . [ "or" {some conditional statement} ] [ {program command} ] . . . [ {program command} ] [ "else" [ "if" {some conditional statement} ] ] [ "or" ...] [ {program command} ] . . . [ {program command} ] "endif" </pre> <p>There a two major changes to this statement:</p> <ol> <li>The conditional statement is interpreted as a number with all the number function capacity of the parser, a non-zero value is considered true and zero considered false. This has no real implications on the running of old programs as the result is the same as before. See the section below on functions.</li> <li>There is the possibility of adding extra if statements following an <code>else</code>, like with most programming languages. This gives a great deal of flexibility to the program and unlike with the original system, only a single "endif" is required to end an "if" block like this.</li> </ol> <a name="The WHILE Statement"></a><h3>The WHILE Statement</h3> <p>This statement is very similar to the IF statement in syntax:</p> <pre> "while" {some conditional statement} [ "or" {some conditional statement} ] . . . [ "or" {some conditional statement} ] [ {program command} ] . . . [ {program command} ] [ {program command} ] "endwhile" </pre> <p>The only difference between this and an "if" is that the program loops continually while the statement at the top is true. Builders writing "while" statements should be careful that it isn't possible to get into an infinite loop, this is a terminal affliction in all programs.</p> <a name="Substitutions"></a><h3>Substitutions</h3> <p>The substitution method of the original system has been kept and expanded to allow a few additional substitutions. The MUDProg has references to a few characters and objects and certain values can be obtained and substituted into the program for each of these. When the program is interpreted these values are expanded to suit the situation.</p> <p>Here is a small table of the standard substitutions used, refer to the original documentation if you are confused by this small table.</p> <table class="sub" border="0" cellspacing="0" cellpadding="2"> <tr> <th class="topleft">variable</th><th class="top">mobile</th> <th class="top">actor</th><th class="top">victim</th> <th class="top">random</th> <th class="top">object</th><th class="top">2nd object</th> </tr><tr> <th class="left">name</th> <td>$i</td><td>$n</td><td>$t</td><td>$r</td><td>$o</td><td>$p</td> </tr><tr> <th class="left">short_desc/title</th> <td>$I</td><td>$N</td><td>$T</td><td>$R</td><td>$O</td><td>$P</td> </tr><tr> <th class="left">he/she/it</th> <td>$j</td><td>$e</td><td>$E</td><td>$J</td><td>--</td><td>--</td> </tr><tr> <th class="left">him/her/it</th> <td>$l</td><td>$m</td><td>$M</td><td>$L</td><td>--</td><td>--</td> </tr><tr> <th class="left">his/hers/its</th> <td>$k</td><td>$s</td><td>$S</td><td>$K</td><td>--</td><td>--</td> </tr><tr> <th class="left">a/an</th> <td>--</td><td>--</td><td>--</td><td>--</td><td>$a</td><td>$A</td> </tr><tr> </table> <code>$$</code> gives the <code>$</code> symbol. <p>KEY:</p> <dl> <dt>mobile <dd>the mob running the program.</dd> <dt>actor</dt> <dd>the character who triggered the program.</dd> <dt>victim</dt> <dd>a second mob/character, eg from socials where one character does something on another.</dd> <dt>random</dt> <dd>a randomly chosen character.</dd> <dt>object</dt> <dd> the object referred to in the trigger (eg when someone gets something)</dd> <dt>2nd object</dt> <dd>Rare: the second object, the only place I can think of is when someone gets something from a bag, this object is the bag.</dd> <dt>shrt_desc</dt> <dd> - the short description of a mobile.</dd> </dl> <p>The name field values ($i, $n, $o...) are values which are commonly used in functions to identify mobs/objects.</p> <a name="Unique Identifiers"></a><h3>Unique Identifiers</h3> <p>By simply adding a hash (<code>#</code>) after the '$' sign you can specify that you want the unique identifier of the character or object instead of their name. This only works for the lower case version of the key such as <code>$n</code> and <code>$o</code>, NOT <code>$N</code> or <code>$O</code>. In order to use this as a target for a command place an additional hash before the '$' sign so the number can be interpreted as a unique id. An optional 'c' or 'C' for character and 'o' or 'O' for object can also be added. No space is allowed between the # and the number.</p> <table class="sub" width="300" border="0" cellspacing="0" cellpadding="2"> <tr> <th class="top">Standard Command</th><th class="top">Expanded Form</th> </tr><tr> <td>goto $n</td><td>goto dragon</td> </tr><tr> <td>get $o</td><td>get sword</td> </tr> </table> <table class="sub" width="300" border="0" cellspacing="0" cellpadding="2"> <tr> <th class="top">Alternate Command</th><th class="top">Expanded Form</th> </tr><tr> <td>goto #$#n</td><td>goto #25940</td> </tr><tr> <td>goto #c$#n</td><td>goto #c25940</td> </tr><tr> <td>get #$#o</td><td>get #83056</td> </tr><tr> <td>get #o$#o</td><td>get #o83056</td> </tr> </table> <p>While this may seem a little confusing, it can be extremely useful for avoiding complications in programs where items may be mixed in amoungst a number of other items with the same keyword, or you are looking for a particular mob that has triggered the program.</p> <p><b>Note:</b> There is also a function for obtaining the unique id number of a character or object, use this when you need to keep tabs on them and they aren't directly related to the program.</p> <a name="Special Substitutions"></a><h3>Special Substitutions</h3> <p>Variables can be substituted by referring to them by name, <code>${variable}</code>, this substitution simply puts the value of the variable and, if the variable doesn't exist, nothing at all.</p> <p>There are also system defined variables <code>${1}, ${2}, ...</code> which are the words in the trigger string, if the program was triggered from something that had a string, i.e. an act_prog or speech_prog. These variables also exist for a sub_prog. These can also be referred to in bundles as <code>${2-3}</code> to get arguments 2 and 3, and <code>${2+}</code> to get from the second argument onwards, be wary with these substitutions they may not always work as you expect.</p> <p>The value of a number function can be substituted in general code, thus general algebra/maths can be done in the program, e.g.:</p> <blockquote><code> set variable $[variable+1] </code></blockquote> <p>Variables are automatically expanded inside these brackets so there isn't any messy multiple substitutions necessary. Variables are identified by the fact that they don't have a digit at the start and they aren't followed by parentheses.</p> <p>Variables also exist for the current program, these values cease to exist after the program is run and can be a fair bit tidier if you only want something for a short period. These values can be set using the command <code>local</code>, which is used in the same manner as <code>set</code>. These are also used for the variable <code>trigger</code> which is the string that caused the program to trigger and the arguments from a regexp match (see regmatch).</p> <p>Number functions are the most commonly used construct in number substitutions as they give access to a wide range of information, a common substitution is:</p> <blockquote><code> say You need to be level $[level($o)-3] to use this object $n. </code></blockquote> <p>Number functions are identified by the parser as having alphabetic characters (i.e. a-z and A-Z) at the start and a term in parentheses straight after them.</p> <p>String function substitution is rarely used but it can be used to get a name for something that has a value, most commonly a character class or race, sometimes a skill. These are substituted as a single function only as below:</p> <blockquote><code> say I see that you are a $(table(class,class($n))) $n. </code></blockquote> <p>This demonstrates the use of the table function, using the "class" table the value from the "class" function was looked up and the name of the class substituted.</p> <a name="Operators"></a><h3>Operators</h3> <p>In the number functions and IF and WHILE statements all the standard C style operators below can be used (this time I'm not lying, the old system fudged it, I, on the other hand, am serious):</p> <table class="sub" border="0" cellspacing="0" cellpadding="2"> <tr> <th class="left">+</th><td>plus</td> <th class="left">-</th><td>minus</td> </tr><tr> <th class="left">*</th><td>times</td> <th class="left">/</th><td>divided by</td> </tr><tr> <th class="left">%</th><td>modulo</td> <th class="left">^</th><td>exclusive OR</td> </tr><tr> <th class="left">==</th><td>equal to</td> <th class="left">!=</th><td>not equal to</td> </tr><tr> <th class="left">></th><td>is greater than</td> <th class="left"><</th><td>is less than</td> </tr><tr> <th class="left">>=</th><td>is greather than or equal to</td> <th class="left"><=</th><td>is less than or equal to</td> </tr><tr> <th class="left">&&</th><td>logical AND</td> <th class="left">||</th><td>logical OR</td> </tr><tr> <th class="left">&</th><td>binary AND</td> <th class="left">|</th><td>binary OR</td> </tr><tr> <th class="left">>></th><td>binary shift right</td> <th class="left"><<</th><td>binary shift right</td> </tr><tr> <th class="left">!</th><td>logical NOT<b>*</b></td> <th class="left">~</th><td>binary NOT<b>*</b></td> </tr> </table> <p><b>*</b> - these operators apply to the number to the right only.</p> <p>Logical operators are not evaluated in the same manner as in C, you can't rely on the result of the first term to not have the second term evaluated. <b><u>all terms are evaluated, relevant or not</u></b>. For example the following code causes bugs to be reported as when $r doesn't exist the level function cannot be performed:</p> <pre> if exist($r) && level($r) < 5 say Hello $r! endif </pre> <p>to fix the problem in this case, use the following code:</p> <pre> if exist($r) if level($r) < 5 say Hello $r! endif endif </pre> <p>Try not to use the binary and logical NOT operators together, who knows what the answer will be, use parentheses if you really must.</p> <a name="Sub Programs"></a><h3>Sub Programs</h3> <p>In order to split up programs into reusable bundles (an idea which hit programming a long time ago) Daleken has now introduced MUDProgram subprograms. The idea is that commonly used bundles of commands can be grouped together in a single, separate program.</p> <p>A new type of program exists whereby these commands can be run from within another program entirely. The sub_prog can be run using the command "sub" with any arguments you like passed in on the line after:</p> <blockquote><code> sub progname [arg1 arg2 arg3 ...] </code></blockquote> <p>A further addition is that these subprograms can be triggered from another mob/object/room progam by using the "trigger" command.</p> <p>Since any program can return a value, sub programs may also return a value, this value is stored in the variable "subreturn". However this return value is not set when the trigger command is used, instead look at the function "sub" below.</p> </td></tr> <tr><th class="heading"> <a name="The Differences between Mobile, Object and Room Programs"></a> <h2>The Differences between Mobile, Object and Room Programs</h2> </th></tr> <tr><td> <p>In order to understand the differences in the types of programs, you must first understand how the programs for objects and rooms work to a certain extent. Both Objects and Rooms cannot themselves perform commands, so when they have a program to run the MUD creates a special mob to perform the commands for them. For this reason there are a few commands which Objects and Rooms cannot perform:</p> <blockquote><code> kill, sub, delay, burrow, cast </code></blockquote> <p>Rooms and objects may cast defensive spells on players, but be careful here as strange effects may occur.</p> <p>There are no hard-coded restrictions, however the results from these commands being run from an Object or Room progam could be extremely nasty.</p> </td></tr> <tr><th class="heading"> <a name="Triggers"></a> <h2>Triggers</h2> </th></tr> <tr><td> <p>This section describes the different programs that are run as a response to different game events.</p> <p>Most programs are on a first in line only basis, the first program encountered that is run successfully is the last on checked, ie as soon as a program is run the others are ignored. So the order of programs is slightly important. Those which don't use this principle are marked with a <b>*</b>.</p> <p>Note also that triggers of the same name may have totally different application when applied to an object as opposed to a mobile, take care to ensure you are in the right context when using these programs.</p> <p>Argument types are as follows:</p> <dl> <dt>percentage</dt> <dd> the argument is a number, the program will be run 'n' percent of the time, i.e. if a number from 1 to 100 is less than or equal to the given number. </dd> <dt>wordlist</dt> <dd> the program is triggered on a string, the argument is a list of words and if one of the words in the argument is part of the string that triggers the program, the program is run. </dd><dd> the wordlist can be a list of words separated by spaces </dd><dd> a phrase, if the first word is a "p" by itself, the program is triggered if the phrase is contained in the string. </dd><dd> a full line, if the first word is a "l" by itself, the program is triggered if the entire line matches the trigger string. </dd><dd> a regular expression, starting with a "r" by itself. </dd> </dl> <a name="Regular Expression Syntax"></a><h3>Regular Expression Syntax</h3> <p>This is by no means a complete regular expression help, but it may help with mudprog programming.</p> <p>A regular expression is a series of branches or options separated by '|' symbols. Each branch is comprised of a number of pieces, which are mostly single characters.</p> <p>A piece or character can be followed by a modifier symbol which signifies how many of that piece can be matched:</p> <table class="sub" border="0" cellspacing="0" cellpadding="2"> <tr><th class="left">*</th><td>0 to infinite matches</td></tr> <tr><th class="left">+</th><td>1 or more matches</td></tr> <tr><th class="left">?</th><td>0 or 1 matches</td></tr> <tr><th class="left">{x-y}</th><td>x to y matches</td></tr> </table> <p>A piece can be non-character symbols:</p> <table class="sub" border="0" cellspacing="0" cellpadding="2"> <tr><th class="left">^</th><td>matches the start of a line</td></tr> <tr><th class="left">$</th><td>matches the end of a line</td></tr> <tr><th class="left">.</th><td>matches anything</td></tr> <tr><th class="left">\</th><td>can precede a special character (e.g. '\.')</td></tr> </table> <p>A piece can also represent a range of characters by using square brackets '[]'. Inside these you can put any character and a range is represented using a '-' (e.g. <code>[0-9]</code> represents any digit) to include ']' make it the first in the sequence, to include '-' put it at the ends. A range piece starting with a '^' means NOT the letters contained (eg [^ ] matches anything but space).</p> <p>Regular expressions in this case also have a grouping notation represented by '\(' and '\)'. These allow you to group branches or pieces into a single piece. Also these are useful in extracting a sub-string from the triggering string, as these grouped sets are put in <code>${r2}, ${r3}, ${r4}...</code></p> <p>Special variables like ${2} when regular expressions are used are as follows:</p> <table class="sub" border="0" cellspacing="0" cellpadding="2"> <tr><th class="left">${r0}</th><td>the entire matched string</td></tr> <tr><th class="left">${r1}</th><td>the first grouped set using '\(' and '\)'</td></tr> <tr><th class="left">${r2}</th><td>the second grouped set...</td></tr> </table> <p>Examples:</p> <table class="sub" border="0" cellspacing="0" cellpadding="2"> <tr><th class="top">Regular Expression</th> <th class="top">Matches</th></tr> <tr><td>part of line</td><td>part of a line</td></tr> <tr><td>^entire line$</td><td>an entire line</td></tr> <tr><td>\(^| \)word\( |$\)</td><td>a single word</td></tr> <tr><td valign="top">\(Yes|No\)</td> <td>yes or no (the result is stored in ${r0} and ${r1})</td></tr> <tr><td valign="top">^\([^ ]+\) says, '\([hH]ello|[hH]i\)[?.!]?'.$</td> <td>someone saying hi or hello (followed by some optional punctuation) <br></br>${r0} - the entire line <br></br>${r1} the person, ${r2} - hello, Hello, hi or Hi</td> </tr> </table> <a name="Common Triggers"></a><h3>Common Triggers</h3> <p>These are common to all types of programs, more or less, some restrictions apply to certain types.</p> <h4>GLOBAL_PROG (vnum of global program)</h4> <p>This program is special in that the program here doesn't actually do anything, the code is totally ignored. This really serves as a reference to a globally created program with the specified vnum. FOr more information see the section below titled "Global Programs".</p> <h4><b>*</b> ACT_PROG (wordlist)</h4> <p>This is the most generic of all triggers, any act message that goes to the room can trigger an <code>ACT_PROG</code> on room or object and any act message that would go to a mob can trigger that mob's <code>ACT_PROG</code>. <h4><b>*</b> SPEECH_PROG (wordlist)</h4> <p>This is triggered when someone speaks.</p> <h4>RAND_PROG (percentage)</h4> <p>This program is run at regular intervals for mobile, room and object. This can be used to add extra character to mobiles which would normally just stand motionless.</p> <h4><b>*</b> GREET_PROG (percentage)</h4> <p>This program is run when a player enters the room. Sneaking characters can avoid this program. This is often used for shopkeepers in combination with the "isopen" function to greet customers.</p> <h4><b>*</b> ALL_GREET_PROG (percentage)</h4> <p>Like <code>GREET_PROG</code> except that the program is always run. Some nasty area writers have mobs casting area spells when players enter the room.</p> <p><b>NOTE:</b> Neither <code>GREET_PROG</code> is activated if the mob is fighting. <code>GREET_(ALL_)PROG</code>s are rare in that multiple programs will all be run.</p> <h4>SUB_PROG (the name of the program)</h4> <p>Described above. The argument is the name of the program, this should be a single word as this makes referring to the subprog much easier.</p> <h4>TIME_PROG (a list of number separated by spaces)</h4> <p>When the time reaches any one of the times named in the argument the program is run.</p> <h4>REPOP_PROG (percentage)</h4> <p>Run when the mobile or object is created and entered into the world. Builders should be careful that the program doesn't kill the mobile concerned. (NOT FOR ROOMS, der!)</p> <h4>LOOK_PROG (percentage)</h4> <p>Run when a player explicitly looks at the mob/object/room.</p> <h4>COMMAND_PROG (list of commands to trigger on)</h4> <p>Run when a player types one of the commands in the trigger. The command entered must match the command exactly in order to work properly.</p> <p>In addition the <code>COMMAND_PROG</code> examines the value returned by the program, if this is 0 (or false) the program will be considered to not have run and the character will have access to normal commands afterwards. If the program is run with the default return value or a non-zero return, then no command is run.</p> <p>This program triggers in a special way, you must specify the exact command word to trigger on although you can specify several command words. Additionally if you are using this to mask actual commands you can use the following notation to signify part of a command: <blockquote><code> comma|ndword </code></blockquote> The vertical bar signifies that any letters after it are optional, so that this is equivalent to the long list: <blockquote><code> comma comman command commandw commandwo commandwor commandword </code></blockquote> As you can see this is useful for masking system commands that are commonly abbreviated such as equipment : <code>eq|uipment</code>.</p> <a name="Mobile Triggers"></a><h3>Mobile Triggers</h3> <h4>FIGHT_PROG (percentage)</h4> <p>This program is checked every round that the mob is fighting.</p> <h4>DEATH_PROG (percentage)</h4> <p>This program is run after the mobile has been killed and just before it is extracted. This can be used to give players their quest prize or something like that or to leave a legacy (maybe drop a box of explosives). Note that this program cannot stop the mobile from dying, this is merely a means of getting a few things done before it dies. The return value of the program is examined and if it is non-zero, the mobile will be free to scream a last death cry.</p> <h4>HITPRCNT_PROG (hit point percentage)</h4> <p>This program is run every round after the mobiles hitpoints reach below the specified percentage of their maximum, it has been used previously so that the mob then starts casting heal on itself every round. Only one of these programs is run, so if there are multiple programs they ones with higher numbers should be placed last.</p> <h4>ENTRY_PROG (percentage)</h4> <p>Run when the mobile enters the room, can be used to announce their presence or to check that someone is here or not.</p> <h4>GIVE_PROG (object name or "all")</h4> <p>This is run when the mobile is given the named object. The argument must be the complete name of the object in order to trigger properly. The first successful trigger is the one that is run, so you can have an "all" trigger catch all rubbish that is given to the mob.</p> <h4>BRIBE_PROG (gold amount)</h4> <p>This program is run when the mob is given the right amount of gold, only one <code>BRIBE_PROG</code> is run at a time so you can have several triggers starting with the large amounts of gold going to the small amounts. Gold given to a mob is given to it as an object in it's inventory unlike what normally happens when you give gold to someone.</p> <h4>ATTACK_PROG (percentage)</h4> <p>This program is run when the mobile is first attacked by someone. The mob gets its actions before the attack goes through so using "peace" has no effect and moving out of the room permanently is the only way of stopping the fight occurring.</p> <h4>DELAY_PROG (percentage)</h4> <p>This program is checked when the mob gets out of imposed delay. This happens when the "delay" command has been used on the mob. This program is used to time programs. Known bug/loophole: if the mob is thrown/smashed/tripped when in delayed by this method it can prolong or shorten the delay.</p> <a name="Object Triggers"></a><h3>Object Triggers</h3> <h4>WEAR_PROG (percentage)</h4> <p>Triggered when someone wears the object. If the return value is false, the program will prevent the character from wearing the item.</p> <h4>REMOVE_PROG (percentage)</h4> <p>Triggered when someone removes the object. If the return value is false, the program will prevent the character from removing the item.</p> <h4>SAC_PROG (percentage)</h4> <p>Triggered when someone sacrifices the object. Like the DEATH_PROG this can't stop the object from being extracted. If the return value is false, the program will prevent the item from being sacrificed.</p> <h4>EXAMINE_PROG (percentage)</h4> <p>Triggered when someone examines the object, this is the "look in" command as opposed to the actual examine command. This is used for when someone looks in a portal, container or something like that.</p> <h4>USE_PROG (percentage)</h4> <p>This is triggered on the object type specific use of the object. So for scrolls this is when it is recited, wands, when zapped, staves when brandished, etc..., if an object is used somehow this prog is run. Like the <code>DEATH_PROG</code> this can't stop the object from being extracted.</p> <h4>GET_PROG (percentage)</h4> <p>Triggered when the object is picked up. If the return value is false, the program will prevent the character from getting the item.</p> <h4>DROP_PROG (percentage)</h4> <p>Triggered when the object is put back down. If the return value is false, the program will prevent the character from dropping the item.</p> <h4>DAMAGE_PROG (percentage)</h4> <p>Triggered when the object is damaged in some way.</p> <h4>REPAIR_PROG (percentage)</h4> <p>Triggered when the object is smithed or repaired.</p> <h4>OPEN_PROG (percentage)</h4> <p>Triggered when the container object is opened.</p> <h4>CLOSE_PROG (percentage)</h4> <p>Triggered when the container object is closed.</p> <h4>LOOT_PROG (percentage)</h4> <p>Triggered when someone loots the container. If the return value is false, the program will prevent the character from getting anything from the chest.</p> <a name="Room Triggers"></a><h3>Room Triggers</h3> <h4>SLEEP_PROG (percentage)</h4> <p>Triggered when a player sleeps in the room. If the return value is false, the program will stop the player from sleeping.</p> <h4>REST_PROG (percentage)</h4> <p>Triggered when a player rests in the room. If the return value is false, the program will stop the player from resting.</p> <h4>LEAVE_PROG (percentage)</h4> <p>Triggered just before a player leaves the room.</p> <h4>DROP_PROG (percentage)</h4> <p>Triggered by a player dropping an item on the ground, the return value of 0 prevents this from happening.</p> </td></tr> <tr><th class="heading"> <a name="Global Programs"></a> <h2>Global Programs</h2> </th></tr> <tr><td> <p>These progams are loaded and saved with an area instead of a particular mobile, object or room. They each have a specific vnum like a mobile, object or room and have their own separate section in the area file.</p> <p>These programs have a type, triggers and commands like any other program. Through the use of the <code>GLOBAL_PROG</code> type of command they can be added to any mobile, object or room through the arguments to the program.</p> For instance we create a global program of type <code>SPEECH_PROG</code> with a vnum of 901 and a trigger message of "hello", then we add this program to all of the guard mobiles in the area by giving them a <code>GLOBAL_PROG</code> with an argument of "901". Now the guards all have effectively the same program, all triggering when someone says "hello" and resulting in the same action, this reduces the duplication of code. <p>One addition that has been made for use in OLC is the addition of a restriction on what type of thing the program can be added to, this is not enforced in the loading of an area, but it is when the area is being edited online. This ensures that programs designed for mobiles aren't used for objects and rooms primarily, that being the main concern.</p> </td></tr> <tr><th class="heading"> <a name="Functions"></a> <h2>Functions</h2> </th></tr> <tr><td> <p>This is a list of all the functions available with a description of how they work. All functions are in the following form:<p> <blockquote><code> function( arg1 [, arg2] [, arg3] [, arg4] ) </code></blockquote> <p>"function" is the name of the function, "arg1", "arg2", ... are the names of the values that the function works on.</p. <p>THERE ARE LOTS AND LOTS OF FUNCTIONS AVAILABLE.</p> <h4>Notation and Variable Types as Used Below</h4> <ul> <li>FALSE refers to the number 0, TRUE is any other number.</li> <li>A character is $i, $n, $t, $r or the name of any character in the MUD.</li> <li>An object is $o, $p or any object in the room.</li> <li>The current room is the room where the mobile is at the moment.</li> <li>A door is north, south... or the name of the exit.</li> <li>A string is substituted differently when taken as an argument: <ol> <li>anything quoted using "" has normal $ substitution done.</li> <li>anything else containing '(' and ')' is taken to be a string function.</li> <li>any other word is taken to be a variable and its value is substituted accordingly.</li> </ol></li> </ul> <table class="sub" border="0" cellspacing="0" cellpadding="2"> <tr><th class="top">Function</th> <th class="top">Arguments</th> <th class="top">Returns</th> </tr> <tr><td valign="top">exist</td> <td valign="top">$i, $n, $t, $r, $o, $p</td> <td valign="top">TRUE/FALSE</td> </tr><tr><td></td><td class="notes" colspan="2"> This is a unique function, only $ codes are allowed as arguments to this function, it returns TRUE if the target of the command exists. This function is used most often to determine if there is a random character to act upon. </td> </tr> <tr><td valign="top">rand</td> <td valign="top"> <ol><li>the start of the range</li> <li>the end of the range</li></ol></td> <td valign="top">a random number between arg1 and arg2</td> </tr><tr><td></td><td class="notes" colspan="2"> This function generates a random number. If arg2 isn't there it results in a number between 1 and arg1 and if there is no arguments then it returns a number from 1 to 100. <br></br><b>NOTE:</b> the usage of this function has changed, this is the only change that program writers need to make to any of their programs. This function no longer returns a boolean, you should replace all lines as below: <blockquote> <code>rand(40)</code> should now become <code>rand(100) <= 40</code> </blockquote> I must apologise for this inconvenience but I consider it a small price to pay when the new version of the function is now much more useful. </td> </tr> <tr><td valign="top">dice</td> <td valign="top"> <ol><li>the number of dice</li> <li>the number of sides on each die</li></ol></td> <td valign="top">the sum of arg1 rolls of an arg2 sided dice</td> </tr><tr><td></td><td class="notes" colspan="2"> This function returns a random number, as if a number of dice were rolled and the sum of the values were added up. The arguments determine how many dice and how big. </td> </tr> <tr><td valign="top">time</td> <td valign="top">--</td> <td valign="top">the current hour of MUD time</td> </tr> <tr><td valign="top">mobs</td> <td valign="top">--</td> <td valign="top">the number of mobiles in the current room</td> </tr> <tr><td valign="top">players</td> <td valign="top">--</td> <td valign="top">the number of players in the current room</td> </tr> <tr><td valign="top">people</td> <td valign="top">--</td> <td valign="top">the number of people in the current room</td> </tr> <tr><td valign="top">mobinarea</td> <td valign="top">--</td> <td valign="top">the number of mobiles in the current area</td> </tr> <tr><td valign="top">playerinarea</td> <td valign="top">--</td> <td valign="top">the number of players in the current area</td> </tr> <tr><td valign="top">timeskilled</td> <td valign="top">--</td> <td valign="top">the number of times a mobile of this vnum has been killed</td> </tr> <tr><td valign="top">isexit</td> <td valign="top">a door</td> <td valign="top">whether the direction given has an exit</td> </tr> <tr><td valign="top">isclear</td> <td valign="top">a door</td> <td valign="top">whether the direction given is an open passage</td> </tr><tr><td></td><td class="notes" colspan="2"> This function returns true if the direction isn't a door as well, it's really purpose is to determine whether you can walk in the direction given. </td> </tr> <tr><td valign="top">islocked</td> <td valign="top">a door</td> <td valign="top">whether the door given is locked or not</td> </tr> <tr><td valign="top">findchar</td> <td valign="top">a possible character</td> <td valign="top">if the character named exists</td> </tr> <tr><td valign="top">findobj</td> <td valign="top">a possible object <br></br>OR <ol><li>a character</li> <li>a possible object</li></td> <td valign="top">if the named object exists (on the specified character in the second usage)</td> </tr> <tr><td valign="top">ispc</td> <td valign="top">a character</td> <td valign="top">if the character given is a player</td> </tr> <tr><td valign="top">uid</td> <td valign="top">a character</td> <td valign="top">the character's unique id number</td> </tr> <tr><td valign="top">isgood</td> <td valign="top">a character</td> <td valign="top">if the character given is good</td> </tr> <tr><td valign="top">isevil</td> <td valign="top">a character</td> <td valign="top">if the character given is evil</td> </tr> <tr><td valign="top">isimmort</td> <td valign="top">a character</td> <td valign="top">if the character given is immortal</td> </tr> <tr><td valign="top">ischarmed</td> <td valign="top">a character</td> <td valign="top">if the character is affected by charm person spell</td> </tr> <tr><td valign="top">isflying</td> <td valign="top">a character</td> <td valign="top">if the character is capable of flying</td> </tr> <tr><td valign="top">hitprcnt</td> <td valign="top">a character</td> <td valign="top">the percentage of hitpoints remaining on the character</td> </tr> <tr><td valign="top">inroom</td> <td valign="top">a character</td> <td valign="top">the vnum of the room that the character is in</td> </tr> <tr><td valign="top">sex</td> <td valign="top">a character</td> <td valign="top">the sex of the character</td> </tr> <tr><td valign="top">position</td> <td valign="top">a character</td> <td valign="top">the position of the character</td> </tr> <tr><td valign="top">level</td> <td valign="top">a character</td> <td valign="top">the level of the character</td> </tr> <tr><td valign="top">waitstate</td> <td valign="top">a character</td> <td valign="top">the wait state of the character</td> </tr> <tr><td valign="top">class</td> <td valign="top">a character</td> <td valign="top">the class of the character</td> </tr> <tr><td valign="top">race</td> <td valign="top">a character</td> <td valign="top">the race of the character</td> </tr> <tr><td valign="top">origclass</td> <td valign="top">a character</td> <td valign="top">the original class of the character (for multiclassed characters)</td> </tr> <tr><td valign="top">goldamt</td> <td valign="top">a character</td> <td valign="top">how much gold the character is carrying</td> </tr> <tr><td valign="top">isopen</td> <td valign="top">a character</td> <td valign="top">if the character is a shopkeeper and open at the moment</td> </tr> <tr><td valign="top">isoutlaw</td> <td valign="top">a character</td> <td valign="top">if the character is an outlaw</td> </tr> <tr><td valign="top">hp</td> <td valign="top">a character</td> <td valign="top">the current hitpoints of the character</td> </tr> <tr><td valign="top">maxhp</td> <td valign="top">a character</td> <td valign="top">the maximum hitpoints of the character</td> </tr> <tr><td valign="top">mana<sphere></td> <td valign="top">a character</td> <td valign="top">the current mana of the character for the specified sphere</td> </tr><tr><td></td><td class="notes" colspan="2"> Used with the name of the sphere directly after the word "mana", e.g. <blockquote><code> manafire($n) </code></blockquote> without specifying a sphere the value is the sum of all spheres. </td> </tr> <tr><td valign="top">maxmana<sphere></td> <td valign="top">a character</td> <td valign="top">the maximum mana of the character</td> </tr> <tr><td valign="top">magic<sphere></td> <td valign="top">a character</td> <td valign="top">the character's current magic for a particular sphere</td> </tr> <tr><td valign="top">move</td> <td valign="top">a character</td> <td valign="top">the current moves of the character</td> </tr> <tr><td valign="top">maxmove</td> <td valign="top">a character</td> <td valign="top">the maximum moves of the character</td> </tr> <tr><td valign="top">str</td> <td valign="top">a character</td> <td valign="top">the current strength of the character</td> </tr> <tr><td valign="top">int</td> <td valign="top">a character</td> <td valign="top">the current intelligence of the character</td> </tr> <tr><td valign="top">wis</td> <td valign="top">a character</td> <td valign="top">the current wisdom of the character</td> </tr> <tr><td valign="top">dex</td> <td valign="top">a character</td> <td valign="top">the current dexterity of the character</td> </tr> <tr><td valign="top">con</td> <td valign="top">a character</td> <td valign="top">the current constitution of the character</td> </tr> <tr><td valign="top">getskill</td> <td valign="top"> <ol><li>a character</li> <li>skill name</li></ol></td> <td valign="top">the current skill for the character in that skill</td> </tr> <tr><td valign="top">getsuccess</td> <td valign="top"> <ol><li>a character</li> <li>skill name</li> <li>[a percentage modifier on their skill.]</li></ol></td> <td valign="top">the current skill for the character in that skill if they succeed at the skill</td> </tr> <tr><td valign="top">isfight</td> <td valign="top"> <ol><li>a character</li> <li>[ a character ]</li></ol></td> <td valign="top">if the character is fighting</td> </tr><tr><td></td><td class="notes" colspan="2"> If the second argument is specified then the function becomes if the two characters are fighting one another. </td> </tr> <tr><td valign="top">cansee</td> <td valign="top"> <ol><li>a character</li> <li>[ a character ]</li></ol></td> <td valign="top">if arg2 is visible to arg1 OR if arg1 is visible</td> </tr> <tr><td valign="top">isfollow</td> <td valign="top"> <ol><li>a character</li> <li>[ a character ]</li></ol></td> <td valign="top">if arg2 is follows to arg1 OR if mob follows arg1</td> </tr> <tr><td valign="top">isaffected</td> <td valign="top"> <ol><li>a character</li> <li>affect name</li></ol></td> <td valign="top">if the character is affected by the names affect</td> </tr><tr><td></td><td class="notes" colspan="2"> The second argument can be any affect as specified by typing '? affect' in the game, it can also be several affects separated by spaces however the results is that of any one of these affects exist, then the function returns true. </td> </tr> <tr><td valign="top">bodypart</td> <td valign="top"> <ol><li>a character</li> <li>the name(s) of bodypart(s)</li></ol></td> <td valign="top">if the character has one of the named bodyparts</td> </tr> <tr><td valign="top">variable</td> <td valign="top"> <ol><li>a character</li> <li>a variable name</li></ol></td> <td valign="top">the value of the variable</td> </tr> <tr><td valign="top">sub</td> <td valign="top"> <ol><li>a character</li> <li>arguments to the sub program</li></ol></td> <td valign="top">the return value of the sub program, 0 if none was run</td> </tr><tr><td></td><td class="notes" colspan="2"> This runs a sub program on the target and returns the result of that sub program. This is a good substitute for the "sub" command if you need to know the result of the program. </td> </tr> <tr><td valign="top">uid</td> <td valign="top">an object</td> <td valign="top">the object's unique id number</td> </tr> <tr><td valign="top">objtype</td> <td valign="top">an object</td> <td valign="top">the type of the object as a number</td> </tr> <tr><td valign="top">objval</td> <td valign="top"> <ol><li>an object</li> <li>the number of the value (0-3)</li></ol></td> <td valign="top">the integer value of that value</td> </tr> <tr><td valign="top">vnum</td> <td valign="top">an object</td> <td valign="top">the virtual number of the character or object</td> </tr> <tr><td valign="top">isvar</td> <td valign="top">a variable name</td> <td valign="top">if the variable named has been set</td> </tr> <tr><td valign="top">strcmp</td> <td valign="top"> <ol><li>a string</li> <li>a string</li></ol></td> <td valign="top">if the strings are equal</td> </tr> <tr><td valign="top">strprefix</td> <td valign="top"> <ol><li>a string</li> <li>a string</li></ol></td> <td valign="top">if the first string is a prefix of the second</td> </tr> <tr><td valign="top">strinfix</td> <td valign="top"> <ol><li>a string</li> <li>a string</li></ol></td> <td valign="top">if the first string is contained within the second</td> </tr> <tr><td valign="top">strkey</td> <td valign="top"> <ol><li>a string</li> <li>a string</li></ol></td> <td valign="top">if the first string is a keyword for the second</td> </tr> <tr><td valign="top">strlen</td> <td valign="top">a string</td> <td valign="top">the length of the string</td> </tr> <tr><td valign="top">speclookup</td> <td valign="top">the name of spec function</td> <td valign="top">the index of the special function</td> </tr> <tr><td valign="top">slookup</td> <td valign="top">the name of a skill</td> <td valign="top">the index of the skill in the skill table</td> </tr> <tr><td valign="top">racelookup</td> <td valign="top">the name of a race</td> <td valign="top">the index of the race in the race table</td> </tr> <tr><td valign="top"><?table?> <br></br>OR<br></br>table(name,value) <br></br>OR<br></br>table-name(value)</td> <td valign="top">the string value you want to look up (value)</td> <td valign="top">the value that the string maps to</td> </tr><tr><td></td><td class="notes" colspan="2"> This function uses the tables in bit.c to get a value, each table that has a value in the OLC command '?' can have a function here, this way you can get the value that a particular name in that table refers to. The name of the function is the name of the table. e.g. <blockquote> <code>apply(intelligence)</code> looks up the apply table for "intelligence" <code>act(aggressive)</code> looks up the act table for the value of "aggressive" </blockquote> </td> </tr> <tr><td valign="top">name</td> <td valign="top">a character</td> <td valign="top">{STRING} the full name of the character</td> </tr><tr><td></td><td class="notes" colspan="2"> Unlike the $n substitution this returns the entire name of the character. </td> </tr> <tr><td valign="top">short</td> <td valign="top">a character</td> <td valign="top">{STRING} the short description of the character</td> </tr> <tr><td valign="top">long</td> <td valign="top">a character</td> <td valign="top">{STRING} the long description of the character</td> </tr> <tr><td valign="top">pers</td> <td valign="top"> <ol><li>a character</li> <li>an observer</li></ol></td> <td valign="top">{STRING} how a character appears to others in most messages</td> </tr><tr><td></td><td class="notes" colspan="2"> This returns how the character looks to others, taking into consideration their setname and if they are visible or not. The looker is by default the runner of the program, but you can specify any other character to see how they look from a different perspective. </td> </tr> <tr><td valign="top">table</td> <td valign="top"> <ol><li>the name of the table</li> <li>value to find in the table</li></ol></td> <td valign="top">{STRING} the name for the value from the table</td> </tr><tr><td></td><td class="notes" colspan="2"> The table can be one of the following: class, race, skill, spec and any of the bit tables as used above. </td> </tr> </table> </td></tr> <tr><th class="heading"> <a name="Commands for Mobiles"></a> <h2>Commands for Mobiles</h2> </th></tr> <tr><td> <p>Mobile commands are somewhat restricted in order to provide security from players, there are a number of program only commands that allow mobiles to perform unusual tasks. Unlike the previous MOBPrograms these commands are not included in the regular command table. This means that mob commands can shadow (have the same name but do different stuff) regular commands.</p> <a name="Getting Around the Restriction"></a><h3>Getting Around the Restriction</h3> <p>As soon as there is a restriction there is a loophole. We found that programs are useless unless mobs can force other mobs to perform these commands. So we invented a loophole. Why bother you ask? Well this gives a central place were we can tighten security rather than a million holes. The "mpcomm" command allows mobiles to access the special commands.</p> <p>For example a mob wants to force another mobile to <code>kill $n</code>, this is only possible through the extended command set so he uses:</p> <blockquote><code> force mob2 mpcomm kill $n </code></blockquote> <p><b>Note:</b> the only addition from the force command is the "mpcomm" (which can be shortened to "mp").</p> <p><b>PLEASE READ THE NOTES ON FORCE and MPCOMM below.</b></p> <a name="The Commands"></a><h3>The Commands</h3> <h4>ASOUND <message></h4> <p>Sends a message to this room and all the rooms adjacent to it. Useful for powerful mobiles and those with things like music and so forth.</p> <h4>AT <location> <command></h4> <p>Much like the immortal command "at", it performs the command at the named location.</p> <h4>BREAK</h4> <p>This is an internal mobprogram command, it signifies that the program should break out of the current loop (if there is one) this differs from the original in that it can be used in a while loop and not terminate the program.</p> <h4>BURROW</h4> <p>Causes the mobile to burrow itself into the ground, thus becoming totalling invisible to everyone, except those with holysight (ie. immortals).</p> <h4>CAST <spell> <target></h4> <p>Used like the other command of the same name.</p> <h4>PASSAGEOPEN <fromvnum> <tovnum> <direction></h4> <h4>PASSAGECLOSE <fromvnum> <direction></h4> <p>This pair of commands allows mobprograms to open and close temporary exits between rooms. This command opens an exit from the room with vnum <fromvnum> to the room with vnum <tovnum> in the direction specified. Mobs can also close this temporary passage by specifying the originating room and the direction to remove.</p> <p><b>NOTE:</b> these temporary exits aren't saved in area files, so you can create them and leave them if you wish.</p> <h4>DAMAGE <character> <amount></h4> <p>Does the specified amount of damage to the character, this is done silently so you have to add your own damage message if you want. This can kill a target so be very careful how much damage you inflict and (more importantly) how you refer to the target after you have inflicted the damage.</p> <h4>DELAY <character> <amount></h4> <p>Sets an amount of lag for the character specified. The amount is a number of game pulses that they are lagged for (divide by 4 to get the number of seconds). After being delayed like this a mob can have it's delay_prog triggered.</p> <h4>LOCAL <variable> <value></h4> <h4>SET <variable> <value></h4> <h4>DELETE <variable></h4> <h4>UNSET <variable></h4> <p>These commands allow you to set and remove MUDProg variables on a mob/object/room. The set command is most often used with some form of substitution to set the variable. Delete and unset are synonyms for the command that removes a variable and frees up the memory it used.</p> <p>The local command sets a variable on the current program, there is no need to delete these values in the program as they are automatically deleted when the program finishes.</p> <p>Use of variables is a process which cannot be covered in this file as there are many ways to use them, we couldn't even begin to think of the possibilities. This file is not a programming tutorial we have to leave some things up to the creator.</p> <h4>DREAM <character> <message></h4> <p>This sends a message to a sleeping character as if they dreamt it.</p> <h4>ECHO <message></h4> <p>This echoes the message to all the awake characters in the room. It uses the <code>act()</code> function so you can do some funky stuff with it such as using $$n to send $n to the act function, but be careful, act isn't totally crash-proof and there can be no checks on this little diddy.</p> <h4>ECHOAROUND <character> <message></h4> <p>Sends the message to all in the room except the specified character.</p> <h4>ECHOAT <character> <message></h4> <p>Sends the message to the specified character.</p> <h4>EVAL ...</h4> <p>This builtin command is used for special cases when one set of substitution is not quite enough. This command expands all '$' expressions in the line and then parses the line that results as if it were the normal thing to do. This also includes things like 'eval if ...'. This means that you can use variables within variables if you think it necessary.</p> <p>This command opens up a whole range of options for the scripter, but often it just makes code unreadable.</p> <p>The two main uses:</p> <ol> <li>Expand a variable within a variable: <blockquote><code> local temp $$n eval say Hello ${temp} </code></blockquote></li> <li>Allow a variable to be used within another variable name: <blockquote><code> eval kill $${enemyof$n} </code></blockquote></li> </ol> <h4>FORCE <character> <command></h4> <h4>QFORCE <character> <command></h4> <p>Forces the character to do the command, much like the imm variety, except silent, the player gets no indication of what they are being forced to do. Be careful to make sure that the character can do this command (see below), otherwise they will get some strange error messages and the program may not run as you expected.</p> <b><em>!!!IMPORTANT!!!</em></b> <p>This command is different in a number of respects to the immortal command, the differences are subtle and they probably wont affect the use of the command but there are implications to anyone who wants to do something tricky.</p> <p>The way that the mpcomm command works is that if a player attempts to enter a mob command through this method, the system blocks them as it realises that they are connected via a descriptor. Thus players cannot have mob commands processed in any way at all.</p> <p>The QFORCE command in the mob commands has a little addition which removes the descriptor temporarily from any character (player OR mobile) before running any command. This means that things like mpcomm are allowed and by using this command you can force players to access these mob commands. ANY forced commands will not be shown to the character, you will have to add emotes or echoes to fill the gaps. This has a large number of advantages for MUDProgs but use this only where you know ALL the implications, try to avoid over-using this pretty heavy-duty feature, as you can see here:</p> <b><em>WARNING!</em></b> Allowing access to the mob commands doesn't mean that it should be allowed, for instance using "qforce $n mp kill xxx" as opposed to "qforce $n kill xxx" is dramatically different, the second ignores certain checks and may very well allow the player to undertake pkilling against his/her will.</p> <em>YOU HAVE BEEN WARNED!</em> <h4>GOTO <location></h4> <p>Transfers the mobile to the specified location, like the imm command.</p> <h4>HALT</h4> <p>Stops the program, no if's or but's.</p> <h4>JUNK <item></h4> <h4>JUNK all.<item></h4> <p>Extracts item(s) from the mobs inventory silently. Be sure you know what you carry it can extracts everything not worn, even object targets of the program, which is very dangerous. You can junk one object, a bunch of objects or the whole lot if you want.</p> <h4>KILL <character></h4> <p>Like the player command used so often. This command is the mobile version as mobiles cannot actually "kill" anything by using this command normally.</p> <h4>MLOAD <vnum></h4> <h4>OLOAD <vnum> [level]</h4> <p>Exactly the same as the immortal command except that there are no messages generated, like most mob commands they are completely silent.</p> <h4>OSET <object> <field> <value></h4> <p>This allows a mobile to set values on an item. This is effectively a quiet version of the immortal oset command.</p> <h4>PEACE</h4> <p>Much like the immortal command of the same name, stops all fighting in the room, no security checks though.</p> <h4>PURGE [character|object]</h4> <p>Much like the immortal command, on its own it purges everything except player corpses. Or you can specify single or multiple characters or objects using all.<char> or all.<obj>.</p> <h4>REGMATCH <pattern> <string></h4> <p>This command uses the regular expression matching algorithm to attempt to match the string here. The main use of this program is in the setting of variables in the local program that contain sections of <string>. As described in the regular expression section above the values ${r0}, ${r1}, etc... are set only if the pattern matches string.</p> <p><b>NOTE:</b> Properly quote <pattern> to ensure proper operation.</p> <h4>RETURN [value]</h4> <p>Sets the return value of the program and stops running the program.</p> <h4>RETVAL <value></h4> <p>Sets the return value of the program. This command is useful to use just before the first WAIT command as it doesn't stop running the program but will ensure that the program returns the right value.</p> <h4>TRANSFER <character> <location></h4> <p>Transfers the specified character to the desired location, like the immortal command of the same name.</p> <h4>TRIGGER <mobile> <sub_prog-name> [arguments...]</h4> <p>This command starts a mobprogram running on the mobile specified. You can specify arguments to the program to determine actions. This allows communication between programs and can avoid some of the nastiness when trying to force other mobiles to do multiple things on their own. Rather than having to force them to do multiple steps you can set them off on their own program.</p> <h4>WAIT <number></h4> <p>Stops the execution of the program and returns, BUT it registers an event with the server to continue execution of the program from the next line in <number> seconds. The value of <number> is automatically interpreted into a number in the same way as the expression following an 'if' or 'while'.</p> <p><b>NOTE:</b> after a wait, the return value of a program is pointless, the value of the return value at the first wait command is the one that is returned if wait is used.</p> </td></tr> <tr><th class="heading"> <a name="Miscellaneous Junk"></a> <h2>Miscellaneous Junk</h2> </th></tr> <tr><td> <a name="The once was 'Wish List'"></a><h3>The once was 'Wish List'</h3> <p>Well, I did all those things, aren't I good (scoff). --Sym 8/2/2000</p> <a name="Regarding CPU Slowdown"></a><h3>Regarding CPU Slowdown</h3> <p>Of course this is making your MUD run slower, DER! The old documentation tried to dodge the issue by going on about aggressive mobiles and so forth, that was merely a way of deflecting the issue. Lets make no bones about this folks, you are adding an interpreted language to your MUD, of course it will make it slower, but that isn't the point is it? You are adding programs to make your MUD better. (Hey even that isn't guaranteed, even the best system can produce rubbish if you can't use it properly, you need someone who can use this sytem first don't you :P ).</p> <p>If you really are concerned about the adverse affects of adding these programs think a little on what it really does, a bigger executable, a few extra checks in various locations (often not commonly called ones) and the occasional parse of a program. This seems to be far outweighed by the benefits, and still Daleken runs fine on a 20MHz machine.</p> <a name="Other info"></a><h3>Other info</h3> <p>This is taken straight from the other document because it applies here...</p> <p>There is really no limit to the number of MOBprograms a given mobile can have and the length of a single command block is only limited by the value of <code>MAX_STRING_LENGTH</code> when it is being edited using the OLC string editor which limits string to around 4k, so that is probably about 100 lines. The indentation spaces shown in the example above are NOT required, but do make it easier to read (and debug).</p> <p>The MOBprogram stuff runs totally without anything in the mob_commands.c file, but letting mobiles be a bit more godlike has allowed us to do what we consider to be wonderful things. The replicant and polymorphing mobiles described above as well as some nifty mob helping mob interactions are an example.</p> <p>It IS possible to accidentally make mobiles which can trigger in loops. As mentioned in the example at the end of this document, the result is usually a mud crash or major CPU dent. We don't know any way to prevent this from happening, other than careful coding and a restriction of mobile travel from zones of one creator to another (another good reason to not have charmed mobiles do anything). Tracking down the culprit mobile is not always easy. The only thing we have found which always works, is to add a log statement into the MOBprogram driver and fill some disk space until it becomes apparent what commands are repetitively issued. Also, most infinite loops are flukes where the situation just happens to be right and usually it never happens again.</p> <a name="Credits"></a><h3>Credits</h3> <p>The reason this code was written was to enhance the playing experience at ThePrincedom (a Merc 2.0 based world scheduled to open in October 1993).</p> <p>The original idea for this type of MOBprogram came from playing on: <u>WORLDS of CARNAGE</u>, a dikumud implemented by Robbie Roberts and Aaron Buhr. Aaron (known as Dimwit Flathead the First) was the original author from what I have been told, and I hope he will not be totally offended and angered by my coding and sharing a mimicked version with the world. This version is probably not as good as the original and I do feel remorse for publishing the idea. However, since Carnage has been down for months without a word of information regarding its return, I am glad to let one of the best features live on in future generations of MUDs.</p> <p>There are no objections to this code being shared, since, aside from a nuclear destruction of all the Temples of Midgaard (excepting the original one!!), bland mobiles are the greatest bane of Dikumuds today. It would be nice to get a message saying you are using the code just for our references. We shant answer questions from anyone until told where they are using the code. *grin* Since this code is not copyrighted, you of course dont have to do anything we say, but it would be nice of you to put the mobprog help screen into your database, and have mobinfo show up somewhere on a more visible help screen (possibly tagged onto the bottom of credits as a see also...)</p> <p>I acknowledge all the work done by the original Diku authors as well as those at Merc Industries and appreciate their willingness to share code. Also, quick thanks to Wraith for doing a little beta-installation testing.</p> <table width="100%"> <tr><td>N'Atas-Ha<br></br> <a href="mailto:murph@ri.cmu.edu">murph@ri.cmu.edu</a></td> <td valign="top">June, 1993</td></tr> </table> <p>In addition to this DOC file credit section, I'd like to add a thank you to Yaz, Mahatma, Zelda, and the rest of the Marble Mud crew for extensively testing MOBProgram 2.1 for me. You may see MOBPrograms in action as well as their own "flavor" of mud at <a href="telnet://marble.bu.edu:4000">marble.bu.edu 4000</a>.</p> <table width="100%"> <tr><td>Kahn<br></br> MERC Industries</td> <td valign="top">Oct 28th, 1993</td></tr> </table> <p>What they said goes for me too, I'd like to thank the creators of SMAUG for their version of the MOBPrograms, on which I based some of my ideas for Object and Room programs. Also the creators of the fabulous Death Gate Scripts seen often in CircleMUDs about the place.</p> <table width="100%"> <tr><td>Symposium<br></br> DalekenMUD</td> <td valign="top">13th of June, 1999</td></tr> </table> <a name="Example(s)"></a><h3>Example(s)</h3> <p>Ok so there is the sample program(s). You really should see the other file, it really is quite good, here is a simple example from one of our areas, it also demonstrates some of the more advanced features of our system.</p> <pre> ? %Type mudprogs speech_prog~ $Args p cast a portal to~ $Comlist # The use of the positional parameter from the trigger string. say You want a portal to ${5} $n? # Note the assumed use of the name() string function. if strcmp(annoyed,name($n)) say You have tried my patience $n! kill $n halt endif if isevil($n) say Walk there you lazy bastard! set annoyed $n else if isgood($n) # No equality operator works on strings so we have to use strcmp() # However this allows implied use of the name() function again. if strcmp(lastportal,name($n)) say You shouldn't ask me too often or I'll get annoyed. set annoyed $n else say Very well, here you go. endif cast portal ${5} set lastportal $n else say You ask a lot of me $n! set annoyed $n cast portal ${5} endif ~ </pre> <p>This is a speech_prog which allows a mob to cast a portal at a player's request, however if the player asks too often or is evil his gets hit for his troubles. Neutral players get some grace but not as much as good players.</p> <p>Better for the use of this program would be to use a regexp trigger and match a parenthesised block from the pattern ${r1}. The trigger string would probably look like...</p> <blockquote><code> $Args r cast a portal to \(.*\)\(,? please\?*|\?|\)$~ </code></blockquote> <p>...or something along those lines. This is of course a little smarter, but you are forced to thoroughly test the trigger to ensure you have gotten the correct syntax for the regular expression.</p> <p>For better examples look at caveofkn.are which has on helluva lot of programs to make mudschool smarter.</p> </td></tr> </table> </body> </html>