Caravel Games
All content on site copyright © 2024 Caravel Games, All Rights Reserved, unless otherwise indicated.

Scripting Reference Guide (By Andrew Schepler)

This document describes the effects of each DROD 2.0 character script command in as much detail as possible. Probably more detail than you need or want to know if you're just starting out. If you haven't done so yet, look at DROD's help page on character scripting (available in-game, or in the installation as Data/Help/1/script.html) to get started, and come back here if you ever need more details.

Each character's script is always considered to be at a certain command within the script. The script runs once before the player's first turn starting from the first command, and once on each turn after that starting from the command where it left off. When the script runs, several commands may take effect, going down the list in order, except when a "Go to" or "If ... go to" command changes which command will execute next. Many commands pause the script until the next turn or longer, and a few stop the script entirely. If any script runs through more commands during the same turn than there are in the script because it has returned to a previous command, the script is terminated and the infinite script loop is noted in the drod.err log.

Script processing other than the run before the first turn occurs after the player and all non-character monsters have moved, before tar/mud is cut or grows, before fuses advance or ignite bombs, and before a new mimic or decoy is placed. The order in which multiple characters' scripts are run depends on the order in which the characters were placed in the room by the architect.

The behavior of many commands depends on whether they are considered conditions or instructions. I will use the term "condition" to describe any command immediately after a "If ... go to" in the script, and the term "instruction" to describe any other command.

In the next section, each command is listed in the order they appear in the script editor's command list. Next to the name of the command is information about the command's type, which indicates how it interacts with other commands and whether it uses up the character's turn. Most have a type that is one of the following:

Free: A command of this type takes effect and then the script continues to the next command during the same turn.

Action: When a command of this type is performed, the character's turn ends immediately after the action. The script resumes on the next turn. Action commands will not execute before the first turn, nor during the same turn as a successful "Appear", "Appear at", "Disappear", or "End on room exit". In those situations, the character will wait for the next turn and then perform the Action command.

Restrict: After a command of this type has taken effect, the script will continue during the same turn. However, if the script comes to a command of the Action type during the same turn, the character will wait for the next turn before performing the Action command.

Test: Most of these commands, which test something else in the room, begin with the word "Wait". The test can result in either true or false. When the Test command is a condition, the script will jump to the label specified by the previous "If ... go to" command if the result is true, or continue to the next command if the result is false. Unless otherwise noted, a Test command as a condition does not use up any turns and the script continues immediately. When the Test command is an instruction, the script will continue to the next line on the first turn for which the test is true. If the test is true when the script first comes to the command, it may take no turns and continue immediately, or the command may pause the script for many turns.

Final: Commands of this type always stop execution of the script immediately, and no further commands take effect while the swordsman remains in the room.

Following the command's name and type is a description of what arguments the command takes, and then the command's behavior.

Commands

Appear [Restrict, unless the character does not appear]
Behavior is the same as "Appear at" in the next entry, except that instead of a specified square, "Appear" uses the square where the character was placed or most recently disappeared.

Appear at [Restrict, unless the character does not appear]
Argument: A square in the room.

If the character is already visible or has no appearance type, the command has no effect and counts as a Free command.

As an instruction: Waits if necessary and as long as necessary until the specified square is not occupied by the player, Halph, a Slayer, a doppleganger, a weapon, a monster, or another character. When the square is clear, the character becomes visible on that square. On that turn (though this command may have taken one or more turns to complete), the script continues as though after a Restrict command.

As a condition: True if the square is clear as described above. If it is, the character appears there, and the script jumps to the appropriate label, then continues as though after a Restrict command. If the square is not clear, this command counts as a Free command.

Move to [unique type]
Arguments: A square in the room, a flag for whether turning is forbidden.

Like an Action command, will not execute before the first turn or in the same turn as a Restrict command (even if the character is invisible or already at the specified square).

