Roger Firth's IF pages

Home

InfLight -- Inform debugging

Email
Back up

In this segment, we'll be looking at switches which control how your game is compiled, and which tell you more about it.

Checking and debug -- S and D

Firstly, the S and D switches, which control the inclusion of code into your game to provide respectively Strict error checking and some Debug capabilities. Even if you don't use the Debug commands, you'll sure as hell be grateful that Strict checking discovers many of your coding snafus before your players do. Remember the message you see at the start of every game?

  Game banner

Almost uniquely among all the switches, S and D are highlighted in the game's introductory banner (the other one so favoured is X, showing that the Infix debugger is present). Seeing them shown like that here is a bit odd, since we haven't so far said anything about setting them. And indeed, Inform's behaviour here is -- controversial, perhaps -- since it turns S on (and with it D) by default. That's what you get out of the box; anything else, you need to ask for. This means that if you don't want Strict checking, you need explicitly to switch it off; this uses the ~S construct (think of removing an attribute from an object), which is one of the instances which doesn't work with Switches ... ;.

 

If you want this combination   

Use this on the command line   

Debug + Strict (the default)

-DS (but why bother?)

Debug alone

-D~S

Strict alone

You can't (Strict always implies Debug)

neither

-~S

So, the moral here seems to be: while you're developing and testing your game, you'll want both Strict error checking and Debug active, so accept the default setting. When you're ready to release the game, you don't want Debug active, which means turning off Strict also, which means -~S on the command line.

Strict checking includes things like ensuring that you don't try to address array entries which are before the start or after the end of the array. It also prevents you from performing operations on object number 0 -- more easily done that you'd imagine, for example after evaluating parent(myObject) when myObject currently has no parent. Before the advent of Strict checking, errors like this were such a common cause of games mysteriously crashing that they become somewhat fancifully know as Vile Zero Errors from Hell. Nowadays, thankfully, they're a lot less prevalent.

How memory is used -- o and z

While both S and D affected the code being compiled into your game, the next set of switches just control what the compiler tells you. The o switch provides a summary of offsets (in hexadecimal) to important divisions within the Z-machine:

 
Offsets in story file:
00042 Synonyms     0010a Defaults     00188 Objects    0031e Properties
00823 Variables    0126f Parse table  01971 Actions    01a65 Preactions
01a67 Adjectives   01a67 Dictionary   02608 Code       11d78 Strings

The z switch provides the same sort of information, but in more detail, and more readably:

 
Dynamic +---------------------+   00000
memory  |       header        |
        +---------------------+   00040
        |    abbreviations    |
        + - - - - - - - - - - +   00042
        | abbreviations table |
        +---------------------+   00102
        |  header extension   |
        +---------------------+   0010a
        |  property defaults  |
        + - - - - - - - - - - +   00188
        |       objects       |
        + - - - - - - - - - - +   0031e
        | object short names, |
        | common prop values  |
        + - - - - - - - - - - +   005fd
        | class numbers table |
        + - - - - - - - - - - +   00609
        | symbol names table  |
        + - - - - - - - - - - +   0080b
        | indiv prop values   |
        +---------------------+   00823
        |  global variables   |
        + - - - - - - - - - - +   00a03
        |       arrays        |
        +=====================+   0126f
Readable|    grammar table    |
memory  + - - - - - - - - - - +   01971
        |       actions       |
        + - - - - - - - - - - +   01a65
        |   parsing routines  |
        + - - - - - - - - - - +   01a67
        |     adjectives      |
        +---------------------+   01a67
        |     dictionary      |
        +=====================+   02608
Above   |       Z-code        |
readable+---------------------+   11d78
memory  |       strings       |
        +---------------------+   13750

The s switch, mentioned in the previous segment, also fits loosely into this category. While most of this stuff is fairly obscure, you need to be aware of the Z-machine's limits, especially if you're writing a large game. Remember that the top of readable memory (where the dictionary ends) can't be higher than $0FFFF, and that if the top of virtual memory (where the strings end) goes over $3FFFF, you'll need to switch from the default Version 5 to Version 8 with the v8 switch.

There's an additional compiler limitation: the section labeled "Z-code" cannot be larger than $40000 (262,144) bytes. If the Z-code region becomes too large, your game will no longer compile due to compiler back-patch errors. (The example game shown here has a very small Z-code section of 63,355 bytes: $11D78 - $2608 = $F770). Authors who note that their game is getting close to this limit are in for a difficult balancing act.

How things are numbered -- j and n

The j switch shows the number allocated to each object as the game is being compiled:

 
  6 "compass"
  7 "north wall"
  8 "south wall"
  9 "east wall"
 10 "west wall"
 11 "northeast wall"
 12 "northwest wall"
 13 "southeast wall"
 14 "southwest wall"
 15 "ceiling"
 16 "floor"
 17 "outside"
 18 "inside"
 19 "(darkness object)"
 20 "(self object)"
 21 "(Inform Parser)"
 22 "(Inform Library)"
 23 "(with no short name)"
 24 "Foyer of the Opera House"
 25 "Cloakroom"
 26 "small brass hook"
 27 "Foyer bar"
 28 "velvet cloak"
 29 "scrawled message"

