MobProgs Explained

This page describes how to write mobprogs for an area file. 
<< Back to #SPECIALS Section  >> Forward to Example Area 

If you are coding an area and want your mobs to show behavior beyond the built-in acts of wandering, scavenging, aggression and the fixed specials, you need to write one or more Mobile Programs, referred to in this document as MobProgs. Writing mobprogs is a simple form of programming and places the author in the twilight zone between building and coding.

The basic structure of a MobProg is as follows:
>trigger args~
commands
 

trigger
A trigger is one of a fixed set of events that the MUD knows about which can start a mobprog running, and thus the mob doing something. Here is a list of the currently defined triggers, in alphabetical order. Detailed explanations follow later.
Trigger name Responds to
act_prog an action by another character in the room
all_greet_prog any character entered the room
bribe_prog money is given to the mob
buy_prog someone buys something from the mob
death_prog the mob is about to die
entry_prog the mob just entered a room
fight_prog the mob enters a new round in a fight
give_prog an object is given to the mob
greet_prog a character, visible to the mob, entered the room
hitprcnt_prog mob is fighting and its hp drop below a given value
in_file_prog dummy trigger for mobprog linkage
rand_prog happens randomly once in a while
speech_prog a player utters a given word or phrase
args
args is short for "arguments". If you're new to programming you're new to this use of the word; it simply means extra information to code on the trigger line which gives the trigger something to work on or tells it details about how to work. The information given is specific to the trigger and fine-tunes its action. For example,
So essentially, "arg" is just what you put on the trigger line after the "xxx_prog" word which identifies the trigger. The arguments are explained in detail below with each of their appertaining triggers.

I'll be saying it again, but the argument on the trigger line must be followed by a tilde ( ~ ) !

commands
commands are one or more commands you want the mob to perform when the trigger is activated. You must code one command per line. The commands may be one of the following:


Before we go on,

Some definitions

mobile (mob)
One of the seemingly living beings running around the MUD, controlled by the MUD program.
your mob
The mob for which you are currently writing or working on a MobProg.
player
The human person sitting at the keyboard behind the screen, playing in the MUD. In the context of this MobProg Guide, though, I use player to mean the player character, i.e. the living being which runs around the MUD built up and controlled by the player.
character
Either a mob or a player character. I refer to character when it's not known for sure which of the two it is, or when it doesn't matter.
message
Most events that happen in the MUD result in a message. This is how players are kept aware of what's happening around them. In an artificial-intelligence sort of way, it's also how the mobs find out about events. The game has two different mechanisms for getting messages to characters. They are characterized by the program functions used to generate them, so for simplicity I'll call them "send_to_char messages" and "act messages". The difference is relevant because those MobProg triggers that respond to messages only respond to the "act message" type.
"send_to_char" messages
Most "quick" responses to commands entered by a character use the send_to_char() function to acknowledge the character's action or to give him some other information. Some well-known examples of these "simple" messages are:
Usually such messages only go to the character who caused the message, and don't refer to any persons other than "you".
"act" messages
Most messages informing one character of what another character is doing are of the "act" message type. They use the program function act(), which is very versatile and able to conveniently build characters' names and personal pronouns into a message, select the recipients of the message based on originator, victim, all in room, all in room but victim, all in room but originator, etc. If a message generated by the game has a character's name in it, it's pretty certain to be of this type and thus useable for MobProgs. You may need to experiment to be certain, though.

Messages are crucially important in MobProgs. While a human player moves around in the MUD because he wants to, is curious, is on a quest or has some other motivation, most mobs do things only for two reasons:

