Main Page

Area Building Docs
Mob Program Examples

Mob Program How-To Doc



Originally appeared in:

        Merc release 2.2

        Wednesday 24 November 1993



        N'atas-Ha natasha@gs118.sp.cs.cmu.edu

        Kahn



Modified for ROM 2.4 in January 1996

        Newt@Imperium Gothique



Last modified on 02/28/98 5:08AM.



TABLE OF CONTENTS



        The Basic Idea

        About This Version

        MOBprogram Syntax

        Linking MOBprograms

        Trigger Types

        Variables

        Control Flow Syntax

        Operators

        If_checks in Control Flow

        New Commands of Interest

        Regarding CPU Slowdown

        Loading Mobiles and Objects

        Miscellaneous Information

        --------------------------

        Quick Reference Sheet

        Examples



-----------------------------The Basic Idea---------------------------------



        Ever wonder why most muds either seem dead or overcrowded?  The answer

is probably partially due to the fact that the mobiles never do anything but

wait to be slaughtered.  Unless someone has gone to great lengths and added

many special procedures, most mobiles have no idea you are in the room with

them and rarely listen to what you say.  The typical Midgaard mayor wanders

happily along even when the populace pokes him, waves his City Key about,

unlocks his gates, or frenches his secretary, etc.  So a way to give the mobiles

a bit more spirit would be neat.  Enter the MOBprograms.



TRIGGERS AND SCRIPTS



        The backbone of the MOBprograms shall be called triggers from this

point on.  Essentially, they are procedure calls placed in sneaky places in the

mud code which provide the context for what is going on around the mobile.  So,

if something happens in the mobile's room and a trigger is activated, then a

list of commands is sent to the interpreter in the mobile's name, thus making

her/it/him do an appropriate something.



VARIABLES



        Since knowing the appropriate response for every mobile to every

possible trigger is not easy, this command list shouldn't be a rigid script, but

needs to be somehow unique for the mobile and the situation.  However, in order

to know the situation, a mobile needs to know more about the trigger than that

it just happened.  So, we have to include some sort of variables as well to set

the context appropriately.



MOBPROGRAMS VS. SPEC_PROCS



        As most implementors know, most area creators are not versed in coding,

but usually have great ideas.  Therefore, whatever system is used needs to be

quite simple.  This is not to demean creators in anyway.  Simply, it is useless

to have a powerful system, if the only person able to write anything is someone

who finds C coding in general to be exciting and non frustrating.  If that is

going to be the case, then stick to the special procedures, since there is no

bound to what a complex special procedure can accomplish.  Yet, from experience

working on several muds, most admins and implementors prefer not to be writing

one shot spec_procs to satisfy the needs of their creators.



        Thus, the basic idea:  let mobiles react to a myriad of mud

events/situations by having them perform a list of commands which can be

tailored to the moment through a simple and unintimidating scheme usable by any

creator.



---------------------------About This Version-------------------------------



        My implementation of MOBprograms owes a lot to the original MOBprogram

code by Natasha.  However, having heard reports about un stability of the code

supplied, and because the code seemed unnecessarily complex to me, I decided to

rewrite the MOBprogram driver.  Admittedly, I have dropped out several features

that were present in the original version, such as reacting to several triggers

at once and string comparison in if_checks. On the other hand, the MOBprogram

code has been simplified and made more stable (there are no memory leaks), and

several new if_checks and MOBcommands have been added.  The system of linking

MOBprograms to mobiles has been changed to allow procedure-like calls.

        This version is an adaptation of my earlier MOBprogram system I created

for Imperium Gothique MUD.  The IG system has object and room programs as well,

but I chose to omit them from this version.



        -- Newt



Newt has graciously permitted us access to his Ursus Mud source code.  From

this code we have extracted the object and room programs for adaptation to

the Abysmal Realms Mud



	-- Msocorcim



----------------------------MOBprogram Syntax--------------------------------



        The simplest way to describe any syntax is by example, so here goes.

First, define the notation: anything contained in braces {} is required,

anything in brackets [] is optional, anything in quotes "" is a case

insensitive literal, NL refers to a required new-line.  The meanings of the

labels used will be described following the syntax diagram.

        To use MOBprograms, you must add a #MOBPROGS section(s) to your area

file(s).



Section syntax:



#MOBPROGS

#{Vnum}

{program_command_1} NL

{program_command_2} NL

{program_command_3} NL

     .   .   .

{program_command_N} NL

"~" NL

     .   .   .

#0



-- Explanations

A VNUM is the MOBprogram virtual number that identifies the program the number

must be unique across area files (like mobile and object vnums). A

PROGRAM_COMMAND can be any legal mud command, or a control flow command.



NOTE 1:  Any white spaces (space, tab, newline) are NOT stripped from the

programs when loading the database (why? because I'm too damn lazy to have

implemented it).  Thus, to save memory and execution time, omit all unnecessary

spaces from your MOBprogram scripts.  If you must have indentation, use TAB.



NOTE 2:  MOBprograms do NOT have to be in the same area file as the mobile

definitions, since the programs are linked to the mobiles after the database

has been loaded.  A MOBprogram can also be used as a subroutine (see MOB CALL

command) without having to be linked to any mobile.



-- Example

#MOBPROGS

#3001

say Hey, no loitering!

poke $n

~

#0



--------------------------Linking MOBprograms--------------------------------



        Once you've written your MOBprograms, you must link the programs to

appropriate mobiles.  In the #MOBILES section, for each mobile you wish to have

a MOBprogram, add lines of the following type to the end of the mobile

definition:



        "M" {Keyword} {Vnum} {Argument}~ NL



--Explanations

The KEYWORD is a single word, see below for explanations.

The VNUM is the MOBprogram virtual number.

The ARGUMENT is the argument that triggers the event.

--Example



M act 3001 sits down~



In the above example, an ACT trigger is defined. When the mobile sees someone