As an instruction: If the character is not visible, acts as an Action command with no effect (like Wait 1). If the character is already on the specified square, acts as a Free command with no effect. Otherwise, attempts every turn to move one square toward the specified location until reaching it. The character has the same movement restrictions as ordinary ground monsters like roaches (no moving through walls, against force arrows, etc.), except that a character in the form of a wraithwing may also move over pits, and a character in the form of a seep may move both over ground and through walls. The character can move around some obstacles similarly to an unbrained goblin but does not calculate winding paths, regardless of its appearance type. If the character has a weapon and turning is not forbidden, then it will never take a step until it is facing the direction it wants to go; it will rotate 45 degrees per turn (preferring clockwise when making an about face) instead of moving until facing toward its next step. The script continues on the next line on the turn after the character reaches the goal square, if ever.

As a condition: If the character is not visible, the command tests true but ends the character's turn. If the character is already on the specified square, the command tests true and the script continues. Otherwise, the character spends one turn as above attempting to move toward the specified square or turning its weapon if turning is not forbidden. The command tests as true if the character steps onto the specified square in that one turn. Whether it does reach the square or not, the turn ends.

Face direction [Action]
Argument: Direction (of the eight possible, plus clockwise or counter-clockwise).

If the character is invisible or already facing the specified direction, has no effect and continues as a Free command.

The character faces or rotates in the specified direction. Unlike other Action commands, "Face direction" can take effect before the first turn or on the same turn as a previous Restrict command. It will still end the turn. The command might rotate a character with weapon more than 45 degrees in a single move. If the character is invisible, the command will still influence its orientation when it does appear.

Strike orb at [Action]
Argument: Location of orb.

Activates the orb (if any) at the specified location. If no orb is at that square, a sound effect will still be played, and characters may react to the orb event. If any character, Halph, or the Neather is standing adjacent to the orb, or if a weapon is touching the orb, it will activate as normal. Otherwise, it will appear the swordsman is using a portable orb.

Turn into monster [Final]
Replaces the character with the ordinary creature of its appearance type. If the character is not visible, the script stops, but nothing new appears. If the character's appearance cannot be anything other than a character (i.e. it is Citizen 1 or 2, Goblin King, Instructor, Mud coordinator, Negotiator, or
Tar technician), then the script stops, and the character remains where it is and still counts as an NPC to other scripts and retains its invincibility if set. If the appearance is a mimic, Slayer, or guard, then the new creature appears in the monster move order after any existing creatures of the same type. If the character turns into a mimic, and a mimic from a potion is also placed this turn, then the potion mimic comes after the formerly scripted mimic in monster order. For all other appearance types, the monster replacing this character comes after all existing monsters, after any roaches hatched this turn, and before any tar babies or mud babies created this turn, except any tar babies or mud babies created when something struck a bomb with a weapon. The monster does not move during the turn in which this command takes effect. In all cases, the script will start again if the swordsman reenters the room, unless "End on room exit" has previously taken effect.

Disappear [Restrict]
If the character is not currently visible, counts as a Free command with no effect instead of Restrict. Otherwise, removes the character from the room.

Speech [Free]
Arguments: Text, optional sound file, Speaker, Mood, duration in milliseconds. In the case of "Custom" speaker, a location.

Speech never has an effect on the gameplay, including the script which triggered it. If previous speech is still being shown/played, another speech command will simply add to a queue, so that the timing of gameplay can run mostly independently of speech timing. The speech duration may be given to the command or left as zero, in which case it will be determined from the sound file, or estimated as one second plus 50 milliseconds per character in the text. If the user's settings has "Show subtitles when voices play" unchecked, then subtitles are not shown for a Speech command with a sound file. Subtitles are still shown for any Speech command without sound file, except when the duration is specified as 1 millisecond. When it is convenient to use one sound file and two caption lines, setting the second Speech command to 1 ms with no sound file will be useful. Any captions displayed stay on the screen for at least two seconds, even if other speech begins sooner.