word
In a MobProg setting, a word is any sequence of characters not including white space (space or end-of-line). Thus,
keyword
A keyword is a word you specify as an argument (or part of an argument) to a MobProg trigger in the hope of having it match a word in a message received by the mob. There are no partial matches on keywords: A keyword can only match a word in a message exactly, character for character, or not at all. As in the spelling of an in-game spell, two or more words can be combined to form a single keyword by placing them in single quotes ( ' ).
keyphrase
A keyphrase is a sequence of text complete with internal punctuation and spaces, which you specify as an argument to a MobProg in the hope of having it match a message or a continuous part of a message received by the mob. There is no partial matching on keyphrases. A keyphrase can only match exactly, character for character, or not at all. This means the punctuation and/or number of spaces between words must match perfectly as well. The end of a keyphrase must match a space or the end of a line. This means that, once again, funny characters like punctuation become part of the phrase to search for. For a poke in the ribs, the correct way to specify the argument would be:
p pokes you in the ribs.~

Note the tilde ( ~ ) right after the end of the keyphrase.

probability
In the context of arguments to mobprogs, a probability is a way of specifying how likely it is that the trigger will trigger if its basic condition is met. This probability is given as number between 1 and 100 which represents a percentage of probability. Do not write a percent sign! A 100 means the trigger is sure to trigger. You can use a 0 if you want to temporarily disactivate a trigger which takes a probability argument. For long term deactivation, you should remove the whole mobprog so it will not take up game memory.


Connecting a MobProg to a mob

In order for a mob to react to events, i.e. in order for the MobProg to be effective, the MobProg must be connected to the mob. This connection is actually not to a specific mob (you could potentially reset hundreds of mobs, all of the same vnum) but to a mob's prototype, which is shared among all mobs of the same vnum. You can think of MobProgs as being attached to a specific mob vnum and affecting all mobs having that vnum.

There are two different and intermixable ways to connect a MobProg to a mob. The first one is simple and comes fairly naturally. For unique MobProgs affecting only a single mob vnum, this is all you need. The second way is harder to understand, and so far Dizzy MUD has no MobProgs attached that way. So, while it may seem illogical to break up the topic, I hope to avoid unnecessary confusion by explaining the easy way right after this paragraph and leaving the hard way for later.

The Simple Way
The last line of a mobile description (the whole thing you code for a mobile, not its short, long or extended description) is the line that reads

0 0 size 0

To attach a mobprog, code the mobprog right after this last line. You may attach one mobprog or several; essentially you are adding a list of mobprogs with one or more mobprogs in it. After the last line of the last mobprog, you must terminate the list with a single line containing a pipe symbol ( | ). Hunt around on your keyboard, it's there!


Example 1

MobProgs are notoriously difficult for non-programmers to understand. Other documents on the topic have made it difficult to understand for programmers as well. While the preceding sections have gotten by with very few examples, I feel that examples will be essential here.

Although the above is only a cursory overview of mob programming, there is enough information there to code a couple of simple MobProgs, as follows. The example shows a mob description from the #MOBILES section of an area file, complete with two mobprogs.
      
#6902
beggar~
a poor beggar~
A poor beggar plies his demeaning trade here on the street.
~
The beggar is a Teilysa, unkempt and poorly clothed against
the cold wind blowing through the streets. He is lacking
both legs and an arm. The remaining arm holds a battered
hat containing a few coins. No one is tempted to say,
"Get a job!"
~
teilysa~
BGHZ KLMXd 0 S
10 0 2d6+130 10d9+100 1d8+4 punch
5 5 5 8
0 A 0 CD
sleep rest male 15
0 0 small 0
>rand_prog 4~
wake
say Alms, please! Some coins for a poor beggar!
cough
sleep
~
>bribe_prog 1~
wake
smile
say Thank you, thank you! May God bless you!
sleep
~
|
         
     
The example shows a sleeping beggar who randomly wakes up to beg for alms, and who wakes up and thanks his benefactor if given any amount of money. Note the right angle bracket ( > ) preceding each trigger line, the tildes ( ~ ) following the trigger line and MobProg commands, and the pipe symbol ( | ) ending the list of MobProgs for the mob.

Future examples will show only the MobProg(s), not the mob. They will also assume that the MobProg or MobProgs are part of a list which is properly terminated with the pipe symbol ( | ).


Trigger Types in Detail

In order to program more interesting MobProgs than the ones in the first example, you need to be familiar with all the available trigger types and how to control them. What follows is a detailed explanation of each trigger type. These explanations are intended to tell you all about each trigger type. A summary for use as a quick reference is contained in the Trigger Type Table.

First, some definitions


Now for the triggers:
>act_prog  keyword(s)~
>act_prog  p  keyphrase~
This is the most general trigger. It responds to "act messages" received by the mob if and only if the message matches what you specify in the argument. There are two ways to specify this argument:
In both cases, the action, i.e. the commands you code under the trigger line, happen if the words or phrase match. It's that simple.
all_greet_prog   probability
This mobprog is triggered when any character enters the room the mob is in, unless the mob is fighting. The 'all' signifies that it means all characters, including ones the mob cannot see. The 'greet' part signifies a typical use: You could have your mob greet people arriving. However, you don't want to use THIS trigger as it would expose invisible people. There is a greet_prog further down which would be better suited. THIS trigger is more useful for high-tech tricks like teleporting players around. Or maybe completely impassable guardians.

The probability specifies how likely it is that this trigger will actually activate even if its condition is met. In this case, if (for example) you specified "bow" as a command and "50" as a probability, the mob would randomly bow to about half the people entering the room.

bribe_prog   silver-amount
Triggered by money given to the mob. The silver-amount argument is the minimum number of silver coins (or the gold equivalent) for which the trigger will activate. If you want your mob to respond to any donation, code a 1. It's hard to give less than 1 silver and still give, right? See also give_prog.
buy_prog   probability
Triggered if someone buys something from the mob. This seems to be local to Dizzy as it's not mentioned in the 'other' documentation on MobProgs. Unfortunately, the mob is only aware that something has been bought, not what or for how much. So there's not much room for individual reactions.
death_prog  probability
This happens at the same time that, without this trigger, the mob would do its death scream: After it was killed but before the body is turned into a corpse. The probability arg determines how likely it is that this trigger will activate instead of the death cry. The mob is put back in a STANDING position before your commands are executed, so you can code any commands without having to worry about the mob being too dead to perform them. Note, however, that nothing you can code can actually prevent the mob's death. Even if the mob were to fully restore itself, it would die after executing your commands. Still, some amazing sleight of hand can be accomplished with this trigger. The bunnies in the temple of Tao, which get right back up after being killed, are a cute example. They load a (fresh and unhurt) clone of themselves into their location, issue a message about getting up again, then (silently) go into another room to die.
entry_prog  probability
This is done when the mob, wandering around, enters a new room. It will be done whether the room is inhabited or not (I think) so visibility of people in the room is not a problem as with (all_)greet_prog. Typical things to do are to peer around or to wave hello.
fight_prog  probability
This trigger is checked once every PULSE_VIOLENCE during a fight. On Dizzy, PULSE_VIOLENCE translates to once every 3 seconds. The probability is checked on each occasion, so if you code less than 100 here whatever it is will not happen EVERY 3 seconds, but randomly.

This is often used to have the mob throw insults at his opponent. If/when MPCAST is implemented, it could be used to throw spells instead. Failing that, perhaps the mob could scream for help?

give_prog  object-name
This is triggered when someone GIVEs an object (not money) to the mob. There is no probability, it always triggers. The argument specifies, though, which object will trigger the mobprog. The object-name argument must exactly match the keywords field of the object. ID and LORE show the list of keywords in single quotes just after the first word of the output, Object:. In order to match, you must specify the entire keyword list, exactly. You do not need to specify single quotes around object-name, though.

You can have your mob respond to ANY object given to it by specifying all as the argument.

greet_prog  probability
Like all_greet_prog, but will not trigger if the mob cannot see the character entering the room. Like all_greet_prog, it will also not activate if the mob is busy fighting.

Some uses include shopkeepers who greet customers and picky thieves mobs who check players' wealth before attacking. Yeah, an attack can be a form of greeting too.

hitprcnt_prog  hp-percent
If your mob is fighting, then the MUD checks very PULSE_VIOLENCE (see fight_prog) whether the mob's hit points are below hp-percent of his maximum hp. If so, this trigger will be activated. Although hp-percent is a percentage, please code only a number between 0 and 100, no percent sign!

This is one of those triggers of which you can code multiple and of which only the first successful one is executed. I'll explain this in more detail below. For now, remember that you can have your mob do something different for various levels of hurt-ness by coding several mobprogs with percentages in ascending order, say 33, 66, 100 for three different stages of defeat. The first two will not trigger as long as the mob has better than 66% of his hp; after that the second one will trigger, etc.

in_file_prog  file-name
This is not really a trigger, but a way to include a set of mobprogs from a different file at the place where this line is coded. It's part of the hard way to link MobProgs to mobs, so I will explain it later.
rand_prog  probability
The only condition for this trigger is that there is at least one player in the same area as the mob. It happens randomly, with the frequency controlled by the probability you specify. It is checked by a timer running at PULSE_MOBILE, which is (in Dizzy, currently) every 4 seconds. If you code 100 as the probability, your mob will do this every 4 seconds and probably annoy the heck out of people. If you code 7 for the probability, it will happen, on the average, every (4 * 100) / 7 seconds, or about every minute. This is almost tolerable. You may want to cut this down to 3 percent for a little less than once every 2 minutes, average.
speech_prog  keyword(s)
speech_prog  p  keyphrase
This trigger is similar to act_prog, except that the triggering word(s) or phrase must be said (using SAY) by a character in the same room as the mob, and not ACTed. A simple example for this useage is the Acolyte of Isa in the Mud School, which gives cake to newbies polite enough to answer 'yes' to her question. You probably don't want to code this TOO specifically, because player utterances can vary wildly. Consider yourself lucky if you get reasonable matches on a single word!

Some more conditions governing the firing of triggers

There are a number of triggers which may appear a number of times for one mob. hitprcnt_prog was one example. For these triggers, you do not want to see the mob performing more than one at any one time. Happily, the MUD program checks to make sure that, from each of the following trigger types, only the first successful trigger is executed: This is hard to picture without an example. Say you have 3 entry_progs for a mob, doing "peer", "grumble" and "scan", each with a 33% chance. Upon entering a room, chances are 33% that the mob will peer. If it does, it will not grumble or scan because it's already done one entry_prog and will do no more of the same kind. If it fails to peer, there is again a 33% chance that it will grumble. Failing that, there is yet a 33% chance that it will scan. Meanwhile, the occurrence of any other triggers is not affected at all; the mob could conceivably do a rand_prog the very same second, for example.

If you're any good with math and probabilities, you will notice that the probabilities of the events in the example are not as simple as they look. There is really truly a 33% chance of the mob doing the first action. But the second one only happens in 33% of the 67% left over from the first case, which is only 22% chance. The chance of either of the first two events happening is 33+22 = 55%. That leaves us only a 100-55 = 45% chance to check the third event. That comes to 33% of 45%, or less than 15%. The events 'further down' sort of 'live in the shadow' of the preceding events. And yes: 33+22+15 do not add up to 100 by a long shot, thus there is a 31% chance that none of the 3 events will take place, although it looked like a 99% sure thing that one of them would.

What's to be learned from all this? Never mind the math. Just remember that triggers of the same kind further down the line have less of a chance of happening than you would think. Also, if you're despairing of ever getting the probabilities just right, take hope from the fact that there are IFs and probability checks coming up soon which may help you code exactly what you mean.

Something entirely different to be aware of: NONE of these triggers work if the mob is charmed! This keeps people from abusing mobprog behavior for their own evil plans.


Example 2

By way of review, I'll try to put some of the new information together into a more advanced example. I'll extend the mobprogs on the poor beggar from Example 1. He's getting badly overloaded now. Unless a mob is a central figure in your theme, you should probably not heap it with mobprogs to do trivial things like these. Consider the following an example of techniques, not of extent.
      
>rand_prog 33~
snore
~
>rand_prog 50~
cough
~
>rand_prog 100~
moan
~
>hitprcnt_prog 10~
say A miserable life, but I'm about to lose it!
~
>hitprcnt_prog 35~
say Something tells me I'm not going to win this fight.
~
>hitprcnt_prog 70~
say Oh no! I'm bleeding!
~
>hitprcnt_prog 100~
say Have you nothing better to do than to attack defenseless beggars?
~
>bribe_prog 10000~
say My fortune is made!
emote straps on a pair of wooden legs and a wooden arm.
hop
dance
sing
~
>bribe_prog 1000~
say So much gold! This will feed me for days!
cheer
~
>bribe_prog 100~
say A fine donation. Thank you so much!
nod
~
>bribe_prog 1~
say If that's all you have, you might as well keep it!
snicker
~
      
     
This example demonstrates 3 techniques: The examples also point out some deficiencies in the mob progs we are able to write so far. In all the examples, the beggar never really interacts with any other character. He is dimly 'aware' of certain events happening, and does some things in response, but in so doing completely ignores the character who initiated the event. Even in a fight, our beggar talks to himself but not to his opponent. The simple reason is that we don't as yet have the means to identify characters and objects involved in the events that activate triggers. Fortunately, the makers of MobProgs considered this, and included

Variables

First, a brief synopsis of when and how you would use variables in a mobprog.
When:
Whenever you need to refer to a player, mob, or object and have no way of knowing in advance which player, mob or object you will be referring to; or if you want to use personal pronouns like him/her or his/her and don't know the sex of the character you want to refer to, or if you want to use the indefinite article 'a' and don't know if the object being referred to begins with a vowel, requiring 'an'.
How:
Build the appropriate variable into your MobProg commands in places where you would otherwise use names, pronouns or articles. All variables consist of two characters, a Dollar sign ( $ ) and a letter. When your mob executes the mobprog, the MUD program substitutes the correct name or whatever for those two characters.
You can't change the values of these variables as you can in other programming languages, but you'll find their contents very useful in giving your mobs a life. Note that most of the variable names come in upper and lower case, with different meanings! Case is relevant, so make sure you use the correct variable name and case for each purpose.

If you've written SOCIALS before, the syntax will seem familiar to you. Alas, most of the letter codes have different meanings for MobProgs. I will provide the variables in groups based on which character or object they refer to, with explanations and examples.

NOTE:
If you are going to use the names of your mobs or objects for mob commands which generate output visible to players (SAY, YELL, etc), then you need to be aware that the lower case variables ($i, $n, etc) all deliver only the first name (keyword) of the mob or object. Thus, you want to code these names such that the first of them will make sense when used in your messages. You may also want to fine tune the short descriptions so that they fit smoothly and grammatically into any messages you are going to produce. Because of different conventions of using 'a', 'A' or neither at the beginning of short descriptions, this can prove to be a challenge.


Another WARNING!

Something about variables which you need to be aware of is dictated by common sense but often overlooked.

The 'actor', 'victim', 'direct object' and 'indirect object' variables ($n, $t, $o and $p) and their associated forms will not work in a rand_prog or entry_prog!

This is just the only hard and fast rule on the topic. But there are other examples of progs where variables are undefined. A give_prog, for example, does not have a victim, nor an indirect object. Thus, you need to

THINK about the trigger type you use, and decide whether the variable you are planning to use makes sense in that trigger!

If you use a variable that's not defined for the trigger type or context you use it in, your MobProg will CRASH the MUD! This will probably not happen at load time. It is likely to happen at some time in the middle of the game. In the case of a rand_prog, there does not even need to be anyone present in the mob's room. This makes such bugs VERY hard to find and fix. BE CAREFUL! 


IF Statements

The 'other' documentation calls these 'control flow syntax'. This is the correct terminology from the point of view of a computer scientist, but since the term normally encompasses a whole group of statements and we have only one type to offer, we can stick with IF Statements here.

IF Statements address our need to more finely control whether or not parts of a MobProg are executed. The need arises all over the place. Here are some examples:

IF Statements allow us to do all this and more. But be warned, unless you're a programmer already and IFs are second nature to you, this section will give you gray hair or put hair on your chest, depending on circumstances.

General Description
An IF statement consists of one or more checks for a certain condition which you specify, and one or two sets of commands you want performed depending on whether the checked condition turns out to be true or false. Before I show you the 'official' complete structure of an statement, I'll show you some possible example structures. The names I give them are my own, you don't have to remember them.
"Simple IF"
IF ( condition )
   "true" command set
ENDIF 
 
If the condition is true, then the command set is performed.
Otherwise, nothing happens. 
 
"Multiple condition simple IF"
IF ( condition )
OR ( condition )
OR ( condition )
   "true" command set
ENDIF 
 
If any one of the conditions is met, then the command set is performed.
Otherwise, nothing happens.

Of course, the number of alternative (OR) conditions does not have to be 2, it can be any number. This is just an example. 

 
"Two-Way IF"
IF ( condition )
   "true" command set
ELSE
   "false" command set
ENDIF 
 
If the condition is true, then the "true" command set is performed.
Otherwise, the "false" command set is performed. 
 
"Multiple Condition Two-Way IF"
IF ( condition )
OR ( condition )
OR ( condition )
   "true" command set
ELSE
   "false" command set
ENDIF 
 
If any one of the the conditions is true, then the "true" command set is performed.
Otherwise (none of the conditions is true), the "false" command set is performed. 
 
"Complete IF structure diagram with optional things in boxes"
IF ( condition )
OR ( condition )
OR ( condition )
... 
 
 
   "true" command set
ELSE
   "false" command set
ENDIF 
 
Looks frightening, doesn't it?
Notice that if you remove some of the boxes, this diagram looks like one of the preceding ones. 
If you are reading this in your browser (the only way, in my opinion) then you may have been missing links to condition and command set. I didn't want to complicate things any further and distract you with the ability to jump around. Here are the explanations I owe you:

command set
I'll do Command set first because it's simpler to explain.

A command set is simply 0 or more commands. Yes, you are allowed to code no statements between the IF line (or optional OR line(s)) and the ELSE line. A statement like
IF ( condition )
ELSE
   command set
ENDIF 
is perfectly legal and essentially says that you want the command set done if your condition is false
The other two applications of empty command sets are also legal, but don't make any sense. If you code
IF ( condition )
   command set
ELSE
ENDIF 
then you might as well leave out the ELSE line and make your mobprog easier to read and debug. 
If you build one of these,
IF ( condition )
ENDIF 
then you can do without the whole IF statement. 
So, having taken care of the empty case, what can be in a command set if it's not empty? Three different things: Important:
All my examples show the command set indented 3 spaces from the column where the IF starts. The MUD program doesn't require this of you, but I do! There is very little debugging support for mobprogs, and badly written IF statements are a very sure way to crash the MUD. Indentation helps you as the MobProg writer visualize the structure of your code and me (or some other Coder) to understand it so I have a chance at debugging it if you can't.

Correct indenting is very easy to do. As I mentioned before, all the lines of a command set are indented 3 spaces from where the IF, the ENDIF and (maybe) the OR or ELSE start. When you're done, you should be able to draw a straight vertical line between the I in any IF and the E in its ENDIF, and that line will hit only white space, with the possible exception of the O in one or more ORs and/or the E in an ELSE, if there is one.

If there is an IF inside a command set, then the IF and ENDIF (as well as the possible ORs and/or ELSE) must line up with the other commands (if any), while the command set(s) of that IF must be indented another 3 spaces. Thus, your indentation will visually reflect what programmers call "your nesting of IFs" or, more generally, the structure of your program. If you have trouble picturing all this, refer to a complex example. There should be one coming up soon.

condition
A condition is a way of asking the MUD a question which expects an answer of "yes" or "no". Programmers prefer to think in terms of true or false, but these mean the same thing. As a simpleminded example, you could ask the MUD if 2 + 2 equals 5, and as long as the universe is right side up, the answer will be "false". It just ain't true. Getting closer to MUD life, you could ask the MUD if your MOB has more than 0 hit points. Unless your mob just got badly trounced in a fight, that will usually be true.

conditions are always coded between paired parentheses ( '(' and ')' ) . The parentheses, well, kinda hold the condition together. As I mentioned, the condition must come out to be something that ends up true or false. Here are the basic legal forms of a condition:

logical-function
numeric_function   number-compare-op   number
string_function   string-compare-op   string
All the terms in italics are terms I have yet to explain. There is a lot of ground to cover here, so I will need to devote the whole next section to these terms and what they represent.
There's no example here. Alas, you can't build an IF statement without the as yet unexplained stuff that makes up a condition. But once you know about those things, IFs fall into place and we're almost done with all there is to MobProgramming. Hopefully this will motivate you to read onward to


Conditional Operands and Operators

This section deals in depth with what goes inside a conditional, one of those expressions that yields an answer of true or false and which IF statements need to make their decisions.

Logical functions as conditions
The simplest thing to put inside a conditional is a logical function.
What's a function, you ask? Well, a function is a definition of a calculation or some other process that gets a number or some other thing to work on, does some grinding, and comes up with a result. The square function, in math, takes any old number, multiplies it by itself, and returns the result. The square root function does the same thing, only backwards. In the MobProgramming context, functions tend to work on characters and objects. 
The logical functions provided by the MobProg code all look at a character and answer some question about him. Following an old C programming convention, they all start with is and so they're easy to recognize:

Logical Functions
function name what question it answers
isnpc($*) is $* an NPC (a mob)?
ispc($*) is $* an PC (a player)?
isgood($*) does $* have good alignment?
isfight($*) is $* currently fighting?
isimmort($*) is $* an Immortal?
(will also recognize mobs >= LEVEL_IMMORTAL)
ischarmed($*) is $* affected by CHARM?
isfollow($*) is $* a follower with their master in the room?
isaffected($*) & number is $* affected by AFF_xxx?
You don't actually write '$*'. Instead, you write one of $i, $n, $t or $r from the list of variables above. In case it's slipped your mind, $i is your mob, $n is the Actor character doing something in your mob's room, $t is the Actor's Victim (if any) and $r is a random character in your mob's room. As you can tell from the list of possible $ types, all of these functions apply to characters only.

The isaffected() function is different from the rest. You need to write an ampersand ( & ) and a number after the function. The number has to correspond to the flag value of the AFF_whatever affect you want to check for (see the Affect Flag Table). You need to convert the letter codes you're used to using for flags into a number; this is explained in Flag Fields Explained.

Finally, we're ready for the next examples:
>greet_prog 100~
if ( isnpc($n) )
   wink $n
else
   say Alms for a poor beggar, please!
endif
~
This prog will react to everyone entering the mob's room.
Depending on whether it's a mob or a player, your mob will either give the secret wink of the MUDwide mob conspiracy or simply beg for money. 
Let's extend this example. This beggar knows that immortals are stingy, and will not waste his time begging from them.
>greet_prog 100~
if ( isnpc($n) )
   wink $n
else
   if ( isimmort($i) )
   else
      say Alms for a poor beggar, please!
   endif
endif
~
Note the use of ELSE to reverse the question. We don't have an ismortal($*) function, so we ask if the potential donor is immortal, do nothing if he is and beg only if not. 
Two more extensions. First, we decide to wink only at mobs of good alignment and to growl at the rest. Second, we decide also not to beg for money if the player entering the room is charmed:
>greet_prog 100~
if ( isnpc($n) )
   if ( isgood($i) )
      wink $n
   else
      growl $n
   endif
else
   if ( isimmort($n) )
   or ( ischarmed($n) )
   else
      say Alms for a poor beggar, please!
   endif
endif
~
Here's our first use of OR. Meanwhile, our IFs are nested deeply enough to give you some idea of what a properly indented complex mobprog looks like. You may well end up coding even more complex stuff. 
Numeric comparisons as conditions
The next kind of condition is a comparison of one number with another. First, a handful of functions which provide numbers you can test:
Numeric Functions
function name Chars/
Objs
what number it yields range or example
rand(percent) - true if a random number between 0 and 100 is less than percent 0 to 100
hitprcnt($*) C character's current percentage of his full hp 0 to 100
inroom($*) C Room vnum the char is in in Dizzy, Recall is 3001
sex($*) C Character's sex (neutral=0, male=1, female=2) 0 - 2
position($*) C Character's position (dead=0, mortally wounded, incapacitated, stunned, sleeping, resting, sitting, fighting, standing, sneak=9) 0 - 9
level($*) C Character's level 1 - MAX_LEVEL
class($*) C Character's class, as an integer 0 - MAX_CLASS
goldamt($*) C Amount of gold carried by char 0 - ?
objtype($*) O Object's item type, as a number see
Shop Item Type Table
objval0($*)
objval1($*)
objval2($*)
objval3($*)
objval4($*)
O Current value from one slot (0-4) of object's value line, as a number see
Item Type and Value Line Table
Remember, you can only use $o or $p with the last two, which refer to objects only!

To finish coding up your condition (formulating your question), the syntax diagram says you still need a number-compare-op and a number.

You provide the number. If you want to check if your mob is at Recall, write 3001 (or whatever number is the right room vnum for your MUD). If you want to check for a female character, write a 2. If you're checking for a character with a million gold, write 1000000. You get the idea. Some of the values may require digging through tables or asking your friendly Coder.

What's left is the number-compare-op, the numeric comparison operator. You can do most of the standard comparisons you know and love from math and/or computer programming. All of these are coded as one or two symbols, as follows: 

Numeric Comparison Operators
Operator Tests for
== equal
(two '=' signs!)
!= not equal
> greater
< less than
>= greater than or equal
<= less than or equal
& bitwise AND
| bitwise OR
 The last two are a bit weird. I'm including them only for completeness' sake. Time for more examples:
>rand_prog 30~
if ( position($r) < 4 )
   slap $n
endif
~
>rand_prog 40~
if ( goldamt($r) > 1000 )
   if ( sex($r) == 2 )
      beg $r
   endif
endif
~
>greet_prog 100~
if ( class($n) != 2 )
   whine $n
endif
~
  • The first prog randomly look for characters in stunned or worse condition and tries to revive them by slapping them. 
  • The second prog randomly begs from rich women. 
  • The third prog whines at anyone entering the room, unless they are a thief. 
String comparisons as conditions
The string comparison stuff is the simplest, and completes the list of possible conditions you can have your MobProgs check for. There is only one string function:
Numeric Functions
function name Chars/
Objs
what string it yields example
name($*) C,O the complete name (from the keywords field) of the char or object name($i) gives:
beggar
These are the string comparison operators: 
String Comparison Operators
Operator Tests for
== exactly equal
(two '=' signs!)
!= not equal
/ contains
(right hand string is part of left hand string)
!/ does not contain
 String comparisons are case sensitive!
As it stands, the only strings you can test are the names of characters and objects. This coding guide and others advise you to code everything in the keyword fields in lower case, so in order for your string comparisons to succeed, your tested strings need to be in lower case as well. Of course, many older MUD areas have never heard of this convention, so the example below shows an exception from this rule.
Player names, on the other hand, are always 'propercased'. That is, the first character is a capital and the rest are lowercase. MobProgs that check for player names are generally silly.

As was the case of the numeric comparisons, you provide the string to check against. You can either provide a complete keyword field and test for equality (or non-equality) or part of a name and test for a substring match. Whatever string you provide, you must not enclose it in single or double quotes. Just write the string as is and the MUD code will figure it out. To demonstrate this, here is another example:
>rand_prog 100~
if ( name($r) != Super Helga )
   if ( name($n) / guard )
      if ( rand(25) )
         north
         break
      endif
      if ( rand(33) )
         east
         break
      endif
      if ( rand(50) )
         south
         break
      endif
      if ( rand(100) )
         west
         break
      endif
   endif
endif
if ( rand(10) )
   beg
endif
~
Another contrived example: The beggar has been told to stop begging in the city. The guards enforce this order and punish the beggar if they catch him. He can only beg in safety if there are no guards around or if he is in the same room with Super Helga, who protects him. 

The strategy encoded here is not perfect, of course (the beggar has trouble walking around without his legs, too), but it gives you the general idea: As often as he possibly can, the beggar randomly looks at a random mob in the room. If that mob is Helga, then he is safe and need not check for a guard. If the random character he is looking at is a guard, then he tries to move to another room. He randomly chooses one of the 4 main directions. 

If he 'runs' away in any direction, the MobProg performs a BREAK. This stops any other coding in this MobProg from happening at this time. Note the mutually exclusive probabilities in his choice of directions, and how the random values are stacked to make all 4 directions equally likely. 

The beggar only begs in 10% of all of the rand_prog triggers, which gives him 10 'scans' for guards for each 'beg'. This is not an airtight strategy but it gives him a good chance of discovering a guard before being caught begging. 

MobProg-Only Commands

In order to do useful and interesting things, mobs need some special abilities, some of them similar to those of immortals. These let them do things that 'normal' mobs and players cannot do. More importantly, these can be used to let them appear to be doing things they would not normally do. I've capitalized the commands in the explanations below, but like all commands they will work regardless of case.
MPJUNK   object(s)
This works like the JUNK command, allowing your mob to get rid of stuff in its inventory by destroying it. Two things which make this command special are:
MPKILL   victim
This works like the KILL command, but it allows the mob to get around all the usual checks and restrictions there. For instance, your mob does not need to have a minimum level or be in a clan to MPKILL.
MPASOUND   text_string
Prints the text_string to the rooms (possibly several) around the mobile in the same manner as a death cry. Some uses include powerful aggressive mobs 'advertising' their presence, and minstrels or musicians performing to more than just the one room they are in. There is no "so-and-so says" or anything like that in front of the message. You need to code the whole message you want players to see, just as you want them to see it. Although the name of the command hints at obvious uses, the message does not HAVE to relate to a sound. Perhaps players are gripped with fear in the vicinity? Maybe they feel the earth shake? Maybe a chill wind blows in?
MPECHO   text_string
MPECHOAROUND   victim   text_string
MPECHOAT   victim   text_string
These commands output a message in your mob's room. As in MPASOUND, you need to specify the complete message that characters are to see. The three variants are:
One example suggestion for a tricky application was the shopkeeper who, as part of his fight_prog, does:
MPAT guard MPECHOAT guard rescue_please
which took me a while to understand, but which does this:
MPFORCE   victim   command
This works like the Immortal FORCE command, it causes the victim (either mob or mortal character) to perform the command specified. There is no message to the victim about being forced, but the victim sees himself performing the action, so you usually want to add an explanatory MPECHO. Even then, players doing things without or against their will is kind of strange, if not rude, so use this command sparingly.
MPGOTO   destination
This command works like the Immortal GOTO command: Your mob, upon performing this command, will leave its current location and reappear at the location specified by destination, which can be one of:
Your mob disappears from its previous room without a message of any sort, so unless characters there eventually bother to LOOK, they will not notice the mob left. Likewise, there is no message at the room where your mob arrives. If characters are to be informed of its arrival, as they usually should be, your mob will need to provide its own arrival message using MPECHO or something.
MPAT   destination   command
This is similar to the immortal AT command. Your mob does whatever command you specify as command, but it does it at the location you specify with destination. Your mob essentially does an MPGOTO to the destination room, performs the action, then MPGOTOs back to its original room. You specify the destination as for the MPGOTO command, with the same options and caveats. Your mob moves from location to location with no message as for MPGOTO, so it can be as obvious or as sneaky as it wants. One popular use of MPAT is not so much to make a certain action happen at the destination room as rather to not make it happen where the mob is currently interacting with other characters. I already mentioned the bunnies going elsewhere to die so they seem not to. Another example is the healer, who painstakingly loads a long list of objects and stuffs them into a newbie bag. The healer ducks into an unpopulated room to do this so that she can present the newbie with a full bag without spamming all over him.

Although command can be practically anything, I do not recommend coding another MPAT command as the command to do elsewhere. Not only does this not make any sense (why not go to the third location in the first place?) but also it's likely that your mob will never find its way back to the first location. Either that, or you'll crash the MUD.

MPMLOAD   vnum
This works like the Immortal command LOAD MOB. It will load a mobile with the specified vnum into your mob's room. Be careful with aggie mobs, you do not want to build a death trap for low levels. One example use for this is the bunny who loads another one of itself when killed, thus appearing to spring back to full life.
MPOLOAD   vnum   level
This works like the Immortal command LOAD OBJECT. It will load an object with the specified vnum into your mob's inventory. Contrary to other documentation, the object is NOT loaded into the mob's inventory if it does not have a TAKE flag. Just like the Imm command LOAD OBJ, the command will dump the object on the floor in the mob's room. Popular uses are giving out quest items or keys.
MPPURGE   argument
This works like the Immortal command PURGE. If there is no argument, it will purge all objects and mobs from the room, except for your mob itself. With an argument, it will purge whatever is named by the argument. Given an argument of $i (which refers to itself, as explained later>, it will even purge itself, but if this is not the last command in the mobprog bad things will happen when the program tries to keep running without the mob it's attached to. BEWARE: MPPURGE does not check the NOPURGE flag on objects or mobs. When it purges, it purges EVERYthing.
MPTRANSFER   victim   destination
This command moves victim(s) to destination. The victim(s) may be mobs, mortal players or ALL. ALL specifies all characters in the same room with your mob. destination works as for MPGOTO. If you don't specify any destination, the victim will be transferred into your mob's room. 
Your mob's victims do not receive a message about having been transferred, nor do they automatically LOOK in the new room. Thus, it is up to you to inform them of what happened (perhaps using MPECHO and/or MPFORCE ... LOOK), if you so choose.
MPCAST  'spell'
MPCAST  'spell'  victim
This command gives your mob the ability to cast any spell. There is no check for level or skill so any mob can cast any spell if you so choose. Try to keep your choice of spells appropriate. A smurf casting Wrath would be an eyesore to the MUD.
This section would not be complete without... you guessed it, an example!
>hitprcnt_prog 50~
sigh
mpecho Realizing $j is going to lose the fight, $I calls to Super Helga for help!
wave $n
mpecho A moment later...
mpechoaround $n $I disappears and $n is left fighting thin air.
mpechoat $n $I disappears and you are left fighting thin air.
mpgoto helga
~
This is a relatively simple MobProg. If the beggar is caught up in a fight and down to 50% of his HP, he sighs, announces his departure and cheats his way out of the fight by doing an MPGOTO Helga. Note the use of MPECHOAROUND to give a message to bystanders, then MPECHOAT to give the specific message to his foe. 

As promised earlier, for those of you who want to know EVERYthing, here is

The Hard Way To Connect MobProgs to Mobs

Actually, after all the preceding, this will not seem so hard any more. Note once again that this practice is currently not in use at Dizzy MUD. In addition, if you have your MobProgs in files, you can code in_file_progs underneath your actual mobs to associate MobProg files with them. This allows you to connect several files to one mob. The syntax for these in_file_progs looks like any trigger prog:
>in_file_prog   filename~


Congratulations! your area file is finished at this point. Do not forget the #$ at the end of your file to terminate your area file. The #$ must come on a line by itself and be followed by at least one or more empty lines. Leaving off this file termination or getting it wrong cause the MUD to crash at load time without even issuing an error message! 
<< Back to #SPECIALS Section 

  This page was last updated May 15, 2001