MadROM Mud Script Authoring Guide

This guide documents the current MadROM .ms Mud Script language implemented in src/mudscript.c. It is not a legacy MobProg manual. Old MobProg notes are useful only when migrating old behavior; new scripted content should use the Mud Script rules below.

Source Of Truth

What Mud Script Is

A Mud Script file is a behavior file for one NPC prototype. The area file maps a mobile vnum to a .ms file in a #MUDSCRIPTS section. The engine loads trigger blocks from that file and runs those blocks when the matching game event happens.

Each mobile prototype gets one Mud Script file. If an area tries to assign more than one, the later file is ignored and a bug is logged. Keep one coherent script file per mobile.

Area Mapping

Put mudscript mappings in the area file's #MUDSCRIPTS section. Files live under area/MOBProgs/.

#MUDSCRIPTS
M 3011 mid_hassan.ms
M 30600 chess_white.ms
S

This is the modern path. Do not add new live dependencies on legacy .prg loaders or old #MOBPROGS semantics unless the task is specifically compatibility work.

File Format

A .ms file contains one or more trigger blocks and normally ends with |.

>trigger_type arglist~
commands...
~
>trigger_type arglist~
commands...
~
|

Supported Triggers

TriggerArglistWhen It Runs
speech_progword/phrase matchWhen a player or NPC speaks in the room.
act_progword/phrase matchWhen the mob receives an act() message with an actor.
entry_progpercent chanceWhen the scripted mob enters a room.
greet_progpercent chanceWhen a player or NPC enters/is checked in the room, the mob is awake, not fighting, and can see the actor.
all_greet_progpercent chanceLike greet_prog, but without the visibility check.
fight_progpercent chanceDuring combat trigger checks.
hitprcnt_progpercent chanceDuring hit-percent combat trigger checks.
death_progpercent chanceWhen the scripted mob dies.
rand_progpercent chanceOn the normal random trigger tick.
give_progobject keyword/nameWhen a player gives the mob an object.
bribe_progminimum gold amountWhen a player bribes the mob.
time_proghour 0-23Once each game hour when the current hour exactly matches.
function_progfunction nameReusable block called with callfunc name; it does not fire by itself.

Actor Filters

Speech, act, and percent triggers can gate on actor type with p or n.

>speech_prog p hello~
say Hello, %player%.
~
>speech_prog n~
say I heard another mobile.
~
>greet_prog p 50~
say Welcome, $n.
~

Word And Phrase Matching

speech_prog and act_prog support two matching styles.

>speech_prog hammerbarn sting nits~
say That was one of the words I was waiting for.
~
>speech_prog p nice parking rita~
say Thanks for playing along.
~

Percent Triggers

Percent triggers clamp chance to 1..100 and run at most one matching block per trigger event. The engine walks the script blocks in file order and stops after the first block that passes its roll.

>rand_prog 15~
say The room feels a little less quiet.
~
>fight_prog 25~
say You picked the wrong fight.
~
>fight_prog n 40~
say Another NPC dragged me into this.
~

Command Execution

Ordinary command lines are expanded, then run as the scripted mobile through the normal command interpreter. That means most existing mobile commands work as long as the mob could legally issue them.

Built-In Mudscript Commands

CommandUse
setvar name valueSet a run-scoped string variable.
unsetvar name / clearvar nameRemove a run-scoped variable.
setmem key valueStore numeric player memory for this mob vnum and key.
addmem key amountAdd to numeric player memory.
unsetmem key / clearmem keyRemove numeric player memory.
callfunc nameRun a function_prog name block from the same script file.
mudlog messageWrite a server log line prefixed with the mob vnum.
response N% { ... }Roll once, then choose one response option or one grouped response outcome.

Variable Expansion

Variables expand before commands run.

TokenMeaning
$iFirst keyword of the scripted mob.
$IShort description of the scripted mob, falling back to name.
$nFirst keyword/name of the actor; player names are capitalized.
$NVisible actor name/short description, or someone if hidden.
$oFirst keyword of the current object in give/bribe/object context.
$OShort description of the current object, falling back to object name.
$e, $m, $sActor pronouns: he/she/they, him/her/them, his/her/their. Hidden actors become generic.
$j, $k, $lScripted mob pronouns.
$$Literal dollar sign.
%name%Run-scoped variable.
%player% / %player_name%Actor's first name/keyword.
%mem:key%Persistent numeric player memory for this mob and key.

Unknown $ codes are preserved literally for forward compatibility.

Control Flow

Mudscript supports line-based conditionals and switches.

if ispc($n)
  say You are a player.
elseif isnpc($n)
  say You are another mobile.
else
  say I do not know what you are.
endif
switch %mood%
case happy
  say Good day.
case angry
  say Not now.
default
  say Hmm.
endswitch

If-Check Operators

Conditions use function-style checks. Boolean checks can be negated with leading !.

if !isfemale($n)
  say You are not female.
endif