The n switch performs the same function, at much greater length, for attributes, properties and actions:

 
Attr  00      animate
Attr  01      absent
Attr  02      clothing
dots
Attr  28      female
Attr  29      neuter
Attr  30      pluralname
Prop  04  LA  before
Prop  05  LA  after
Prop  06  LA  life
dots
Prop  48  L   parse_name
Prop  49  L   articles
Prop  50  L   inside_description
Action 'LetGo' is numbered 118
Action 'Receive' is numbered 120
Action 'ThrownAt' is numbered 122
Action 'Order' is numbered 124
Action 'TheSame' is numbered 126
Action 'PluralFound' is numbered 128
Action 'ListMiscellany' is numbered 130
Action 'Miscellany' is numbered 132
Action 'Prompt' is numbered 134
Action 'NotUnderstood' is numbered 136
Action 'Pronouns' is numbered 0
Action 'Quit' is numbered 1
Action 'Restart' is numbered 2
Action 'Restore' is numbered 3
dots
Action 'Empty' is numbered 118
Action 'InvTall' is numbered 119
Action 'InvWide' is numbered 120
Action 'GoIn' is numbered 121

The first block of actions -- LetGo through NotUnderstood --- are the Fake actions; then come the real actions (but I'm not sure I understand why the numbers overlap).

The code that's generated -- a and t

If you should want to see a listing of the Z-code program itself, use the a switch (very long) or the t switch (very very long):

 
    0  +00000  [ Main__

    0  +00001     call_vs      long_0 -> TEMP1
    0  +00006     quit

   33  +00008  [ Main

   33  +00009 <*;gt; call_vn      long_10 long_139 long_140
   33  +00011 <*;gt; rtrue

  146  +00014  [ LanguageToInformese

  147  +00015 <*;gt; rtrue

  160  +00018  [ LanguageContraction text

  161  +00019 <*;gt; call_vs      long_33 text short_0 -> sp
  161  +00020     pull         TEMP1
  161  +00023     je           TEMP1 short_97 short_101 short_105 to L1 if TRUE
  161  +0002b     je           TEMP1 short_111 short_117 short_65 to L1 if TRUE
  161  +00033     je           TEMP1 short_69 short_73 short_79 to L1 if TRUE
  161  +0003b     je           TEMP1 short_85 to L0 if FALSE
  161  +00040    .L1
  162  +00040 <*;gt; rtrue
  162  +00041    .L0
  163  +00041 <*;gt; rfalse
  dots
  381  +0e5a0  [ PrintRank

  381  +0e5a1 <*;gt; print_ret    "."

  387  +0e5a4  [ ParseNoun obj

  387  +0e5a5 <*;gt; store        obj obj
  387  +0e5a8 <*;gt; ret          long_65535
 
 
    0  +00000  [ Main__

    0  +00001     call_vs      long_0 -> TEMP1
                               e0 3f 00 00 ff
    0  +00006     quit
                               ba

   33  +00008  [ Main

   33  +00009 <*;gt; call_vn      long_10 long_139 long_140
                               f9 03 00 0a 00 8b 00 8c
   33  +00011 <*;gt; rtrue
                               b0

  146  +00014  [ LanguageToInformese

  147  +00015 <*;gt; rtrue
                               b0

  160  +00018  [ LanguageContraction text

  161  +00019 <*;gt; call_vs      long_33 text short_0 -> sp
                               e0 27 00 21 01 00 00
  161  +00020     pull         TEMP1
                               e9 7f ff
  161  +00023     je           TEMP1 short_97 short_101 short_105 to L1 if TRUE
                               c1 95 ff 61 65 69 80 01
  161  +0002b     je           TEMP1 short_111 short_117 short_65 to L1 if TRUE
                               c1 95 ff 6f 75 41 80 01
  161  +00033     je           TEMP1 short_69 short_73 short_79 to L1 if TRUE
                               c1 95 ff 45 49 4f 80 01
  161  +0003b     je           TEMP1 short_85 to L0 if FALSE
                               41 ff 55 00 00
  161  +00040    .L1
  162  +00040 <*;gt; rtrue
                               b0
  162  +00041    .L0
  163  +00041 <*;gt; rfalse
                               b1
  dots
  381  +0e5a0  [ PrintRank

  381  +0e5a1 <*;gt; print_ret    "."
                               b3 96 45

  387  +0e5a4  [ ParseNoun obj

  387  +0e5a5 <*;gt; store        obj obj
                               2d 01 01
  387  +0e5a8 <*;gt; ret          long_65535
                               8b ff ff

How things are spelt -- r

Finally in this segment, don't forget the r switch which dumps all of the text in the game to a file gametext.txt. Skip over the first 1000 or so lines containing stuff from the library, and you'll come to your strings:

 
You are standing in a spacious hall, splendidly decorated in red and gold,...
You've only just arrived, and besides, the weather outside seems to be...
Foyer of the Opera House
The walls of this small room were clearly once lined with hooks, though now...
Cloakroom
It's just a small brass hook,
with a cloak hanging on it.
screwed to the wall.
small brass hook
The bar, much rougher than you'd have guessed after the opulence of the foyer...
Blundering around in the dark isn't a good idea!
In the dark? You could easily disturb something!
Foyer bar
A handsome cloak, of velvet trimmed with satin, and slightly spattered with...
This isn't the best place to leave a smart cloak lying around.
velvet cloak
The message, neatly marked in the sawdust, reads...
The message has been carelessly trampled, making it difficult to read. You...
scrawled message
^^Hurrying through the rainswept November night, you're glad to see the bright..
You have lost

Before you release a game, copy this stuff and paste it into an editor or word processor with a spell-checker: yule bee sir prized watt ewe fined.


Next, we glance at some other ways of inspecting a game file from the outside.