sitting down in the room, the mobile will execute program number 3001 (defined

in #MOBPROGS section).



NOTE:  Several mobiles can use the same MOBprogram, i.e. MOBprograms can be

SHARED with several mobiles.  The keyword and trigger argument can be different

for each mobile even if they share the same MOBprogram code.



-----------------------------Trigger Types----------------------------------



        Here's a summary of triggers:



        Triggers are fairly easy to add, but this basic list should hold for

most needs.  Their names, argument list syntaxes, and translation into more

articulate english are given below:



===================

        ACT

===================

Keyword : 'act'

Argument: string

Programs: mobile



The argument is a phrase, a text string.  The trigger is activated whenever the

phrase is contained in the act() message.



NOTE:  Most general trigger.  Applies to almost every event which happens in

the mud.  Anytime the function act() is called with a message to be delivered

TO_CHAR, TO_VICT, TO_ROOM, etc., the act can be triggered.  Basically this will

trigger on almost everything you'll ever want.  Output of "say", "emote", and

all public channels ("shout", "gossip", etc.) does not trigger this event.





===================

      SPEECH

===================

Keyword : 'speech'

Argument: string



NOTE:  This is only triggered when the phrase is contained in a message which

has been said by a PC in the same room as the mob.  The PC restriction is not

necessary, but makes infinite loops between two talking mobiles impossible.  It

also makes it impossible for two NPCs to stand and discuss the weather however.





===================

      RANDOM

===================

Keyword : 'random'

Argument: number



The argument is a number between 0 and 100 inclusive, with 0 as no chance

that the event will trigger and 100 as the event always being triggered.



NOTE:  This trigger is checked at each PULSE_MOBILE and if the argument is

greater than or equal to a percentage roll the trigger is activated.  Thus

'random 25' would activate 25% of the time. This will happen even if there is

no PC in the room with the mob, but there must be players in the same area.  It

is useful to give mobiles a bit of a personality.  For instance a janitor who

stops to spit tobacco, or complain about the hours, or wonder why there are no

woman janitors on muds, or a fido which barks or growls or pees on the curb is

much more alive than one which just sits there scavenging.  Note that this

trigger is checked only when there are players in the area.  If you want this

event to be triggered always, you must set the ACT_UPDATE_ALWAYS flag of the

mobile.





===================

  GREET/GREET ALL

===================

Keyword : 'greet'

Argument: number



Argument is as per RANDOM.



NOTE:  Whenever someone enters the room with the mobile, and the mobile saw the

person enter, this is checked.  Good for shopkeepers who want to welcome

customers, or for pseudo-aggressive mobiles which need to discriminate on who

they attack.



NOTE:  Greet trigger activates only when the mobile is not busy (fighting,

sitting, sleeping etc.).  If you want to be sure to catch all players, use

grall.



Keyword : 'grall'

Argument: number



Argument is as per RANDOM.



NOTE:  Like greet, but it can be triggered even if the mobile didn't see the

arrival (i.e. sneak, invis, etc) or is busy. Most useful for faking teleport

rooms or for impassable guardians.





===================

      ENTRY

===================

Keyword : 'entry'

Argument: number



The argument number is as per RANDOM.



NOTE:  The opposite of greet trigger.  Whenever the mobile itself enters a new

room, this can be triggered.  Useful for looking around, or waving or other

things that real PCs do when they arrive at a crowded room. IMPORTANT:  In an

entry program, the mobile can only refer to a random pc ($r in if checks) --

there's no way to know how many PCs exist in the room the mobile enters!  Also,

you must check visibility of the target in your program.





===================

   EXIT/EXIT ALL

===================

Keyword : 'exit'

Argument: number



Argument is the exit number (0:north, 1:east, 2:south, 3:west, etc.)



NOTE:  The opposite of entry trigger. This is activated when PC tries to leave

a room through an exit indicated by the argument, and the mobile sees the

person leave. Useful for having a single guardian to watch several exits. An

exit trigger works better than an entry trigger, since you can refer to a

specific PC instead of a random PC. IMPORTANT: If this event is triggered, the

victim will not move through the exit. If necessary, you must move the

character yourself in your program (see MOB TRANSFER/MOB GTRANSFER). Also, this

event is not triggered when a character flees from combat or the mobile is not

in its default position.



Keyword : 'exall'

Argument: number



Argument is as per EXIT.



NOTE:  The same as exit trigger, but it can be triggered even if the mobile

cannot see the person trying to leave the room or if the mobile is busy.





===================

       GIVE

===================

Keyword : 'give'

Argument: string OR object vnum



The argument is either the a string containing words to be matched

against the keywords of the object, or the word "all";

e.g. argument "long sword" will match to objects "long bow" and

     "small sword".

Alternatively, the argument can be the virtual number of a single object.



NOTE:   This is triggered whenever something is given to the mobile.  Best used

for quests.  Since the first successful trigger is the only one of this type

which is processed, having an "all" argument in the script at the end of the

MOBprogram list is essentially a default response.





===================

      BRIBE

===================

Keyword : 'bribe'

Argument: number



The argument is any positive integer number.



NOTE:  This trigger is activated whenever money is given to the mobile. If the

amount given exceeds the number, then process the commands. Note again, that an

argument of '1' would act as a default response. Also note that if the script

is not triggered (because of too little money having been given), the mobile

still keeps the money...



ROM 2.4 NOTE: Since ROM 2.4 has two different types of currency (gold and

silver coins), for bribe trigger the amount to be given is converted to silver

coins with the rate of 1 gold = 100 silver. Thus, the number in the argument

should be the expected amount in silver coins.





===================

       KILL

===================

Keyword : 'kill'

Argument: number



Argument is as per RANDOM.



NOTE:  This trigger is checked whenever a PC attacks the mobile. The check

occurs only ONCE, in the beginning of combat. Useful for summoning assistance

etc.  (See MOB MLOAD).





===================

       FIGHT

===================

Keyword : 'fight'

Argument: number



Argument is as per RANDOM.



NOTE:  Useful for giving mobiles combat attitude. It is checked every

PULSE_VIOLENCE when the mobile is fighting. Can be used to cast spells (see MOB

CAST), curse at the opponent, or whatever. Only the first successful one will

be processed to save time.  Also, this means that the mobile wont get lucky and

1. curse, cast a fireball and 2. spit on the player, cast another fireball in

the same pulse.





===================

  HIT PERCENTAGE

===================

Keyword : 'hpcnt'

Argument: number



Argument is as per RANDOM.



NOTE:  Is activated at each PULSE_VIOLENCE when the mobile is fighting. It

checks to see if the hitpoints of the mobile are below the given percentage.

Multiple hpcnt triggers should be listed in increasing order of percent since a

40% will always be activated before a 20% and, only the first successful

trigger is performed. (See also MOB FLEE).





===================

      DEATH

===================

Keyword : 'death'

Argument: number



Argument is as per RANDOM..



NOTE:  When the mobile dies, if the random percentage is less than the argument

the mobile performs the MOBprogram commands rather than the usual death_cry()

sequence.  This is done before the corpse is made, so the commands can be

considered the mobiles last gasp.  It could perhaps destroy the items it was

holding (see MOB REMOVE and MOB JUNK), or create some (see MOB OLOAD), or cast

a spell (see MOB CAST) on the killer and the room, or even goto a new location

(see MOB GOTO) and die there (with a text message, the corpse would seem to

vanish) The position of the mobile is set to STANDING, and so it can do all the

normal commands, without worrying about being DEAD.  However, even if the

mobile restores itself to full hitpoints, it will still die.



NOTE:  This is not a way to immortal mobiles.  However, the last thing this

mobile does could be to goto some vacant room, load a fresh version of itself,

drop all its items, force the new mobile to get all the items and wear them,

send the new mobile back to the character who killed it and force the new

mobile to attack that character.  Along with a text message which said the

mobile restored itself, this might be a convincing effect. (Note that your

kitten could turn into a dragon this way too).





===================

      DELAY

===================

Keyword : 'delay'

Argument: number



Argument is as per RANDOM.



NOTE:  This trigger activates when the delay of a mobile (set with the MOB

DELAY command) expires. This trigger can be used to create staged mobile

behavior, for example, a guardian could see a player entering a room, give a

warning and activate a delay. If the player is still present when the delay

expires, the guard would attack the player. (See also MOB REMEMBER). A mobile

can have several delay triggers, but every time the delay timer expires, all

the triggers are checked and the first successful one executed.





===================

    SURRENDER

===================

Keyword : 'surr'

Argument: number



Argument is as per RANDOM.



NOTE:   This trigger activates when the mobile is fighting and the opponent

issues a "surrender" command. When triggered, both parties will cease fighting,

and the mobile can accept the surrender (perhaps taking all equipment from the

character with MOB REMOVE).



NOTE: If the mobile does not accept the surrender, it must resume fighting with

MOB KILL.



NOTE:  If a character surrenders and the mobile does not have a surrender

trigger, or the trigger does not activate, the fight resumes normally.





===================

    PULL/PRESS

===================

Keyword : 'pull'

Argument: string



The argument is a string containing keywords to be matched against the words

entered by the player.

e.g. "rope chain" would match if the player used either 'pull rope' OR

     'pull chain'



NOTE:  This trigger will activate when a PC types in a matching phrase for the

PULL command.



Keyword : 'push'

Argument: string



The argument is a string containing keywords to be matched against the words

entered by the player.

e.g. "button switch" would match if the player used either 'push button' OR

     'push switch'



NOTE:  This trigger will activate when a PC types in a matching phrase for the

PUSH command.



NOTE:  Push is current set to the player command "press".



---------------------------------------------------------------------------



NOTE:  No MOBprograms will be successful when the mobile is charmed (since it

has no self volition, it should act like it has none) to protect mobiles which

are given special powers from being implemented by a player.



------------------------------Variables------------------------------------



        To make things come alive, variables are needed.  These are represented

in the MOBprograms by using a dollar sign convention as in the socials.  When

the mud command is processed, these variables are expanded into the values shown

below.  Usually, it is best to use the short descriptions of mobiles and the

names of players when speaking them, but if you are performing an action to

someone almost always you want the name.  The title field for players is an

extra that probably wont often be used.  Without further hesitation... the

variables:



$i      the first of the names of the mobile itself.

$I      the short description of the mobile itself.

$n      the name of whomever caused the trigger to happen.

$N      the name and title of whomever caused the trigger to happen.

$t      the name of a secondary character target (i.e A smiles at B)

$T      the short description, or name and title of target (NPC vs PC)

$r(x)   the name of a random PC in the room with the mobile

$R(x)   the short description, or name and title of the random PC

$q      the name of the MOBprogram target (see MOB REMEMBER)

$Q      the short description of the MOBprogram target



$e      he,she,it based on sex of $n.

$E      he,she,it based on sex of $t.

$j      he,she,it based on sex of $i.

$J      he,she,it based on sex of $r.



$m      him,her,it based on sex of $n.

$M      him,her,it based on sex of $t.

$k      him,her,it based on sex of $i.

$K      him,her,it based on sex of $r.



$s      his,hers,its based on sex of $n.

$S      his,hers,its based on sex of $t.

$l      his,hers,its based on sex of $i.

$L      his,hers,its based on sex of $r.



$o      the first of the names of the primary object (i.e A drops B)

$O      the short description of the primary object

$p      the first of the names of the secondary object (i.e A puts B in C)

$P      the short description of the secondary object



For the $r/$R, $K, and $L tokens, there is a sub-token that can be specified:

$r(a)	chose a random char from all available characters in the room

$r(m)	chose a random mob from all available characters in the room

$r(p)	chose a random PC from all available characters in the room

$r(v)	chose a random mob with the same vnum as the mob

$r(g)	chose a random character from all chararacters grouped with the mob



        Also, in if_checks, the accepted variables are the basic ones

(i,n,t,r,o,p,q).  If a variable is referenced that doesn’t exist, then the

value is simply left blank or replaced with "someone"/"something" in

output (i.e referring to $o when the trigger is: A kisses B)



        If variable $q has not been defined, it is automatically set to the

last player that has triggered the program being executed (i.e. variable $n).

Once $q has been defined, it can be modified with MOB REMEMBER and MOB

FORGET commands in a program. Variable $q lets the mobile "remember" a player

across different programs, which can be useful. Note that $q is set

automatically only the FIRST TIME the mobile executes a program, every time

thereafter it must be set with MOB REMEMBER.



        The only problem with the variables is that the secondary object and

the secondary target are passed by act() in the same location.  This means that

if you reference $t in an  A puts B in C  situation, the result will probably

be a happy mud crash or some weird side effect, especially if $t is used in an

if_check (i.e. if isnpc($t) in the above situation) The basic fix for this is

to change everyone who calls the act() procedure to specify a secondary object

and a secondary character. But that is a fairly comprehensive trivial twiddle,

so we left it the way it is so that, you aren't forced to make all those

twiddles to use the MOBprograms.



Note:  always use $N instead of $n when using communication commands such as

say, gossip, etc.  The use of $n is for actual manipulative commands that have

nothing to do with communication.



e.g. Compare "say Hello $n!" with "say Hello $N!" on player characters.  In

most cases both of these will return identical results.  But if a player has

the mimic spell, then using the first instance (with the $n) will still return

the player's actual name, not the mimic description: "Hello Garag!".  If $N

were used it would return "Hello janitor!" (or whatever Garag happened to be

mimiced as).



---------------------------Control Flow Syntax------------------------------



        In place of any legal mud command in a MOBprogram, one can substitute a

flow of control command.  Here is the syntax for a flow of control command.

The parts between [ and ] are optional:



"if" " " {[!]if_check_1} {argument} [ {operator} {value} ] NL

[ "or" " " {[!]if_check_2} {argument} [ {operator} {value} ] NL ]

[ "or" " " {[!]if_check_N} {argument} [ {operator} {value} ] NL ]

                   .           .            .

[ "and" " " {[!]if_check_N} {argument} [ {operator} {value} ] NL ]

[ "and" " " {[!]if_check_N} {argument} [ {operator} {value} ] NL ]

                   .           .            .



        [ {program_command_1} NL ]

        [ {program_command_2} NL ]

              .   .   .

        [ "break" NL ]

              .   .   .

        [ {program_command_N} NL ]



[ "else" NL ]



        [ {program_command_1} NL ]

        [ {program_command_2} NL ]

              .   .   .

        [ "break" NL ]

              .   .   .

        [ {program_command_N} NL ]



"endif" NL



        Basically, it is: an 'if' line, followed by zero or more 'or' lines,

followed by zero of more 'and' lines ('and' and 'or' lines can be in any order)

followed by zero or more legal mud commands, which may contain a 'break' line,

possibly followed by an 'else' line , followed by zero or more legal mud

commands, which may contain a 'break' line, followed by an 'endif' line.



The only new syntax labels are all in the IF/OR/AND line:



--Explanations



An IF_CHECK is a string which describes under what context to compare things.

The ARGUMENT is the reference point from which the LHS of an expression comes.

The OPERATOR indicates how the LHS and RHS are going to be compared. The VALUE

is the RHS of the expression to be compared by the operator.



If a ! is placed before the argument, the evaluation results are logical NOT of

that evaluation.

e.g. if !affected $n blind

     Would execute if the character was NOT blinded.



The BREAK command bails out of the entire MOBprogram regardless of the level if

nesting. (END is a synonym for BREAK).



If that looks confusing, skip to the end of the document and review the

examples.  Hopefully that should clear things, otherwise you'll probably have

to give me a mail since examples are the best way I know to explain syntax.



---------------------------------Do Loop------------------------------------



Syntax:

do

        [ {program_command_1} NL ]

        [ {program_command_2} NL ]

              .   .   .

        [ {program_command_N} NL ]

loop



The do-loop construct will execute the commands within it for each character

present in the room.  This does not take into account if the mobile can

see the characters, or if the characters are NPCs or PCs.



The following MOBprogram will cause the mobile to grin at every NPC in the room

and glare at all the PCs:



do

	if isnpc $n

	grin $n

	else

	glare $n

	endif

loop



--------------------------------Operators-----------------------------------



        Most of the basic numeric operators are legal and perform the same

function as in C:



==      is equal to

!=      is not equal to

>       is greater than

=      is greater than or equal to

<= is less than or equal to If_Checks In Control Flow

----------------------------------If Checks----------------------------------- 

The provided list of if_checks and their arguments are below. They should all

be fairly obvious in what they do, but some of the more obtuse deserve a slight

explanation. Any '="='" operator can be replaced with any of the available ones

described above. The argument $* refers to any of the variables which make sense

for that if_check (i.e. for an if_check which is referencing a person the only

valid variables would be $i, $n, $t, $r or $q) A value type of string is a

sequence of characters. It does not need to be included in quotes or anything

like that (i.e. if name $n fido )

There are five types of if checks:

Type 1: Keyword and value rand num Is random percentage (1 to 100) greater than

num e.g. rand 25 would return TRUE 25% of the time

mobhere vnum Is a NPC with this vnum in the room

mobhere name Is a NPC with this name in the room

objhere vnum Is an object with this vnum in the room

objhere name Is an object with this name in the room

mobexists name Does NPC 'name' exist somewhere in the world

objexists name Does object 'name' exist somewhere in the world

Type 2: Keyword, comparison and value

people="=" integer Is the number of people in the room equal to integer

players="=" integer Is the number of PCs in the room equal to integer

mobs="=" integer Is the number of NPCs in the room equal to integer

clones="=" integer Is the number of NPCs in the room with the same vnum as

the NPC who activated the program equal to integer

order="=" integer Is the order (of several similar NPCs) of the NPC who

activated the trigger equal to integer

hour="=" integer Is the hour (game time) equal to integer

Type 3: Keyword and actor

isnpc $* Is $* an NPC ispc $* Is $* a PC

isgood $* Does $* have a good alignment

isneutral $* Does $* have a neutral alignment

isevil $* Does $* have an evil alignment

isimmort $* Is $* an immortal (level of $*> LEVEL_HERO)

ischarm    $*              Is $* affected by charm

isfollow   $*              Is $* a follower with their master in the room

isactive   $*              Is $*'s position > POS_SLEEPING

isdelay    $*              Does $* have a delayed MOBprogram pending

isvisible  $*              Is $* visible to NPC who activated the program

hastarget  $*              Does $* have a MOBprogram target in the room

istarget   $*              Is $* the target of NPC who activated the program

iskiller   $*              Does $* have a killer flag

isthief    $*              Does $* have a thief flag

istwit     $*              Does $* have a twit flag



Type 4: Keyword, actor and value



affected   $*   'affect'   Is $* affected by 'affect'

affected2  $*   'affect'   Is $* affected by 'affect' (for affect2 bits)

act        $*   'act'      Is $*'s ACT bit 'act' set

off        $*   'off'      Is $*'s OFF bit 'off' set

imm        $*   'imm'      Is $*'s IMM bit 'imm' set

carries    $*   'name'     Is $* carrying object 'name'

wears      $*   'name'     Is $* wearing object 'name'

has        $*   'type'     Does $* have object of item_type 'type'

uses       $*   'type'     Is $* wearing object of item_type 'type'

name       $*   'name'     Is $*'s name 'name'

pos        $*   'position' Is $*'s position 'position' (sleeping etc.)

clan       $*   'name'     Does $* belong to clan 'name', "none" = not clanned

race       $*   'name'     Is $* of race 'name'

class      $*   'name'     Is $*'s class 'name'

objtype    $*   'type'     Is $*'s item_type 'type'



Type 5: Keyword, actor, comparison and value



vnum       $*   == integer Is $*'s virtual number equal to integer

hpcnt      $*   == integer Is $*'s hitpoint percentage equal to integer

room       $*   == integer Is vnum of the room $* is in equal to integer

sex        $*   == integer Is $*'s sex equal to integer

truesex    $*   == integer Is $*'s true sex equal to integer

level      $*   == integer Is $*'s level equal to integer

align      $*   == integer Is $*'s alignment equal to integer

money      $*   == integer Does $* have money (in silver) equal to integer

objval#    $*   == integer Is $*->value[#] equal to integer (# from 0-4)



Type 6: Keyword, value, comparison and value



objcount  vnum == integer  Is the number of objects of vnum in the game equal to

                           integer





NOTE:  The original MERC 2.2 MOBprograms used parenthesis '(' and ')' around

variables.  In this version, they are not allowed. Also, parameters MUST BE

separated with spaces (if level $n<10 is NOT valid, correct syntax is:

if level $n < 10).

-----------------------New Commands Of Interest-----------------------------

1. GENERAL COMMANDS Syntax:

        SURRENDER This command can be issued in combat. If the one giving the
        
        command is a PC and the opponent is a NPC, the NPC will be checked
        
        for a surrender trigger. If the trigger activates, the fight will be
        
        terminated. Otherwise the combat will resume normally. Note that the
        
        mobile can resume the combat in the MOBprogram (see MOB KILL). If anyone
        
        (PC or NPC) surrenders to a PC, the combat will terminate. The PC can resume
        
        the combat with 'kill' command. With this command, and the use of surrender
        
        trigger, non-lethal combat can be implemented (arenas etc.).
        
2. DIAGNOSTIC COMMANDS

        These two new commands are available to immortal players.
        
        Syntax: MPSTAT [mobile] Displays the triggers and MOBprogram vnums defined
        
        for the mobile.
        
        Syntax: MPDUMP [vnum] Displays the MOBprogram code of given vnum.
        
3. MOBCOMMANDS

      MOBcommands are special commands that allow mobiles to perform immortal-like
      
      actions within a MOBprogram (transferring players or loading items, for example).
      
      Most MOBcommands them are wiz commands which have been changed to allow for mobiles
      
      to perform the commands. In this version of MOBprograms, players have been prevented
      
      from using these commands by adding a separate interpreter for MOBcommands. This also
      
      speeds up (in most cases) MOBprogram execution when MOBcommands are used. All
      
      MOBcommands are preceded with the word 'MOB' on the command line.
      
      Syntax: MOB ASOUND [string] MOB ZECHO [string] MOB GECHO [string] ASOUND prints the text
      
      string to the rooms around the mobile in the same manner as a death cry. This is really
      
      useful for powerful aggressives and is also nice for wandering minstrels or mobiles like
      
      that in concept. ZECHO prints the string to all players in the same area with the mobile.
      
      GECHO prints the string to all players in the game.
      
      Syntax: MOB ECHO [string]
      
      MOB ECHOAT [victim] [string]
      
      MOB ECHOAROUND [victim] [string] 
      
      ECHO displays the string to everyone in the room. ECHOAT displays the string to the victim only.
      
      ECHOAROUND displays the string to everyone except the victim. The three options let you tailor
      
      the message to goto victims or to do things sneaky like having a merchant do: mob at guard mob
      
      echoat guard rescue_please This coupled with a guard act trigger on rescue_please to: mob goto
      
      $n mob echo $I has arrived. It is an affective way of quickly bringing guards to the scene of an
      
      attack. (Note that the merchant has to be the only one of its kind in the game or have a unique
      
      name, otherwise the guard might go to different mobile...).
      
      Syntax: MOB MLOAD 

        MOB OLOAD  [level|'obj' [[max_count] load_count] ['r'|'w']]


        MLOAD creates a mobile and places it in the same room with the

        mobile.



        OLOAD loads the object into the inventory of the mobile.  If the

        item does not have the TAKE bit set, it will be placed in the

        room instead.  This lets a mobile distribute a quest item or load

        a key or something.



        Optional arguments are:

        level      : Sets the level of the object, default is the same as

                     the level of the mob loading it.  If 'obj' is specified,

                     this too will load the object at its default level.

        max_count  : Specifies the maximum number of the given vnum that

                     can be in the game at once.

        load_count : Load this many at once.  This will not exceed

                     'max_count' if that is specified.

        'r'        : Load the object to the room.

        'w'        : Wear the given object.



Syntax:  MOB KILL [victim]



        Lets a mobile kill a player without having to murder. Lots of

        MOBprograms end up with mpkill $n commands floating around. It

        works on both mobiles and players.



Syntax:  MOB FLEE



        Causes a mobile to unconditionally flee from combat. Can be used

        for example with the hit point percentage trigger to simulate

        "wimpy" behavior.



Syntax:  MOB REMOVE [victim] [vnum|'all']



        Lets the mobile to strip an object of given vnum from the victim.

        Objects removed are destroyed. If the vnum is replaced with "all",

        the whole inventory of the victim is destroyed. This command is

        probably most useful for extracting quest items from a player

        after a quest has been completed.



Syntax:  MOB JUNK [object]



        Destroys the object referred to in the mobile's inventory. It prints

        no message to the world and you can do things like junk all.bread or

        junk all. This is nice for having janitor mobiles clean out their

        inventory if they are carrying too much (have a MOBprogram trigger on

        the 'full inventory')



Syntax:  MOB PURGE [argument]



        Destroys the argument from the room of the mobile. Without an argument

        the result is the cleansing of all NPC's and items from the room with

        the exception of the mobile itself.  However, mppurge $i will indeed

        purge the mobile, but it MUST be the last command the mobile tries to

        do, otherwise the mud cant reference the acting mobile trying to do the

        commands and bad things happen.



Syntax:  MOB AT [location] [command]



        Performs the command at the designated location. Very useful for doing

        magic slight of hand tricks that leave players dumbfounded.. such as

        metamorphing mobiles, or guard summoning, or corpse vanishing.



Syntax:  MOB GOTO [location]



        Moves the mobile to the room or mobile or object requested. It makes

        no message of its departure or of its entrance, so these must be

        supplied with echo commands if they are desired.



Syntax:  MOB TRANSFER  [victim|'all'] [location]

         MOB GTRANSFER [victim]       [location]

         MOB FTRANSFER [victim]       [location]

         MOB OTRANSFER [object]       [location]



        Sends the victim to the destination or to the room of the mobile as a

        default.  if the victim is "all" then all the characters in the room

        of the mobile are transferred to the destination.  Good for starting

        quests or things like that.  There is no message given to the player

        that it has been transferred and the player doesn’t do a look at the

        new room unless the mob forces them to.

        Gtransfer works like transfer, except that the group the victim

        belongs to is transferred with the victim. Ftransfer works like

        Gtransfer, but the victims must be standing. Otransfer transfers an

        object in the room.



Syntax:  MOB FORCE  [victim|'all'] [command]

         MOB GFORCE [victim]       [command]

         MOB VFORCE [vnum]         [command]



        Forces the victim to do the designated command. The victim is not told

        that they are forced, they just do the command so usually some mpecho

        message is nice.  You can force players to remove belongings and give

        them to you, etc.  The player sees the normal command messages (such as

        removing the item and giving it away in the above example)  Again, if

        the victim is "all" then everyone in the mobiles room does the command.

        Gforce works like force except that it affects the group the victim

        belongs to.

        Vforce affects all mobiles with given vnum in the game world. This

        is useful for, for example, purging certain type of NPCs from the

        game (by forcing them to purge themselves).



Syntax:  MOB CAST [spell] [victim]



        Lets the mobile to cast spells. Beware, this does only crude validity

        checking and does not use up any mana. All spells are available

        regardless of the race or other abilities of the mobile. Casting the

        spell occurs silently, but spell effects are displayed normally.



Syntax:  MOB DAMAGE [victim|'all'] [min] [max] {lethal}



        Causes unconditional damage to the victim. Specifying "all" as

        victim causes damage to all characters in the room except the mobile.

        Min and max parameters define the minimum and maximum amounts of

        damage caused. By default, the damage is non-lethal, but by supplying

        the optional 'lethal' parameter, the damage can kill the victim.

        This command is silent, you must echo all messages yourself in the

        program. Useful for implementing special attacks for mobiles.



Syntax:  MOB DELAY

         MOB CANCEL



        MOB DELAY sets the time in PULSE_MOBILE after which the mobile's

        delay trigger is activated. If the mobile has a program defined

        for delay trigger, the program is executed when the timer expires.

        MOB CANCEL resets the delay timer.



Syntax:  MOB REMEMBER [victim]

         MOB FORGET



        This command enables the mobile to remember a player for future

        reference in a MOBprogram. The player can subsequently be referred

        as '$q' in programs activated by the mobile. MOB FORGET clears

        the target. Note that if the first time the mobile runs a program,

        $q is automatically set to the player who triggered the event.

        Most commonly this command is used in delayed programs, where the

        mobile has to remember the player who triggered the original

        event, for example to continue conversation.



Syntax:  MOB CALL [vnum] {victim} {target1} {target2}



        This command lets you call MOBprograms from within a running one,

        i.e. to call a MOBprogram subroutine. The first parameter is the

        vnum of the program to execute, the second is the victim's name

        (for example $n), and the third and fourth are optional object

        names. All other parameters except vnum can be replaced with

        word 'null' indicating ignored parameter.

        MOBprograms can be called recursively, but as a safety measure,

        parser allows only 5 recursions.



--------------------------Regarding CPU Slowdown-------------------------------



In the original MERC 2.2 MOBprogram documentation Nata'sha and Kahn wrote:

        "We have no real idea how slow this makes a mud.  However, you will

find that if you are judicious with your use of MOBprograms, you can either do

little damage, or even reduce the effort on your server!  This means that

mobile polling (including the rand_progs) need only be checked when players are

around.  This reduces computation of random_stuff a little, but it is still a

polling method, and subject to a basic inefficiency there.  However, aside from

the rand_progs, the only additional slowdowns will be when the mobile is

responding to the situation, and you would get that from a special procedure as

well (although MOBprograms are surely not as efficient as compiled C code)"

        I have used MOBprograms extensively in my own mud without adverse

effects.  This version of MOBprograms polls random triggers only when there are

players in the area, so the load is kept to minimum.  I would venture to claim

that in most cases, line lag will exceed machine lag even with ample and

complex use of MOBprograms.



--------------------------Loading Mobiles and Objects--------------------------



        No doubt you want to load objects and mobiles in your MOBprograms with

"mob oload" and "mob mload".  There are two problems connected to this.  One is

that mloaded mobiles will appear without equipment and the other is that it is

difficult to keep track of the number of created mobiles and objects.

        If you want to mobiles to appear in your area as a result of the

players' action, create a "storage room".  Define resets for the mobiles as

usual (equipment etc.) and place them in the storage room.  When you need to

use the mobiles, just "mob transfer" them to the location you want.  This is

better than creating mobiles on the fly, since you don't have to worry about

creating too many mobiles or equipping them, area resets take care of all that.

        If you have a MOBprogram that creates new mobiles, you might want to

make the mobiles "self-destructing".  This is easiest to do with a random

trigger that checks if the mobile is doing anything useful and possibly does

'mob purge $i'.

        Another possibility is to use a "purgemaster".  Create a storage room

with a single mobile.  Attach a random trigger that does 'mob purge' to that

mobile.  Now, when you need to get rid of anything, just 'mob transfer' the

mobile or item to purgemaster, and it will be destroyed sometime later.



-------------------------Miscellaneous Information-----------------------------



        There is really no limit to the number of MOBprograms a given mobile

can have.  However, the length of a single command block is limited by the

value of MAX_STRING_LENGTH.  In my version it was around 4k, so that is

probably about 100 lines.  The indentation spaces shown in the example above

are NOT required, but do make it easier to read (and debug).  HOWEVER, all

spaces and indentations are loaded into memory as a part of the program, so

you're using up memory unnecessarily.  Memory usage can also be reduced by

using subroutines (see MOB CALL).

        It IS possible to accidentally make mobiles which can trigger in loops.

Infinite loops have been prevented, but in case of a loop, the mobile behavior

is undefined.

        The list of variables and triggers and if_checks will grow continuously

as mud creators demand the ability to do certain things.  If you have a request

or if you have a new one, I don't mind hearing about them, and if you find

bugs, I shall gladly attempt to squash them for you.  As additions or fixes are

made, the code will occasionally be redistributed. However, if you want a

current version, please feel free to ask.  When the code is redistributed, a

file containing the change history from the original release will be provided

(when possible) to allow you to patch in the changes with low grief.



----------------------------------Credits-----------------------------------



        The reason this code was written was to enhance the playing experience

at ThePrincedom (a Merc 2.0 based world scheduled to open in October 1993)



        The original idea for this type of MOBprogram came from playing on:

WORLDS of CARNAGE, a dikumud implemented by Robbie Roberts and Aaron Buhr.

Aaron (known as Dimwit Flathead the First) was the original author from what I

have been told, and I hope he will not be totally offended and angered by my

coding and sharing a mimicked version with the world. This version is probably

not as good as the original and I do feel remorse for publishing the idea.

However, since Carnage has been down for months without a word of information

regarding its return, I am glad to let one of the best features live on in

future generations of MUDs.



        There are no objections to this code being shared, since, aside from a

nuclear destruction of all the Temples of Midgaard (excepting the original

one!!), bland mobiles are the greatest bane of Dikumuds today. It would be nice

to get a message saying you are using the code just for our references. We

shant answer questions from anyone until told where they are using the code.

*grin*  Since this code is not copyrighted, you of course don't have to do

anything we say, but it would be nice of you to put the mobprog help screen

into your database. and have mobinfo show up somewhere on a more visible help

screen (possibly tagged onto the bottom of credits as a see also...)



        I acknowledge all the work done by the original Diku authors as well as

those at Merc Industries and appreciate their willingness to share code.  Also,

quick thanks to Wraith for doing a little beta-installation testing.



N'Atas-Ha                                                    June, 1993

natasha@gs118.sp.cs.cmu.edu



        In addition to this DOC file credit section, I'd like to add a thank

you to Yaz, Mahatma, Zelda, and the rest of the 4th Realm crew for extensively

testing MOBProgram 2.1 for me.  You may see MOBPrograms in action as well as

their own "flavor" of mud at marble.bu.edu 4000.



Kahn                                                        Oct 28th, 1993

MERC Industries



        This driver was rewritten by me in summer '95. I also added room and

object programs (not in ROM 2.4 version). While I acknowledge the skill and

insight of the above people who conceived the original MOBprogram idea, they

should not be held responsible in any way for this release. I can't promise I

will be able to support this code in the future, use at your own risk. However,

if you're using this code, and/or have bug reports or improvements, I'd be glad

to hear from you. The revised MOBprograms can be seen in action at Imperium

Gothique, mud.pitek.fi 4000. This code may be freely used and distributed, but

some favorable publicity (such as having my name appended to your in-game

credits) would encourage me to develop this software.



Newt@Imperium Gothique                                  May 1995-Jan 1996

mn54196@uta.fi                                          (am I lazy or what?)



===================CUT HERE FOR QUICK REFERENCE SHEET========================



MOBprogram quick reference to triggers/variables/ifchecks/mobcommands



-----------------------------------------------------------------------------

Area file format

-----------------------------------------------------------------------------

#MOBILES



M {trigger} {program vnum} {argument}~



#MOBPROGS



#{program vnum}

{program code}~



-----------------------------------------------------------------------------

trigger    argument and what must happen to activate trigger

-----------------------------------------------------------------------------

act        STRING       to match from act() to mobile

speech     STRING       to match in dialogue (say, tell) to mobile

rand       PERCENT      chance to check whenever a PC is in the mobiles zone

bribe      INTEGER      minimum amount of silver coins given to mobile

give       OBJECT NAME, OBJECT VNUM or ALL to match when obj given to mobile

greet      PERCENT      chance to check if visible char enters mobile's room

grall      PERCENT      chance to check when any char enters mobile's room

entry      PERCENT      chance to check when mobile moves to a new room

exit       EXIT NUMBER  a visible char tries to exit mobile's room

exall      EXIT NUMBER  any char tries to exit mobile's room

kill       PERCENT      chance to check when the mobile begins fighting

fight      PERCENT      chance to check at fight_pulse if mobile is fighting

hpcnt      PERCENT      lower than mobile's hit/max_hit if mobile is fighting

death      PERCENT      chance to check after mobile has been slain

surr       PERCENT      chance to activate when a char surrenders to mobile



----------------------------------------------------------------------------

variable         mobile actor victim random target    object 2nd_object

-----------------------------------------------------------------------------

name               $i    $n     $t     $r    $q       $o       $p

shrt_desc/title    $I    $N     $T     $R    $Q       $O       $P

he/she/it          $j    $e     $E     $J    $X       --       --

him/her/it         $k    $m     $M     $L    $Y       --       --

his/hers/its       $l    $s     $S     $K    $Z       --       --

a/an               --    --     --     --    --       --       --



For the $r/$R, $K, and $L tokens, there is a sub-token that can be specified:

$r(a)	chose a random char from all available characters in the room

$r(m)	chose a random mob from all available characters in the room

$r(p)	chose a random PC from all available characters in the room

$r(v)	chose a random mob with the same vnum as the mob

$r(g)	chose a random character from all chararacters grouped with the mob



-----------------------------------------------------------------------------

ifcheck    argument(s)     meaning

-----------------------------------------------------------------------------

rand       num             Is random percentage less than or equal to num

mobhere    vnum            Is a NPC with this vnum in the room

mobhere    name            Is a NPC with this name in the room

objhere    vnum            Is an object with this vnum in the room

objhere    name            Is an object with this name in the room

mobexists  name            Does NPC 'name' exist somewhere in the world

objexists  name            Does object 'name' exist somewhere in the world

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

people     ==   integer    Is the number of people in room equal to integer

players    ==   integer    Is the number of PCs in room equal to integer

mobs       ==   integer    Is the number of NPCs in room equal to integer

clones     ==   integer    Is the number of NPCs in room with the same vnum

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

isnpc      $*              Is $* an NPC

ispc       $*              Is $* a PC

isgood     $*              Does $* have a good alignment

isneutral  $*              Does $* have a neutral alignment

isevil     $*              Does $* have an evil alignment

isimmort   $*              Is $* an immortal (level of $* > LEVEL_HERO)

ischarm    $*              Is $* affected by charm

isfollow   $*              Is $* a follower with their master in the room

isactive   $*              Is $*'s position > POS_SLEEPING

isdelay    $*              Does $* have a delayed MOBprogram pending

isvisible  $*              Is $* visible to NPC who activated the program

hastarget  $*              Does $* have a MOBprogram target in the room

istarget   $*              Is $* the target of NPC who activated the program

iskiller   $*              Does $* have a killer flag

isthief    $*              Does $* have a thief flag

istwit     $*              Does $* have a twit flag

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

affected   $*   'affect'   Is $* affected by 'affect'

affected2  $*   'affect2'  Is $* affected by 'affect2' (for affect2 bits)

act        $*   'act'      Is $*'s ACT bit 'act' set

off        $*   'off'      Is $*'s OFF bit 'off' set

imm        $*   'imm'      Is $*'s IMM bit 'imm' set

carries    $*   'name'     Is $* carrying object 'name'

wears      $*   'name'     Is $* wearing object 'name'

has        $*   'type'     Does $* have object of item_type 'type'

uses       $*   'type'     Is $* wearing object of item_type 'type'

name       $*   'name'     Is $*'s name 'name'

pos        $*   'position' Is $*'s position 'position' (sleeping etc.)

clan       $*   'name'     Does $* belong to clan 'name', "none" = not clanned

race       $*   'name'     Is $* of race 'name'

class      $*   'name'     Is $*'s class 'name'

objtype    $*   'type'     Is $*'s item_type 'type'

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

vnum       $*   == integer Is $*'s virtual number equal to integer

hpcnt      $*   == integer Is $*'s hitpoint percentage equal to integer

room       $*   == integer Is vnum of the room $* is in equal to integer

sex        $*   == integer Is $*'s sex equal to integer

truesex    $*   == integer Is $*'s true sex equal to integer

level      $*   == integer Is $*'s level equal to integer

align      $*   == integer Is $*'s alignment equal to integer

money      $*   == integer Does $* have money (in silver) equal to integer

objval#    $*   == integer Is $*->value[#] equal to integer (# from 0-4)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

objcount   vnum == integer Does obj vnum count (in the world) equal integer



-----------------------------------------------------------------------------

MOBcommand argument_list           MOBcommand argument_list

-----------------------------------------------------------------------------

ASOUND     [text_string]           ECHO       [text_string]

GECHO      [text_string]           ZECHO      [text_string]

ECHOAT     [victim] [text_string]  ECHOAROUND [victim] [text_string]

MLOAD      [vnum]                  OLOAD      [vnum] [level] {{max} num} {R|W}

KILL       [victim]                FLEE

REMOVE     [victim] [vnum]         MOB JUNK   [object]

PURGE      [argument]              AT         [dest] [command]

GOTO       [dest]                  TRANSFER   [victim] [dest]

GTRANSFER  [victim] [dest]         FTRANSFER  [victim] [dest]

OTRANSFER  [object] [dest]         GFORCE     [victim] [command]

FORCE      [victim] [command]      CAST       [spell] [victim]  nd]