String comparisons support the same operators as the engine helper: equality, inequality, and substring-style matching where supported by mudscript_seval(). Numeric comparisons support ==, !=, <, <=, >, and >=.

Character Checks

CheckMeaning
ispc($x)Target is a player.
isnpc($x)Target is an NPC.
isimmort($x)Target is an immortal player.
isgood($x)Target is good aligned.
isevil($x)Target is evil aligned.
isneutral($x)Target is neutral aligned.
ismale($x), isfemale($x), issexless($x)Target sex checks.
sex($x) == NNumeric sex check for compatibility; prefer the named checks above.
isfighting($x)Target has a fighting pointer.
ischarmed($x)Target has charm affect.
isfollowing($x)Target has a master in the same room.
isleader($x)Target has no master.
ispet($x)Target is an NPC with ACT_PET.
isnotpet($x) / isntpet($x)Target is not an NPC pet.
isactive($x) / isawake($x)Target position is above sleeping.
issleeping($x)Target position is sleeping.
isvisible($x)The scripted mob can see the target.
istarget($x)The scripted mob is fighting the target.
level($x) >= NTarget trust level comparison.
hitprcnt($x) <= NTarget hit ratio comparison as currently implemented by the engine.
inroom($x) == VNUMTarget room vnum comparison.
align($x) < NTarget alignment comparison.
position($x) == NTarget position number comparison.
goldamt($x) >= NGold carried by $i or $n.
tribe($x) == abbrevTribe abbreviation for $i or $n.

Object And Room Checks

CheckMeaning
number($i) == NFor $i, compares the mob's gold value as currently implemented.
number($n) == VNUMFor NPC actors, compares actor mobile vnum.
number($o) == VNUMCompares current object vnum.
name($i) == wordString compare against mob keywords.
name($n) == wordString compare against actor keywords/name.
name($o) == wordString compare against object keywords.
objtype($o) == NCurrent object type number.
objval3($o) == NCurrent object's value slot 3.
mobhere(VNUM) > 0Counts matching mobs in the current room.
mobhere(VNUM) > ROOMVNUMWith a comparison value present, the engine checks the selected room. This is low-level; test with MUDSIM before relying on it.

Affect Checks

hasaffect($x, flag) and isaffected($x, flag) look up named flags in affect_flags and affect2_flags.

if hasaffect($n, sanctuary)
  say Sanctuary will not save you forever.
endif

Convenience aliases exist for common flags: isblind($x), isinvisible($x) / isinvis($x), issanctuary($x) / issanct($x), and isflying($x).

Variables And Functions

Run-scoped variables reset at the start of each trigger run. Functions share the caller's run-scoped variables and actor/object context.

>function_prog greet_player~
say Hello, %player%.
~
>greet_prog p 100~
setvar mood friendly
if var(mood) == friendly
  callfunc greet_player
endif
~
|

Function recursion is capped at 16 calls to prevent runaway loops.

Persistent Player Memory

Mob memory is stored on the player file by mob vnum and key. It only works when the current actor is a player. For NPC actors or missing actors, memory commands safely do nothing.

>speech_prog p remember me~
addmem remembered 1
if mem(remembered) >= 3
  say I know you, %player%.
else
  say I will remember that.
endif
~

Response Blocks

response rolls once. If the roll passes, it picks one option. Plain options run one selected command. Grouped options run every command in the selected group.

response 50% {
  say One possible line.
  say Another possible line.
}
response 100% {
  {
    say First grouped outcome.
    smile
  }
  {
    say Second grouped outcome.
    nod
  }
}

Give And Bribe Context

give_prog and bribe_prog carry object/money context into mudscript.

>give_prog hammer~
if objtype($o) == 5
  say That is the kind of thing I needed.
else
  say This is not useful.
endif
~
>bribe_prog 1000~
say Fine. You have my attention, $n.
~

Use $o, $O, number($o), name($o), objtype($o), and objval3($o) only when an object context exists.

Testing With MUDSIM

MUDSIM is the staff safety tool for mudscript. It runs the trigger logic and prints what would happen without executing commands.

mudsim 3011 speech pc hello
mudsim 3011 speech npc hello
mudsim 3011 greet pc
mudsim 3011 bribe pc 1000
mudsim 3011 time none 19

Debugging Live Behavior

Migration Notes From Legacy Mobprog

This section is only for conversion work. It is not the preferred way to write new scripts.

Complete Example

>function_prog warm_greeting~
response 100% {
  say Good to see you, %player%.
  say Welcome back, %player%.
}
~
>greet_prog p 100~
if isimmort($n)
  say Staff always makes me nervous.
  return
endif
addmem visits 1
if mem(visits) >= 3
  callfunc warm_greeting
else
  say Hello, $n.
endif
~
>speech_prog p hammerbarn~
if tribe($n) == vamps
  say I was not expecting a vampire shopping trip.
else
  say Hammerbarn has everything.
endif
~
>rand_prog n 20~
say The mobiles are talking again.
~
|

Authoring Rules