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:
-
Huh? and
-
You are thirsty.
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:
-
They are responding to a random trigger. This is explained later but essentially
every few seconds a binary coin is flipped to decide whether or not the
mob will do something. If the outcome is positive, the mob does its thing,
whatever that may be. It can have several 'things' to do.
-
They are responding to a message 'telling' them that another character
did something, i.e. they are responding to another character's action.
There are several different types of actions that can be used to set off
a response in a mob.
-
word
-
In a MobProg setting, a word is any sequence of characters not including
white space (space or end-of-line). Thus,
-
"rinky-dink" is one word.
-
In "How now, brown cow?", the second and fourth words are "now,"
and "cow?".
-
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:
-
As a list of (one or more) keywords. The act_prog will trigger if all of
the keywords you specify is contained in the message the mob receives.
-
As a letter 'p', followed by a space and a complete keyphrase.
The act_prog will trigger only if the message it receives contains the
exact sequence of words you specify, in the given order and with the given
spacing. Punctuation characters are taken to be part of the words of the
message, and once again, there is no partial matching. Thus, the correct
act_prog phrase trigger for a poke in the ribs would be:
>act_prog p pokes you in the ribs.~
Note the period. It's part of the "word", 'ribs.' . It's required for
an exact match of the keyphrase.
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:
-
bribe_prog
-
death_prog
-
entry_prog
-
fight_prog
-
give_prog
-
rand_prog
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:
-
How to set up several mutually exclusive 'probability' events such that
they have equal chances of happening: The first event has 1/3 chance
of happening. The second has 50% of the remaining 2/3, again 1/3. The last
event has 100% of the remaining 1/3 chance of happening. Notice the pattern?
1/3, 1/2, 1/1. The easy and foolproof way to set up any old sequence of
equally likely events.
-
Setting up hitprcnt_progs in ascending order so the lowest one will trigger
appropriately.
-
Setting up bribe_progs in descending order so the highest one will trigger
appropriately. Also note the value of 1 in the last one: As this is the
lowest possible amount for a money donation, it is guaranteed to
trigger if none of the others do. Of course, this kind of default trigger
needs to go at the end of a list of triggers of the same type.
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.
-
The 'Actor'
This is (at least) the second character in the
room, because your mob is observing his actions. Most MobProgs simply respond
to an action of another character.
Such actions include, among others:
-
entering a room
-
saying something or
-
giving something to our mob.
I'll call the character who does all these things the Actor.
There are 5 variables used to refer to the Actor:
| $n |
the first of thenames of the Actor, who performed the action
that set off the trigger. |
| $N |
the name and title of the Actor.
(rarely used) |
| $e |
he / she / it based on sex of Actor. |
| $m |
him / her / it based on sex of Actor. |
| $s |
his / hers / its based on sex of Actor. |
Here is a (very contrived) example of a bribe_prog using all of
these variables to respond to a donation to our beggar:
>bribe_prog 1~
thank $n
yell $N is a very kind person!
yell $e gave me some of $s money.
yell I am forever grateful to $m!
~ |
| if Elrac is the donor, this translates to:
thank Elrac
yell Elrac of Oberrad is a very kind person!
yell he gave me some of his money.
yell I am forever grateful to him! |
Note that this example will work no matter if the Actor is male, female
or sexless. The variables substitute him/her/it and other words as appropriate.
However, because of the $N (name and title), it will probably not work
if the generous donor is a mob.
The 'he' in the second sentence should be capitalized, but is not. MobProgging
does have limits, alas.
-
The Direct Object
Other than just appearing on the scene
or interacting with our mob, the Actor could also do something to or with
an object. There are cases involving 2 objects which I'll get to later,
but for now assume there is only one. Some things the actor can do with
one object are: Getting it, dropping it, eating it or giving it to your
mob.
Here are the variables used to refer to such a Direct Object:
| $o |
the first of the keywordss of the direct object (The
object NActor does something to).
If an object's keyword field says 'bagel cream cheese', $o would yield
'bagel'. |
| $O |
the short description of the direct object |
| $a |
a / an based on first letter of direct object |
Example:
>act_prog drops~
point $n
say Hey $n, you dropped $O!
~ |
| If Elrac drops his Thunderstriker, this works out to:
point Elrac
say Hey Elrac, you dropped Thunderstriker! |
-
The Indirect Object
This one doesn't see too much use. We're talking
about the second object involved in an action, such as the backpack in
"Elrac puts a pie in his backpack." The direct object in this sentence
is the pie, but the backpack is also involved... indirectly. Other documentation
also calls this the 'secondary object'. Here are the variable names:
| $p |
the first of the keywordss of the indirect object |
| $P |
the short description of the indirect object |
| $A |
a / an based on first letter of indirect object |
Example:
>act_prog puts in~
sigh
say I wish I had $A $P to put my $O in!
~ |
| "Elrac puts longsword in his scabbard" yields:
sigh
say I wish I had a scabbard to put my sword in! |
WARNING:
There's a potential problem with using the above "Indirect Object"
variables. Because the problem is shared with the "Victim" variables, below,
the problem is explained in detail in the Victim
Description Warning.
-
The Victim
If you get 3 characters into the same room, your mob
could end up watching another character (the Actor) do something to the
third character, who is sometimes called the target but whom I'll call
the Victim. You could imagine a setting where your mob is a guard
watching out for fights in the room. The Victim, of course, does not need
to be an actual victim of violence; if the Actor does anything to a character,
that character is just called the Victim for the purpose of discussing
these variables:
| $t |
the first of the names of a secondary character target, the
one Actor does something to. |
| $T |
| for mobs: |
the short description |
of the target character |
| for players: |
the name and title |
|
| $E |
he / she / it based on sex of Victim. |
| $M |
him / her / it based on sex of Victim. |
| $S |
his / hers / its based on sex of Victim. |
Example:
Doh, I can't think of one that's reasonably assured of working all the
time. Triggers alone are not enough to tell whether the victim of an action
was your mob or a third mob (i.e. a real Victim), so it's not possible
at this point to produce an appropriate response. This problem is fixed
by IF Statements, later on.
WARNING:
In the internal plumbing of act messages, the same data slot is
used for the Victim and for the Indirect Object. This saves space because
any action can have only either a victim or an indirect object but never
both. Well, it may be possible in English grammar but it just doesn't seem
to happen in the MUD. So what ends up happening here is that if an action
has a victim, that victim's name will end up both in $t and the indirect
object variable, $p (see below). If an action has an indirect object, the
object's name will end up both in $p and $t. If you're just using the name
in a command or a message that isn't so bad, it may look stupid but will
do no further harm. If you use $p or $t in an IF statement
(see below) that is specific to characters or objects and it's mismatched,
you're in trouble. In the happy case, your mobprog will just work incorrectly.
However, it's also quite likely that the MUD will crash!
-
Your mob
There is one character you can always count on to
be around when your MobProg runs: The mob itself. In actions performed
to itself, your commands can easily refer to 'self'. If the mob speaks
of itself, you can use 'I', 'me' and 'my', which English grammar calls
'the first person'. So the following set of variables is needed only when
the mob refers to itself in the 3rd person in an EMOTE or some other command,
or if the same MobProg is attached to several mobs and these need to identify
themselves by name.
Here are the 5 variables which your mobprog can use to refer to its
own mob:
| $i |
the first of the names of your mob
(generally prefer $I) |
| $I |
the short description of your mob. |
| $j |
he / she / it based on sex of your mob. |
| $k |
him / her / it based on sex of your mob. |
| $l |
his / hers / its based on sex of your mob. |
Example:
>greet_prog 100~
say Hello, I am $I.
~ |
| for the poor beggar, this translates to:
say Hello, I am a poor beggar. |
-
The Random Character
As discussed above, mobs mostly take action
based on the action of another character or on a random impulse. If you
want your mobile to start interacting with someone in its room,
you don't have an Actor you can use to direct the mob's commands
at. Instead, the mob must choose a character in the room at random to be
the target of its action. The variable $r and its brethren allow us to
do just this.
| $r |
the first of the names of a random char in the room with the
mobile
(never the same as your mob itself) |
| $R |
| for mobs: |
the short description |
of the random char |
| for players: |
the name and title |
|
| $J |
he / she / it based on sex of the random char. |
| $K |
him / her / it based on sex of the random char. |
| $L |
his / hers / its based on sex of the random char. |
Note that this random character can be either a mob or a player, but will
never be your mob itself. If there is no other character in the room, $r
will probably end up being an empty string, but this doesn't matter much
because nobody will be there to watch your mob bungle its grammar.
Example:
>rand_prog 20~
say Mirror, mirror on the wall...
ponder
say $r is the ugliest here!
~ |
| We don't know whom the beggar will point out. That's the idea behind
'random'. |
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:
-
The beggar is assumed to be sleeping most of the time, and sometimes snores.
Without further checks, he would also snore in a fight!
-
If the beggar's room is frequented by wandering mobs, it might get spammy
if he greets every character entering. It would be nice if he could single
out only the players for greeting. Mobs are unlikely to donate money anyway.
-
I'd like to complete the Victim example, above, but as yet we can't tell
the differences between actions directed at your mob and those affecting
third parties, i.e. true Victims.
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 )
"true" 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:
-
normal MUD commands to be performed by your MOB, including the MobProg-Only
Commands described later
-
complete IF statements
(that's right, you can have IF statements inside of IF
statements inside of...)
-
BREAK statements.
A BREAK statement will bail you right out of the processing
of the current trigger, no matter how deeply you may find yourself nested
in IF statements. You write BREAK like a normal MUD command,
and it essentially means, "this is the last command I intend to do for
this trigger."
BREAK statements may only be used as part of the command sets
inside IF statements. They make no sense anywhere else because if
you wanted to execute no more commands elsewhere, you could simply write
no more commands.
Even inside an IF, BREAK statements make sense only at the end
of a command set, because any commands afterthe BREAK
would never be performed anyway. Of course, it's legal and sometimes useful
to write a BREAK as the only statement of a command set,
as your needs and circumstances dictate.
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.
-
The bitwise AND operator ( & )
yields true if the numbers on both sides have at least one bit
set in the same position. This is generally used in tests for flag bits
and comes in handy for the isaffected() test but nowhere else I can think
of.
-
The bitwise OR operator ( | )
returns true if either of the numbers on both sides of it is
not 0. I can't think of any use for this.
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:
-
There is no message to anyone about the process, it happens silently and
spam-lessly.
-
Arguments like all.bread or even all are allowed for object(s),
so you can use it to wipe out an entire inventory.
-
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:
-
MPECHO creates a message seen by everyone in the same room with
the mob.
-
MPECHOAT sends the message only to the specified victim in
the room. The word 'victim' doesn't imply a fight, of course. Consider
it a 'message target'.
-
MPECHOAROUND sends the message to everyone in the room except
your mob and its victim.
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:
-
goes to a guard's location (you'd be advised to use a more specific name
for the exact guard you want), there to do the following:
-
send the following message to exactly one character, namely the guard:
-
rescue_please is a string not likely to appear in a normal action;
but presumably the guard has an act_prog sensitive to this string
and will come to the merchant's rescue. Note that although the string is
used in something like an ACT, it doesn't matter that it's weird because
only the intended recipient, the guard, will ever see it.
-
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:
-
A room vnum; this is the most assured of working, especially if the room
you specify is in your area
-
The name of a mob; you will want this to be very specific, and even then
it could fail if the target mob is killed or moved. Anyway, if the target
mob is found, the mob executing the command will move to the room at which
the target mob is.
-
The name of a player; probably not a good idea as they move around a lot,
can have any old name and are often out of the game. If successful, though,
the command will take your mob to the player's current room.
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.
-
Collect your MobProgs into groups such that one or more groups of
MobProgs can be attached to each mob that needs them. You cannot attach
parts of groups, it's all or nothing. But you can give each mob more than
one group of MobProgs.
-
Write each group of MobProgs into a separate file (there may be a special
directory or set of files designated for this purpose on your MUD -- ask
your Coders). Conventionally, each of the files containing MobProgs has
an extension of .MOB or .MP
-
In your .ARE (area) file, as the last section, start up a #MOBPROGS
section. Follow this with lines of the form:
| M |
mob-vnum |
MobProg-filename |
Each of these lines names a mob that you want to attach a MobProg to, and
names the file that contains that MobProg.
After all your M lines, code a line with only an S on
it to end your #MOBPROGS section.
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!
| |
This page was last updated
May 15, 2001.
|