VFORCE     [vnum]   [command]      DAMAGE     [victim] [min] [max] {lethal}

DELAY                              CANCEL

REMEMBER   [victim]                FORGET

CALL       [vnum] [victim] [target1] [target2]



======================END OF QUICK REFERENCE SHEET===========================



+++++++++++++++++++++++++++++++ EXAMPLES ++++++++++++++++++++++++++++++++++++



In #MOBILES:



M act 1000 pokes you in the ribs.~



In #MOBPROGS:



#1000

if isnpc $n

   chuckle

   poke $n

   break

else

   if level $n <= 5 or isgood $n tell $n I would rather you didn't poke me. else if level $n> 15

         scream

         say Ya know $n. I hate being poked!!!

         if mobhere guard

            mob force guard kill $n

         endif

         kill $n

         break

      endif

      slap $n

      shout MOMMY!!! $N is poking me.

   endif

endif

~



Ok.. time to translate.. the trigger will only happen when the mobile

gets the message "... pokes you in the ..." If the offender (recall

the $n and $N refer to the char who did the poking...) is an NPC, then

the mobile merely chuckles and pokes back. If the offender was a PC

then good and low level characters get a warning, high level chars

get attacked, and midlevel chars get slapped and whined at.

Also, when attacking, the mobile will check if there are guards in the