The speaker and mood determine the face shown at the upper left for the duration of the speech and the position and color of the caption. Except for cases when the "Custom" speaker indicates no monster, the captions will always be associated with a specific character or monster and will move if the character or monster moves before or during the time the caption is displayed. If the associated character or monster dies before the speech is complete, the speech is cut off or not played or shown at all. If the speaker is anything other than "Custom" or "None", a face for that speaker will be shown, and the caption will be in an appropriate color. When the speaker is Beethro, Halph, Slayer, or Negotiator, the command's mood also determines the picture shown. If the character is visible and the speaker type matches its appearance, then the caption appears next to it. Otherwise, it is displayed next to the monster or character with matching appearance which comes first in the monster move order. If no monster or character matches the speaker, then the caption is next to the character (visible or not) whose script contains this command.

For speaker "None", Beethro's face shows (as the default), and the caption is in gray next to the script's character, visible or not.

When using speaker "Custom", a target square in the room must also be specified. If any creature other than the swordsman is on this square when the Speech command takes effect, that creature does the speaking. The caption will appear next to the monster in an appropriate color. When the creature is any human, a goblin (including the Goblin King), or a rock golem, the appropriate face will be shown, and in the case of Halph, a Slayer, or a Negotiator, the command's mood also applies. Other monsters do not have face graphics, so the view will default to Beethro in "Normal" mood. If the target square is unoccupied (or if the swordsman is there), then the face defaults to Beethro Normal, and the caption displays by the target square in gray.

Flush Speech [Free]
Argument: Flag indicating whether to display captions.

Stops any speech sound file currently playing and cancels all Speech commands that have been queued but have not yet been played or displayed. If the flag is "On", then captions are displayed immediately for all cancelled speeches, even if the user has selected not to see captions when sound is available.

Question [Action/Test]
Argument: Question text.

The character's turn ends immediately. At the end of this turn, a yes/no dialog pops up with the specified text, even if the character dies during the same turn. The command tests as true if the player selects "Yes". If the command is used as an instruction, the dialog comes up at the end of the turn, but it doesn't matter what answer is given.

Set Music [Free]
Argument: Music category.

Selects the style of music to be played starting now, until another "Set Music" command or until the player leaves the room. Some styles usually have more than one song, which are chosen randomly. If this command takes effect before the first turn in a room and the new music style matches what was already playing, the current song will continue uninterrupted. See the drod.ini file for details on songs in each style.

Invincibility [Free]
Argument: On/Off flag.

Sets whether the character is immune to death by weapons and bombs. The new setting applies to any potentially deadly circumstances that occur later in the same turn. Invincibility is not enabled when the script starts up, unless the character is in the form of a wubba.

If a weapon is already puncturing the character when invinciblity is turned off, it does not die until the next turn of the weapon's owner. The character will die if the weapon's owner does not remove the weapon as its next action. Since the player acts first in every turn and other non-characters with weapons move next, this usually means the character survives until the next turn, but another character with a weapon may come later in the monster order and kill the newly vulnerable character through action or inaction during the same turn.

Wait [unique type]
Argument: Number of turns (N).

If N is zero, this is always a Free command with no effect.

As an instruction: Causes the character to take no Actions for N turns. If the first turn has not yet begun or a Restrict command has taken effect during this turn, then this turn does not count as one of the N turns, since no Action could have taken place yet anyway. The script resumes on the (N+1)st turn.

As a condition (not recommended): If the first turn has not yet begun or a Restrict command has taken effect during this turn, then the test result is false, and the script continues immediately. Otherwise, the test result is true and the character does nothing for N turns including this one.

Wait for event [Test]
Argument: Event to check.

As an instruction: If the specified event has already occured during this turn, the script continues as for a Free command. If not, the script will resume the first time after the event does happen when it is this character's turn in the normal monster order. In most cases when the player is a direct cause of the event, the script will continue during the same turn.

As a condition: Tests true if the specified event has already occured during this turn. Whether it has or not, the script continues immediately.

