=== MOBprograms
MOBprograms are a way to make your mobiles more interesting. This
basic version has enough to get things going, and should be quite readable and
understandable and more to the point, extendable. The remainder of this
document describes MOBprograms and gives a couple trivial examples.
For information on how to install the MOBprograms into a Merc 2.0 beta
coding platform consult INSTALL.
Table of Contents:
The Basic Idea
MOBprogram Syntax
Associating MOBprograms With A Mobile
MOBprogram Files
Trigger Types
Variables
Control Flow Syntax
Operators
If_Checks In Control Flow
MOBcommands Of Interest
Regarding CPU Slowdown
Miscellaneous Information
Credits
-----------------------------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 frenchs his secretary, etc. So a way to
give the mobiles a bit more spirit would be neat. Enter the MOBprograms.
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.
Since knowing the appropriate response for every mobile to every
possible trigger is not easy, this command list shouldnt 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.
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.
----------------------------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.
">" {trigger_type} " " {argument_list} "~" NL
{program_command_1} NL
{program_command_2} NL
{program_command_3} NL
. . .
{program_command_N} NL
"~" NL
-- Explainations
A TRIGGER_TYPE is one of the available triggers.
A PROGRAM_COMMAND can be any legal mud command, or a control flow command.
The ARGUMENT_LIST depends upon the trigger, but it is always parsed into the
system as a character string.
This is an example of ONE MOBProgram block for a mob.
-------------------Associating MOBprograms With A Mobile--------------------
There are two ways for the mud to associate the program with the
mobile. In either case, the result is a link list of mob_programs which are
attached to the mobile_prototype. This is done at boot time, and so only one
copy is kept, regardless of how many instances of the mobile are running
about. This also means that there is no dynamic way to edit or modify the
MOBprograms.
Back to ways to associate...
The first involves a simple in-file approach. In the mobile section
of your area files, at the end of the mobile's block (i.e. on the line
following the typical position/default position/sex line), append any number
of MOBprograms blocks (using the syntax above) followed by a line starting
with one '|' (pipe). Example provided: Example.are
The second method is to add a #MOBPROGS section to the area files.
Logically this section should follow the #MOBILE section since otherwise the
mobiles probably wont have space allocated for them. In the #MOBPROGS section,
list as many lines as you desire of:
"M" {Vnum} {MOBprogram_filename} NL
followed by a line starting with a 'S' (case insensitive)
--Explainations
The VNUM is whatever number mobile to which you are associating the MOBprogram.
The MOBPROGRAM_FILENAME is the name of the external file of MOBprograms.
It is not case INsensitive and may include directory heirarchies (foo/bar/xx)
NOTE: MERC 2.2 provides for a separate directory called MOBProgs. Any
directory heirarchies branch from the Merc2/area/MOBProgs directory.
----------------------------MOBprogram Files----------------------------------
Since it is often useful to have the same MOBprograms affecting several
different mobiles, referencing MOBprograms stored in an external file
is needed. As described above, if the second method is used, such a file
is already being referenced. Using the first method, in place of a true
MOBprogram block, one can place the dummy line in the #MOBILE section of the
*.are file in place of the MOBProgram block(s).
">" "in_file_prog" {MOBprogram_filename} "~" NL
Note there is no list of program_commands as well as no second tilde ~.
In a file, the syntax is exactly the same as it is for a in_file
approach:
A list of MOBprogram (NOT including any dummy in_file_prog
lines, sorry but recursion was outlawed for simplicity)
blocks followed by a line starting with one '|' (pipe).
Example provided: Beggar.prg
More than one mobile can use the same file and one mobile can call more
than one file. Files referenced using the dummy in_file_prog line are
placed in the MOBprogram list at the point where the dummy line exists.
Files referenced using the #MOBPROG section are added to the end of the
mobiles MOBprogram list. This is important because the only the first
successful MOBprogram of some trigger_types is checked. These are described
below.
-----------------------------Trigger Types----------------------------------
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:
Syntax: in_file_prog
The argument is a single word which is the location of the stored
file as referenced from the running directory (MOBProgs).
NOTE: Dummy trigger. Not valid in any file, only for use in loading files
from the first method described two sections above.
Syntax: act_prog [p]
The argument is a list of keywords separated by spaces. If the
first word is the character 'p' by itself then the rest of the word list is
considered to be a phrase. The trigger is activated whenver a keyword (or
the phrase) is contained in the act() message. Both the phrase and keywords
are case insensitive.
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 (and some things you wont as well) For example:
MOBprogram: >act_prog p pokes you in the ribs.~
This trigger will only be activated if a mobile receives a message
in which the above five words are found in the exact order and
spacing given. Note that the period is needed because the words
must be found on their own. This eliminates confusion when the
keyword is 'hi' and a message with the word 'this' is being checked.
Syntax: speech_prog [p]
The argument is the same as for an act_prog.
NOTE: This is only triggered when the keyword or 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 NPC's to stand and discuss the weather however.
Syntax: rand_prog
The argument is a number betweeen 1 and 100 inclusive.
NOTE: This trigger is checked at each PULSE_MOBILE and if the argument is
greater than a percentage roll the trigger is activated. 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.
Syntax: fight_prog
The argument is a percentage like in rand_prog.
NOTE: Useful for giving mobiles combat attitude. It is checked every
PULSE_VIOLENCE when the mobile is fighting. Can be used to cast
spells, 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.
Syntax: hitprcnt_prog
The argument is a percentage.
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 hitprcnt_progs should be listed in increasing
order of percent since a 40% will always be activated before a 20%
and, only the first successful hitprcnt trigger is performed.
Syntax: greet_prog
Again a percentage argument.
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.
Syntax: all_greet_prog
Again a percentage argument.
NOTE: Like greet_prog, but it can be triggered even if the mobile didnt
see the arrival (i.e. sneak, invis, etc). Most useful for faking
teleport rooms (if your mobiles can transfer) or for impassable
guardians.
**NOTE: neither greet_prog is activated if the mobile is fighting.**
Syntax: entry_prog
Again a percentage argument.
NOTE: The opposite of a greet_prog. Whenver 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.
Only the first successful one of these is done so the mobile doesnt
look stupid by repeating commands resulting from multiple MOBprograms.
Syntax: give_prog
The argument is either the complete name of an object, or the word
'all'. A complete name is like: "sword shiny magic" vs "sword". It
is whatever is on the line of the object section following the VNUM.
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 give_prog
at the end of the MOBprogram list is essentially a default response.
Syntax: bribe_prog
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.
If money is given to a mobile with this trigger type, instead of the
cash being added to mob->gold, the mobile is instead given a pile of
coins in the proper amount. In this way, the mobile can drop the coins
or refer to the object by "amount" (short description:"%d gold coins")
This surely has some drawbacks, but it lets the mobile do something
with the bribe (NOTE: dropping it and getting it turns it into cash)
This can be done sneakily if a NPC-only "at" command exists.
Syntax: death_prog
The argument is a percent once again.
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, or create some, or cast a spell
on the killer and the room, or even goto a new location 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.
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). Of course this assumes that some NPC
commands have been implemented.
Note that the first successful bribe_prog, give_prog, hitprcnt_prog,
death_prog, fight_prog, rand_prog and entry_prog is the only one which
is executed. All the successful greet(_all)_progs, speech_progs, and
act_progs will be done. This is the best arrangement we found for handling
situations where you imported several MOBprogram files for a mobile. If you
are going to write lots of little files and piece them together to create
the effect you want, it is advisible to not mix things together all that
much, otherwise you have to pay close attention to the order in which the
programs are added to the link list.
Also, no MOBprograms will be successful when the mobile is charmed
(since it has no self violition, it should act like it has none) to protect
mobiles which are given special powers from being implemented by a player.
One bug we had in early testing was a player who charmed a mobile and then
used its aggressive greet_prog to attack other players.
------------------------------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 the name of a random char in the room with the mobile (never == $i)
$R the short description, or name and title of the random char
$j he,she,it based on sex of $i.
$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 $r.
$k him,her,it based on sex of $i.
$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 $r.
$l his,hers,its based on sex of $i.
$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 $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
$a a,an based on first character of $o
$A a,an based on first character of $p
Also, in if_checks, the accepted variables are the basic ones
(i,n,t,r,o,p). If a variable is referenced that doesnt exist, then the value
is simply left blank. (i.e referring to $o when the trigger is: A kisses B)
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, espescially 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 arent forced to make all
those twiddles to use the MOBprograms.
---------------------------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.
"if" " " {if_check_1} "(" {argument} ")" [ {operator} {value} ] NL
[ "or" " " {if_check_2} "(" {argument} ")" [ {operator} {value} ] NL ]
. . .
[ "or" " " {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 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 line:
--Explainations
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.
The BREAK command bails out of the entire MOBprogram regardless of the
level if nesting.
If that looks confusing, skip to the end of the document and review the
Example. Hopefully that should clear things, otherwise you'll probably have
to give us a mail since examples are the best way we know to explain syntax.
--------------------------------Operators-----------------------------------
Most of the basic numeric operators are legal and perform the same
function as in C. The string operators are a bit more confusing. There are
negative versions of some of the operators. These are not strictly needed,
since the if/else construct of Control Flow commands can handle either case.
Numeric Operators: == != > < >= <= & | String Operators: == != / !/
For strings, == and != check for exact match between the two strings
and the other two, / and !/ check to see if the second string is contained in
the first one. This is so things like: if name($n) / guard will respond
true to "cityguard" "guard" "guardian" etc. Using == on a name implies
that you are matching the complete name "cityguard guard" or whatever.
The string operators are case SENSITIVE.
------------------------If_Checks In Control Flow---------------------------
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 or $r)
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. name($n)== orc large brown)
rand (num) Is random percentage less than or equal to num
isnpc ($*) Is $* an NPC
ispc ($*) Is $* a PC
isgood ($*) Does $* have a good alignment
isfight ($*) Is $* fighting
isimmort ($*) Is the level of $* greater than max_mortal
ischarmed ($*) Is $* affected by charm
isfollow ($*) Is $* a follower with their master in the room
isaffected($*) & integer Is ($*->affected_by & integer) true
(person only)
hitprcnt ($*) == percent Is the hit/max_hit of $* equal to percent
inroom ($*) == integer Is the room of $* equal to integer
(person only)
sex ($*) == integer Is the sex of $* equal to integer
position ($*) == integer Is the position of $* equal to integer
level ($*) == integer Is the level of $* equal to integer
class ($*) == integer Is the class of $* equal to integer
goldamt ($*) == integer Does $* have a gold total equal to integer
objtype ($*) == integer Is the type of $* equal to integer
(armor,boat,etc)
objval# ($*) == integer Is $*->value[#] equal to integer (# from 0-3)
number ($*) == integer Is the vnum of $* equal to integer
name ($*) == string Is the name of $* equal to string
------------------------MOBCommands Of Interest-----------------------------
These are fairly basic things, most of them are wiz commands which have
been changed to allow for mobiles to perform the commands. If you have the
problem of immortals abusing these powers on your mud either ditch the
immortals, or add a check in all of them to only let NPC's with null
descriptors do the commands. (However, you lose a little debugging help that
way). MERC 2.2 has provided a little security feature against this but
it is by no means comprehensive. Please check yourself if you are concerned.
Here are the basic MOBcommands that we found to be enticing:
Syntax: MPSTAT
Shows the MOBprograms which are set on the mob of the given name or
vnum and some basic stats for the mobile
Syntax: MPASOUND
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.
Syntax: MPJUNK Text file Source (historic): geocities.com/area51/cavern/6760/mudweiser
geocities.com/area51/cavern/6760geocities.com/area51/cavern
geocities.com/area51
(to report bad content: archivehelp @ gmail)
|
|
|
|
|