room (if mobhere guard) and if one is found, it will be forced to

attack the player, too (mob force guard mob kill $n). Notice the

use of a MOBcommand "mob force".



Note that two of these mobiles could easily get into an infinite poke

war which slows down (or frequently crashes) the mud just a bit :(

Be very careful about things like that if you can. (i.e don't respond

to a poke with a poke, and try not to let heavily programmed robot mobiles

wander around together. More on that is given above.)



Also, it is clear that the 'order' command could get confused with the 'or'

control flow. However, this is only the case when 'order' is abbreviated to

its two letter form, and placed immediately following an 'if' line. Thus,

if you want to be that malicious in trying to break the MOBprogram code,

no one is going to stand in your way (However, the result of this would be

a bug message and a bail out from the ifcheck so things don't really break)



Another example:



This program could be used on a temple guardian mobile, whose job is to

prevent evil characters from entering the sanctuary. Let's assume

the exit to the temple is north (exit 0) and the temple antechamber is

room 2301



In #MOBILES



M exit 1001 0



In #MOBPROGS



#1001

if isgood $n

   say Hail!

   emote salutes $n.

   if carries $n holy

      mob transfer $n 2301

   else

      say If you wish to enter the temple, get a holy symbol.

   endif

else

   curse $n

   say Get lost, you scum!

endif

~



How this works: The trigger is activated when the player tries to exit

north from the room. If the player is of good alignment, the guard will

greet the player. However, the guard will not let the player to the

temple unless he or she carries a holy symbol. If the player is neutral

or evil, the guard will curse and block the way.



Example of using DELAY and REMEMBER:



In #MOBILES



M greet 1002 100

M delay 1003 100



In #MOBPROGS



#1002

if isevil $n

   say You infidel! Go away or face the wrath of mighty Mota!

   mob remember $n

   mob delay 10

   break

endif

~

#1003

if hastarget $i

   growl

   mob echo $I screams and attacks $Q.

   mob kill $q

else

   mob forget

endif

~



How this works: When the player enters a room, the mobile checks if the

player is evil. If this is the case, the mobile makes the player the

target (mob remember) and sets up a delay of 10 * PULSE_MOBILE.

When the delay expires, program #1003 is activated. The mobile checks

if the target is still in the room (hastarget), and if the player hasn't

left, the mobile attacks ($q and $Q refer to the target). If the player

has left, the mobile will forget the player (mob forget).



Example of MOB CALL:



In #MOBILES:



M greet 1004 100



In #MOBPROGS:



#1004

if isgood $n

   mob call 1005 $n null null

else

   mob call 1006 $n null null

endif

~

#1005

mob echo Suddenly, a bright aura surrounds $I!

mob cast 'heal' $n

~

#1006

mob echoat $n $I points $l finger at you in fury!

mob echoaround $I points $l finger at $N in fury!

mob cast 'curse' $n

~