Chapter 8: Debugging

When a script does not behave as expected, you have two main tools: compile-time error messages and the live trace. This chapter shows how to use both.

Compile errors

When you save a script with @ in the editor, the script is compiled immediately. If there is a problem, you will see an error message with a line number:

Script compilation error: line 3: unknown command 'gret'

Common compile errors:

Error Meaning Fix
unknown command 'X' Typo in a command name Check spelling: greet vs gret
undefined variable '$X' Using a variable that was never declared Add a let, check spelling, or pass it as a parameter
expected block A construct like if or each needs { } Add braces around the body
duplicate name 'X' Two let or def with the same name in the same scope Rename one of them

The error tells you which line has the problem. Use &r in the editor to redisplay the script with line numbers, then &l N text to fix line N.

Turning on tracing

Tracing shows you every instruction the script executes, in real time. To enable it:

  1. Start editing the mob: olc medit <vnum>
  2. Turn on tracing: olc mtrace on
  3. Stay in the room with the mob and trigger the event.

For objects and rooms:

olc oedit <vnum>
olc otrace on

olc rtrace on       # traces the room you are currently in

Trace output appears in cyan to immortals in the same room as the script's owner. It looks like:

[Script Trace] --- after command [handler 1] ---
[Script Trace]     stack[0]:
[Script Trace]     PUSH_CONST      "help"
[Script Trace]     stack[1]: help
[Script Trace]     LOAD_LOCAL      $args (0,3)
[Script Trace]     stack[2]: help, <iterable>
[Script Trace]     CALL_ROUTINE    keyword (2 args)
[Script Trace]     stack[1]: help, true
[Script Trace]     REQUIRE
...

This shows:

Reading trace output

The trace shows a stack-based execution. Values are pushed onto the stack, operations consume them and push results. Key things to look for:

Turning off tracing

olc mtrace off
olc otrace off
olc rtrace off

Always turn tracing off when you are done — it generates a lot of output and can be distracting.

Common runtime errors

These appear in the trace output or as error messages:

Error Cause Fix
type error: expected bool, got int Passing an integer to if or require Use a comparison: [gt $n 0] not $n
type error: expected int Arithmetic on a non-integer Use [int $str] to convert a string
stale creature reference The creature was removed from the world The script silently stops; check with [exists $target] before use
too few arguments Calling a block with fewer args than it declares Check the block's <params>
execution limit exceeded Infinite loop or very expensive computation Simplify the logic; check loop bounds

Debugging strategies

1. Check whether the handler fires at all

Add a simple do "say" as the first line:

after command (say) {
  do "say DEBUG: handler fired"
  require [keyword $args quest]
  do "say Here is the quest info."
}

If you never see "DEBUG: handler fired", the filter is wrong or the event is not matching.

2. Check variable values

Interpolate variables into a do "say" to inspect them:

after command (say) {
  do "say DEBUG: arg='$arg'"
  let n [count $args]
  do "say DEBUG: word count=$n"
}

3. Check require conditions separately

If a require seems to fail unexpectedly, test the condition in isolation:

after command (say) {
  let result [keyword $args quest]
  do "say DEBUG: keyword result=$result"
  require $result
  do "say You asked about a quest!"
}

4. Check entity references

If a script stops silently mid-execution, a stale entity reference may be the cause. Use exists to guard:

if [exists $target] {
  do "say [name $target] is still here."
} else {
  do "say They left."
}

The offline debugger

For testing scripts without a running MUD, you can use the command-line script debugger:

./bin/circle --script-debug file.script sample_lib [command] [args...]

This compiles and runs a script file against the sample library data, optionally simulating a game command. It prints the full trace to stdout.

Key points

Back to index