The list below explains when each event occurs. Note that many correspond to a sound effect, which may help remember on which turns they do and do not occur. They are classified according to the phase or phases of the turn during which they might occur: Events in the Early phase occur as an immediate result of the player's action or on the turn of a non-character monster or other creature, who always act before characters. Events in the Char phase occur as an immediate result of a character's action. Events in the Late phase occur after all character scripts have run. Some events can also occur before the first turn begins, in which case they fall either in the Init phase if they occur before character scripts are first run, or in the InitLate phase if they occur after character scripts run and before the player's first move. The Double phase is used for convenience to describe events that can be a direct result of placing a mimic or decoy, but it can be considered part of the Late phase, or sometimes InitLate. "Wait for event" as a condition will always catch Init and Early events and never catch Late or InitLate (or Double) events. The behavior when a Char phase event comes up may depend on the relative monster order of the characters. However, if some of the causes of an event are not possible in a given room, certain phases can often be eliminated as possibilities (e.g. nothing happens in Double phase if there are no decoy or mimic potions; and if there are no fuses, bombs never explode Late). To sum up the phase descriptions:

  "Turn 0"
    Init
    [Character scripts run here, but cannot cause any events yet.]
    InitLate
    Double
    [Instruction-type "Wait for event" commands get another chance to detect
      events.

  Ordinary Turn
    Early (in this order: player, mimics, Slayer, guards, Neather, other
      monsters and Halph)
    Char [Character scripts run and can both cause and detect events.]
    Late
    Double
    [Instruction-type "Wait for event" commands get another chance to detect
      events.]


All monsters killed [Late/Double]
There was at least one monster in the room at the start of a turn, not counting Halph, Slayers, decoys, mimics, wubbas, or characters, and no such monsters at the end of the same turn. This event does not occur if the only monster or two are destroyed on room entry.

All tarstuff removed [Bomb struck with weapon: Early/Char/Double;
Bomb lit from fuse: Late; tar/mud cut with weapon: InitLate/Late/Double]

Something destroyed some tar or mud, and now no tar or mud is in the room, not counting freed tar babies or mud babies.

Bomb exploded [Struck by weapon: Early/Char/Double; Lit by fuse: Late]
A bomb was struck or ignited and exploded.

Broken wall destroyed [Init/Early/Char/Double]
A breakaway wall or secret wall was destroyed by the swordsman's body on room entry or by a weapon. The event does not occur for bombs that remove breakaway or secret walls.

Double placed [Double]
A decoy or mimic has been successfully placed.

Roach egg hatched [Early]
A roach egg hatched into a live roach.

Evil eye woke [Early]
An evil eye that had been sleeping saw the swordsman or a decoy and activated.

Fuse burning [Bomb struck with weapon: Early/Char/Double; Spark lit adjacent fuse(s) or detonated bomb which lit fuse(s): Late; Stepped on loose end: Init/Early/Char/Double]
A piece of fuse caught on fire, or a bomb was lit from a fuse (in which case the bomb will explode next turn).

Halph entered room [Early]
Halph appeared at the edge of the room.

Player bumps obstacle [Early]
The swordsman attempted an illegal move, bumping into a wall, object, monster, or any square where he cannot step, or resisting a force arrow or orthogonal square. Tapping Halph on the shoulder and bumping into a closed yellow door while Halph is in the room do not cause this event. This event does not occur on the same turn as "Player teeters on pit edge".

Monster stabbed [Init/Early/Char/Double; Neather: Late]
A creature died from a weapon strike, or a seep died from an opening door. Stabbing serpents (even when it kills a rattlesnake), rock golems, wubbas, and currently invincible characters does not cause this event. Stabbing the Neather only causes this event in the Neather's final room when the player refuses to spare him.

Rattlesnake tail stabbed [Init/Early/Char/Double]
A weapon struck a rattlesnake's tail.

Mud baby formed [Bomb struck with weapon: Early/Char/Double; Bomb lit from fuse, or mud growth: Late; Mud cut with weapon: InitLate/Late]
A mud baby broke free of a mud blob when the blob was damaged or grew.

Mud growth [Early]
A mud mother caused the mud in the room to (attempt to) grow. This event may be detected when the mud does not in fact grow, if a mud mother dies during the Char phase.

Player activates orb [Init/Early]
The player's sword activated an orb.

Object activates orb [Bomb struck with weapon: Early/Char/Double; Bomb lit from fuse: Late]
A bomb explosion activated an orb.

Monster activates orb: [Early/Char/Double]
A weapon other than the player's sword activated an orb, or Halph or the Neather struck an orb, or a "Strike orb at" script command took effect. The "Strike orb at" command causes this event even if no orb is at its location.

All trapdoors removed [Early/Char]
The swordsman, a mimic, or a character in the form of a mimic stepped off the last trapdoor in the room.

Player teeters on pit edge [Early]
The player attempted to move into a pit, and nothing saved the swordsman but his balance and reflexes. This event does not occur if a force arrow under the swordsman or orthogonal movement marker on either square prevents the movement, but it can even if an opposing force arrow is over the pit.

Slayer entered room [Early]
The Slayer appeared at the edge of the room.

Serpent smashed [Red serpent: Early; Rattlesnake: Init/Early/Char/Double]
A serpent died from shrinking to length one.

Tar baby formed [Bomb struck with weapon: Early/Char/Double; Bomb lit from fuse, or tar growth: Late; Tar cut with weapon: InitLate/Late]
A tar baby broke free of a tar blob when the blob was damaged or grew.

Tar destroyed [Bomb struck with weapon: Early/Char/Double; Bomb lit from fuse: Late; Tar/mud cut with weapon: InitLate/Late]
Some tar or mud was removed, by bomb or by weapon.

Tar growth [Early]
A tar mother caused the tar in the room to (attempt to) grow. This event may be detected when the tar does not in fact grow, if a tar mother dies during the Char phase.

Trap door removed [Early/Char]
The swordsman, a mimic, or a character in the form of a mimic stepped off a trapdoor, which fell into the pit.

Tunnel [Early]
The player went through a tunnel.

Slayer wisp found player [Early]
At some point during the Slayer's turn, the wisps made a chain from the Slayer to the swordsman. This event occurs on every turn for which it is true, not just when the wisps first touch the swordsman.

Wubba stabbed [Init/Early/Char/Double]
A wubba that was not stabbed during the previous turn was stabbed with a weapon this turn. Characters in the form of wubbas do not cause this event. It does not matter if a different weapon stabs a wubba; once a wubba has gotten used to being tickled, it does not cause the event again until it has been left alone for an entire turn.

Wait for player [Test]
Argument: Rectangle within the room.

True if the player (body, not sword) is within the specified rectangle.

Wait while player is [Test]
Argument: Rectangle within the room.

True if the player (body, not sword) is not within the specified rectangle.

Wait for Halph [Test]
Argument: Rectangle within the room.

True if at least one Halph is within the specified rectangle.

Wait while Halph is [Test]
Argument: Rectangle within the room.

True if no Halph is within the specified rectangle.

Wait for monster [Test]
Argument: Rectangle within the room.

True if at least one monster is within the specified rectangle. For purposes of this command, Slayers and guards count as monsters, but mimics, decoys, Halph, and characters do not.

Wait while monster is [Test]
Argument: Rectangle within the room.

True if no monsters are within the specified rectangle. For purposes of this command, Slayers and guards count as monsters, but mimics, decoys, Halph, and characters do not.

Wait for NPC [Test]

Argument: Rectangle within the room.

True if at least one character (including this one) is within the specified rectangle.

Wait while NPC is [Test]
Argument: Rectangle within the room.

True if no character (including this one) is within the specified rectangle.

Wait for door to [Test]

Arguments: A square within the room, and a flag set to "Open" or "Closed".

True if the current state of the square matches the flag's setting. In addition to testing yellow doors, blue, green, red, and black doors will be considered closed until they drop and open afterward. Squares without doors are considered Open. Master walls are not considered doors and will always test as Open.

Wait for turn [Test]

Arguments: A turn number (N).

True if the turn counter is equal to or greater than N. The turn counter is always equal to the number of times the player has moved, rotated, or rested since entering the room.

Wait for clean room [Test]

True if there were no monsters in the room originally, or the player has reentered this room after previously conquering it, or if at the end of any turn prior to this there were no monsters left alive. For the purposes of this command, mimics, decoys, Halph, Slayers, and characters do not count as monsters; guards do. This command is equivalent to testing for a green door to open (except that it will work just as well if there are no green doors in the room).

Wait for player to face [Test]

Argument: A compass direction.

True if the swordsman is facing in the specified direction.

Label [Free]

Argument: A string identifier.

No effect. "Go to" commands and "If ... go to" commands may specify this command as a jump point. The identifiers of different labels do not need to be distinct for the script to work, but using distinct strings makes things easier on the programmer.

Go to [Free]

Argument: A Label command in the same script.

Instead of continuing to the next command, the indicated Label command will be the next one executed.

If ... go to [Free]

Argument: A Label command in the same script.

Makes the next command a condition. If the following command has a true result, then the script jumps to the indicated Label command after the condition. Unless otherwise noted, Free commands and Action commands have true results. Final commands do not have results.

If no command follows this one, the script ends as usual on completing the final command. When multiple "If ... go to" commands appear consecutively, all except the last are ignored. When an "If ... go to" command is followed by a "Go to" command, the "If ... go to" is ignored and the script jumps to the label of the "Go to" command.

End on room exit [Restrict]

After this command has taken effect at least once, the character will not appear in the room and its script will not execute any time the player reenters the room.

End [Final]

After this command has taken effect, the character will not appear in the room and its script will not execute any time the player reenters the room.

Ending and restarting scripts

By default, a character will be present and its script will start from the beginning when the player enters the room a second time, regardless of whether the room has been conquered. The "End" and "End on room exit" commands set the character that it will not be present the next time the player enters, but nothing else does. Reaching the end of the script, the "Turn into monster" command, dying, and the undesirable infinite loop condition stop the cript, but do not affect what happens on the next visit to the room.

An alternative to marking a character not to be present in the future is testing at the beginning of the script whether it should appear or disappear. For example, if I want a character that should be in the room until it is conquered, then never again, I might set it visible by default and start its script with:
  If ... go to "Vanish"
  Wait for clean room
  Goto "Start"
Label "Vanish"
  Disappear
  End
Label "Start"


Back-compatibility

Various bugs and changes to the game's behavior mean that some scripts will behave in an unintended way on older versions of the game, though most character- and event-related bugs seem to have been sorted out by 2.0.8 (at about the time the first draft of this document was prepared). The above sections present the way things currently work. For the sake of completeness, in this section are listed all known past bugfixes and changes which affect the above information, in reverse chronological order. This list may be useful in case of an unusual bug report from a playtester who has an older DROD version.

In all versions through 2.0.7:
* When "Move to" is encountered as a condition on the same turn as a Restrict command, it fails to behave as a condition when executed on the next turn.
* Characters might not detect InitLate phase events, especially at a level entrance or restore to room start.
* The "Face direction" command always takes one turn, even if the character is invisible, or already facing the specified direction.
* The "Appear" and "Appear at" commands end the character's turn if the character is already visible or has no appearance type. The "Disappear" command ends the character's turn if it is already invisible.
* The "Serpent smashed" event never occurs during the Char phase, since a bug fails to kill rattlesnakes when struck with a character's weapon.
* Mud and/or tar might grow on the turn a mother is killed by a character's action, but the "Tar growth" / "Mud growth" events will correctly reflect whether it does.
* Characters in the form of wubbas are vulnerable by default.
* If two "Wait for event" commands appear consecutively, the second may be skipped too soon, if the first is a conditional which tests false, or if the first is satisified in the Late phase and the second in the Double phase.
* Characters in the form of mimics do not light fuses or drop trapdoors (and therefore the events "Fuse burning", "Trap door removed", and "All trapdoors removed" would not occur).
* The "Wubba stabbed" event never occurs during turn number 1.

In all versions through 2.0.6:
* "Wait for clean room" command is equivalent to "Wait while monster is" with a rectangle covering the entire room. This might test true before the green door drops if Late events like cutting tar/mud or some bomb explosions create more monsters.
* Using "Move to" as a condition does not end the character's turn.
* The "Wait" command resumes the script after N-1 turns if N>=2, but does not allow Action commands on the Nth turn. In the old behavior, Wait may be thought of as N-1 Action commands and one Restrict; it is now simply N Action commands.