Articles
AGI Error Code Tutorial v1.0
by
Nick Sonneveld
Last updated 9th March, 2002
Page: 1
2
3
4
[ 5 ]
6
5. Debugging Techniques
The problem with the
errors in the interpreter is that it generally doesn't give you an indication
of where the error occured. Since the logic script language is compiled,
it can't contain information on line numbers. The best way, after you've
encountered an error, is to systematically go through your code to find where
the error occurs. There are many techniques for this, and the interpreter
supplies a few of them internally.
The obvious starting point is to look around code that's for the room you're in
before the game crashes. Try and identify conditions that triggers
the error. These would include: touching a line, sound finished, changing
rooms, etc, etc. Once you know this, it will help you identify where
to use the debugging tools.
|
Tracing lets you step through each command individually.
|
Tracing: Tracing is a very useful tool available to AGI developers. It is available
in the original Sierra interpreters, NAGI and Sarien (through the console).
Tracing allows you to step through each command that the interpreter
parses whilst going through the logic code. It lets you skip past logic
code and you can call it in any part of the game through pressing the "scroll-lock"
key.
Initialising Trace: In the interpreter's "natural state", it doesn't
have tracing on by default. You have to perform a few functions first
to initialise it. Most game have debug code to do this. The standard
way is to press "alt-d", usually this will set the trace flag for you. The
commands vary from game to game though. If you're adding it to your
own game, the commands are:
set.flag(10);
trace.info(logic number, pos, height);
Flag 10 is the trace flag, it has to be set to enable tracing. "trace.info"
does the initialising of the trace data. The logic number points to
a special logic that has all the names of the commands as messages. The
"pos" is the line number of the top of the trace window whilst "height" is
the height of the trace window.
Calling Trace: There are two ways to open the trace window after you
have initialised it with code or by the alt-d/"trace on" commands.
- Press "scroll-lock". This should open the trace window
- Call the logic function "trace.on". This will open a trace window.
Depending on what you want to do, either way is approrpriate to call trace.
If you want to trace a logic from a certain time (ie, just before you
change rooms), it would be better to use trace.on. A word of warning
however, "trace.on" expects the trace code to be initialised before you call
it. Due to a bug, it could corrupt the state of the interpreter if
you call it before anything has been initialised.
Trace Commands: There are three basic commands whilst in the trace window.
- any key - Call function and skip to the next one.
- '+' - Continue parsing logic until you get to the next one. Handy for skipping over logics.
- 'scroll-lock' - Return to game.
Be careful whilst tracing because, before logic.0 is called again, the interpreter
will update the graphics and it may overlap over the trace window. Tracing
will still continue however.
Closing Trace Window: After you are finished with trace, you can close the window off by pressing "scroll-lock".
|
"show.mem" will help you tune the memory usage of your game.
|
Show Memory Info:
If you continue receiving "out of memory" or "script full", then you
may want to investigate the problem with the command "show.mem". It
gives you a few statistics on the memory usage. The info is as follows:
- heapsize - amount of memory allocated for the interpreter. The "heap".
- now - amount of memory used by the interpreter at the moment "show.mem" was called.
- max - maximum amount of memory that was ever used at a time.
- rm.0, etc. - amount of memory set aside for logic.0, menus, object, words.tok, script, things like that.
- max script - maximum size the script ever reached.
The "max script" statistic is useful. You can set the script size to
the maximum amount possible, play through the entire game, and the set the
script to the highest value used. It will save on memory for other
things.
|
Object Status lets you quickly see what your animated object is up to.
|
Object Status: The "obj.status.v" command is handy if you want
to know the properties of a certain animated object. It's probably
handy to also have a display of the ego's on the screen as well.
Logging: Logging is great if you want feedback from the users
of your game. You can use it to log anything. Most of the developers
from Sierra used it to log words that users typed in but the interpreter
didn't understand. It was this was that they managed to beef up their
dictionaries. You could use it to log whole phrases, places in the
screen that the user visits, the score at certain points in the game (to
see if they're missing anything)... etc etc. For beta versions of your
game, this would be great to incorporate if you want more feedback. You
could even have a flag that's set to remind the users when they quit, if
they logged anything, to email it back to you.
The syntax for the log function is simple:
log(<message>);
The format of the log is this:
"
Room <room number>
Input line: <last input line>
<your message here>"
Note the two extra lines at the start of each entry. The message that
you specify is wrapped so it will fit in an 80 character wide text file.
|
Having a constant display of the ego's position was common in Sierra's debug mode.
|
Print/Display: Another handy tactic is to contantly display
statistics on the screen. You may have seen some debug modes in Sierra
games that displayed the x, y coordinates of the ego. You don't have
to stop there. You could print on the screen the state of some flags
or variables that you're debugging, or the time left between events. I've
used it to accurately time the difference between events in the V intro and
also to find out when a flag was being reset in another game.
The best way to display something is to use this code:
display(24, 0, "my variable = %v50 ");
It's suggested you use a few spaces after the string, because if the value of the
variable changes from one digit to two, you won't get hanging characters.
Special Debug Code: In Kings Quest 3, they have an entire debug
logic section dedicated to the wizard because he is such a complicated beast.
You can track where he is, what he's doing, what he's waiting for you
to do and how long he's going to be. You could do the same thing for
you game if you wanted to debug some complicated code. Write code that
would be run side by side, to give the state of the code that you're trying
to debug.
Another technique is just to add to the generic debug logic code that all
games have. This includes all those "show var" and "tp" commands that
most AGI debug modes have. You could develop more debug commands off
that.
Vary the Interpreter: A different strategy to try is to run the game under different versions of
the interpreter or one of the fanmade interpreters. The reason for
this is because of the different ways they can handle the data. NAGI
has a few workarounds for bugs and so would Sarien and AGIL. One bug
that crashes the Sierra interpreter might not crash NAGI or Sarien. The
idea is to see the effects of what the bug does so, if game still runs with
the ego running around as a spaceship, you might want to look at any code
that changes the ego's view resource.
Page: 1
2
3
4
[ 5 ]
6