Roger Firth's IF pages

Home

Inform 6: Frequently Asked Questions

Email
Back up

Into
the Intro

Setting
the scene

Preparing
to program

Learning
the lingo

Dabbling
in data

Operating
on objects

Verbal
versatility

Bothered
by bugs

History and
hereafter

Worldly
woes

Inside
information

Tips and
techniques

These advanced topics lift the hood and peer at the mechanics:

What's a Library entry point?
Where are all those Library files used?
    Overview of how a game runs
Can I use Inform without the standard Library files?
What's all this stuff about message-passing?
    Sending messages to Objects, Classes, Routines and Strings
What actually happens at the start and end of each turn?
What's the difference between a Daemon and a Timer?
    Example: timed bomb inside a box
    How to control the order in which daemons run
What's the difference between a Daemon and an each_turn property?
Why don't my daemons run at the start of a game?
How do I compile a game as Version 3?
Can I combine a game and an interpreter in a single file?
Could you explain how character sets are handled?
    Character encoding
    The ZSCII character set
    Allocating extra characters using the C switch
    Allocating extra characters using the Zcharacter directive
    Printing ZSCII characters
    Printing Unicode characters
    String packing
    Runtime issues
Little-used features: what's a low string?
Little-used features: what's an abbreviation?
Little-used features: what's a fake action?
How is the parse array structured?
How are the standard print rules implemented?

What's a Library entry point?

More information in the DM:
§A5

Inform provides around 20 opportunities for the game author to influence or control the Library's behaviour. You can do this from outside -- without having to change the standard header files -- because the Library provides 'hooks' on which, if you wish, you can hang suitable chunks of code. These hooks are actually calls to routines with pre-defined names; if your game provides a routine of that name, the Library calls it at the appropriate time. Your routine may either produce some supplementary output (for example, DeathMessage() provides an opportunity to explain how the player has 'died'), or return a value causing the Library to change its default behaviour (for example, ChooseObjects() allows you to influence how multiple or equivalent objects are selected).

Here's roughly how parserm.h invokes ChooseObjects() when deciding whether to include object 'j' in an ALL:

  flag=1;
  if (action_to_be == ##Take or ##Remove && parent(j)==actor) flag=0;
  k=ChooseObjects(j,flag);
  if (k==1) flag=1; else { if (k==2) flag=0; }
  if (flag==1) {    ! Decided to INCLUDE it
  ...
  } else {          ! Decided to EXCLUDE it
  ...
  }

Now while there's no need to worry about the details of how that works, you will notice that the Library makes a perfectly normal call to ChooseObjects(), without caring whether or not you've actually provided such a routine. How can this work? normally, the compiler complains bitterly if you call a routine which doesn't exist. The answer is: there will always be a ChooseObjects() routine; if you don't provide one, the Library supplies a dummy version instead. Right at the end of Grammar.h, you'll find the line:

More information in the DM:
§38

  #Stub ChooseObjects   2;

which is a shorthand way of saying:

  #IfNDef ChooseObjects;
  [ ChooseObjects a1 a2; rfalse; ];
  #EndIf;

Two points are worth noting here: If you're providing an entry point routine, do so before the #Include of Grammar.h. And, that rfalse is important: for those entry point routines which return a value, false always triggers the Library's default behaviour.

Where are all those Library files used?

The Inform Library comprises nine header (.h) files; why so many, and where are they all used? You already know that every game must #Include the three top-most files Parser.h, VerbLib.h and Grammar.h; what is perhaps less familiar is the manner in which those three files in turn #Include the rest of the Library. The diagram illustrates how this works:

Library files

The file english.h is actually included into parserm.h by the directive Include "language__", where language__ is a library variable (initialised to "english") which you can change with a compiler switch like +language_name=french. Also, if you count carefully, you'll notice that one file -- linklv.h -- isn't mentioned anywhere. That's because it applies only when using Modules, which as we all know is A Bad Idea.

More information in the DM:
§1.2 §4

The highlighted code to the right gives an overview of how the game runs (not that you need to know any of this other than from sheer curiosity). Every Inform program is required to have a Main() routine, but you don't write it yourself: the Library provides one in Parser.h. Main() simply invokes the play property of the InformLibrary object, and it's here that everything happens.

The play property routine first sets up the game -- calls your Initialise() routine, moves player to location, prints the game banner, and so on -- and then loops until deadflag is non-zero. Each iteration of the loop represents one turn: parse a line typed by the player, perform the appropriate action, and then carry out standard end-of-turn processing. Finally, the player wins or dies, deadflag becomes non-zero, and the loop ends. The play() routine prints an appropriate message, and exits back to Main(). That in turn exits, and the game is over.

Why so many files? probably a combination of clean modularity, author flexibility and the requirements of the module linking scheme. Why are parse_input(), play(), end_turn_sequence() and begin_action() implemented as object properties rather than standalone routines? I don't know, though I suspect it may be for compatibility with the message-passing mechanism.

Can I use Inform without the standard Library files?

Inform is actually a fairly general-purpose programming language, albeit with a few annoying limitations (for example, the Z-machine's Input/Output capabilities are somewhat limited, though Glulx is better in this respect). There's no reason why you shouldn't use the language for purposes other than writing Interactive Fiction and, if you do so, there's no particular need to #Include the library files Parser.h, VerbLib.h and Grammar.h. For example, this is a perfectly acceptable Inform program which runs on the Z-machine:

  [ Main;
      print "Hello world^";
  ];

More information in the DM:
§1.2 §2.5

That's pretty unexciting. Here's a slightly more useful Z-machine tool which scrambles text using ROT13: this involves replacing each letter with one that appears 13 characters later in the alphabet. (Note, by the way, that the Z-machine automatically converts all text to lowercase before storing it in the input buffer.)

  ! ROT13 for the Z-machine

  Constant INPUTBUFFER_SIZE 100;
  Array    inputBuffer -> 2                   ! Max size, actual size,
                        + INPUTBUFFER_SIZE    ! then the characters,
                        + 1;                  ! then a spare in case of overflow.

  [ Main i c;
      inputBuffer->0 = INPUTBUFFER_SIZE;
      while (true) {
          print "^^Enter some text> ";
          read inputBuffer 0;
          if (inputBuffer->1 == 0) quit;
          for (i=0 : i<inputBuffer->1 : i++) {
              c = inputBuffer->(i+2);
              switch (c) {
                'A' to 'M', 'a' to 'm': print (char) c + 13;
                'N' to 'Z', 'n' to 'z': print (char) c - 13;
                default:                print (char) c;
              }
          }
      }
  ];

Using Glulx, things are slightly more complex. For a start, the "Hello world" program won't quite run on the Glulx virtual machine which, unlike the Z-machine, doesn't automatically open a window in which to display the program's output. To make that happen, you need to include a few more lines:

  [ Main w;
      @setiosys 2 0;                      ! Select the Glk I/O system.
      w = glk($0023, 0, 0, 0, 3, 0);      ! Open a text-buffer window,
      glk($002F, w);                      ! and select it as the current output stream.

      print "Hello world^";
  ];

More information on Andrew Plotkin's Glulx and Glk pages

The Z-machine has its Input/Output mechanisms built into the interpreter. Glulx is more generalised: it can use any suitable I/O system, though in practice that usually means Andrew Plotkin's Glk. So, @setiosys 2 0; specifies the use of Glk, the glk($0023...) call uses glk_window_open() to return the identifier of a newly-created window, and then the glk($002F...) call uses glk_set_window() to direct I/O to that window. Not that you need to worry about how it works: just copy those initialisation statements into your own program.

There's another problem to be overcome before our ROT13 tool works on Glulx: we can't use the Inform read statement. Instead, we need more glk() calls to fetch the line of input text:

  ! ROT13 for the Glulx VM

  Constant INPUTBUFFER_SIZE 100;
  Array    inputBuffer -> INPUTBUFFER_SIZE;

  Array    gg_event --> 4;

  [ Main w i c;
      @setiosys 2 0;                      ! Select the Glk I/O system.
      w = glk($0023, 0, 0, 0, 3, 0);      ! Open a text-buffer window,
      glk($002F, w);                      ! and select it as the current output stream.

      while (true) {
          print "^^Enter some text> ";
          glk($00D0, w, inputBuffer, INPUTBUFFER_SIZE, 0);
          while (true) {                  ! Wait for RETURN to be pressed.
              glk($00C0, gg_event);       ! LineInput is the only interesting event.
              if (gg_event-->0 == 3 && gg_event-->1 == w) break;
          }
          if (gg_event-->2 == 0) quit;
          for (i=0 : i<gg_event-->2 : i++) {
              c = inputBuffer->i;
              switch (c) {
                'A' to 'M', 'a' to 'm': print (char) c + 13;
                'N' to 'Z', 'n' to 'z': print (char) c - 13;
                default:                print (char) c;
              }
          }
      }

  ];

Here, the glk($00D0...) call uses glk_request_line_event() to request a line of text from the window, and then the glk($00C0...) call uses glk_select() to detect that the text has been typed. Again, don't get too hung up on the mechanics. In fact, if you #Include infglk.h, you can make things a little more readable, by using sensible names rather than mysterious numbers:

  ! ROT13 for the Glulx VM

  Include "infglk";

  Constant INPUTBUFFER_SIZE 100;
  Array    inputBuffer -> INPUTBUFFER_SIZE;

  Array    gg_event --> 4;

  [ Main w i c;
      @setiosys 2 0;                      ! Select the Glk I/O system.
      w = glk_window_open(0, 0, 0, wintype_TextBuffer, 0);
                                          ! Open a text-buffer window,
      glk_set_window(w);                  ! and select it as the current output stream.

      while (true) {
          print "^^Enter some text> ";
          glk_request_line_event(w, inputBuffer, INPUTBUFFER_SIZE, 0);
          while (true) {                  ! Wait for RETURN to be pressed.
              glk_select(gg_event);       ! LineInput is the only interesting event.
              if (gg_event-->0 == evtype_LineInput && gg_event-->1 == w) break;
          }
          if (gg_event-->2 == 0) quit;
          for (i=0 : i<gg_event-->2 : i++) {
              c = inputBuffer->i;
              switch (c) {
                'A' to 'M', 'a' to 'm': print (char) c + 13;
                'N' to 'Z', 'n' to 'z': print (char) c - 13;
                default:                print (char) c;
              }
          }
      }

  ];

What's all this stuff about message-passing?

More information in the DM:
§3.9 §3.12

Inform games are constructed from four fundamental building blocks: Objects, Classes, Routines and Strings; other than primitive structures like variables and arrays, all of the components of a compiled game fit into one of these four categories. The most important category is the Object, and indeed it's the InformLibrary object, along with its more outgoing sister InformParser, which actually makes the game run.

How does it do that? Largely, by invoking the actionSub() associated with the player's current action, and by sending one-word messages to other objects -- the one(s) directly involved in that action, and others in the vicinity. The messages are the mechanism by which those objects (a) find out what's about to happen, and (b) have an opportunity to influence events. You can use the MESSAGES ON debugging command to watch them being sent.

Every message receives a reply; here's the syntax for sending a message and capturing the response:

  x = obj.message(p1,p2,...);

in which obj is the object to which the message is sent, message is the actual message, and p1 p2 etc are optional parameters associated with the message. The reply is placed in variable x. For example, a command like DROP THE BLUE BALL is first parsed to give action=Drop and noun=blueball, and then the -- somewhat simplified -- flow of execution is:

  if (noun.before() == false) {
      move noun to parent(player);        ! These three statements
      if (noun.after() == false)        ! are the essence of
          print "Dropped.^";              ! the DropSub routine.
  }

The two messages involved in that action are highlighted; they look familar, don't they? You know them better in the guise of the before and after properties, and indeed that's exactly what they are: the property names possessed by an object are the messages which the object is prepared to accept, and the values of those properties determine what replies those messages will receive. You can increase the set of messages to which an object will respond simply by defining appropriate properties matching those message names.

You can also send messages to Classes, Routines and Strings, but here the rules a slightly different: the set of acceptable messages is pre-defined and can't be increased. This is a list of each possible message, the effect of sending it, and the reply that it will generate.

This message...

... has this effect...

... and returns this value

obj.prop()
(when the value of prop is a routine)

Sets self to obj, sender to the sending object (often InformLibrary), and invokes the routine.

The value returned by the routine.

obj.prop()
(when the value of prop is a string)

Outputs the string, followed by a newline.

true

obj.prop()
(when the value of prop is false, nothing, zero or unspecified)

None.

false

obj.prop()
(when prop is a common property not defined by obj)

None.

The default value of prop.

obj.prop()
(when the value of prop is a small number)

None.

The value of prop. Because 'small' is ill-defined, this usage requires care; a safer technique is simply x=obj.prop;

obj.prop()
(when the value of prop is a large or negative number)

Usually causes a run-time error.

 

obj.class::prop()
(when the value of prop is any of the above)

Provided that object obj is of class class, sends the message to the prop property of the class, rather than to the (inherited or over-ridden) prop property of the object.

The value from that same class property.

class.remaining()

None.

The number of pre-defined object instances of class which are not currently active.

class.create() or
class.create(p1,p2,p3)

Creates an object obj of this class (actually, activates a pre-defined instance) with a parent of nothing. If obj has inherited a create property routine from class, sends a further message obj.create() or obj.create(p1,p2,p3).

obj, or nothing if no more instances can be activated.

class.recreate(obj) or
class.recreate(obj,p1,p2,p3)

Re-initialises obj to its state at creation. If obj has inherited a create property routine from class, sends a further message obj.create() or obj.create(p1,p2,p3).

false

class.destroy(obj)

Destroys an object of this class (actually, de-activates a pre-defined instance). If obj has inherited a destroy property routine from class, sends a further message obj.destroy().

false

class.copy(obj,source_obj)

Sets the property and attribute values of obj equal to those of source_obj. Both objects must be members of class.

false

routine.call(p1,p2,...)

Invokes the routine;
essentially equivalent to routine(p1,p2,...)

The value returned by routine.

string.print()

Outputs the string, followed by a newline;
equivalent to
  print_ret "string"

true

string.print_to_array(array)

Writes the number of characters in the string into word array-->0, and the individual string characters into bytes array->2, array->3, array->4, etc; equivalent to
  @input_stream 3 array;
  print "
string";
  @input_stream -3;

The number of characters in string.

What actually happens at the start and end of each turn?

More information in the DM:
§22

Start: The parse_input property of the InformParser object is responsible for:

  1. displaying the prompt, by calling L__M(##Prompt),
  2. running the optional AfterPrompt entry point routine,
  3. refreshing the status line, by calling DrawStatusLine(),
  4. reading the player's typed input,
  5. dealing with an AGAIN, OOPS or UNDO,
  6. parsing the player's input.

More information in the DM:
§20

End: The end_turn_sequence property of the InformLibrary object is responsible for:

  1. adjusting the turns and the_time variables,
  2. running all active daemons and timers,
  3. running any each_turn property for the location, and then for each object in scope,
  4. running the optional TimePasses entry point routine,
  5. checking whether the location has light,
  6. giving the moved attribute, and optionally awarding scores, to any objects which the player has just picked up.

What's the difference between a Daemon and a Timer?

Not a great deal: each is a routine, defined as an object's embedded property routine, which has no effect until you explicitly set it running. The difference lies in what happens next: a daemon then runs a daemon() routine automatically at the end of each turn (until you stop it or the game finishes); a timer does nothing for a specified number of turns (stored in time_left), and then runs a time_out() routine once only. To illustrate the distinction, consider these two simple examples. The blue box defines a daemon which makes the box 'tick' for as long as it's switched on, while the red box defines a timer which makes the box explode without notice three turns after being switched on.

More information in the DM:
§20

  Object  -> "blue box"
    with  name 'blue' 'box',
          after [;
              SwitchOn: StartDaemon(self);
              SwitchOff: StopDaemon(self);
              ],
          daemon [;
              if (IndirectlyContains(location,self))
                  "^An ominous ticking noise is coming from the box.";
              ],
    has   switchable ~on;

  Object  -> "red box"
    with  name 'red' 'box',
          after [;
              SwitchOn: StartTimer(self,3);
              SwitchOff: StopTimer(self);
              ],
          time_out [;
              if (IndirectlyContains(location,self))
                  print "^The box explodes into a zillion fragments.^";
              remove self;
              ],
          time_left 0,
    has   switchable ~on;

The blue daemon runs once each turn from the turn where you call StartDaemon() until the turn where you call StopDaemon(); the red timer waits three turns after you call StartTimer(), and then runs explosively... unless the player switches off the red box in time. To allow for the player switching on a box and then wandering away, both daemon and timer print their output only if they’re in the same room as the player.

In fact, because a daemon runs at the end of every turn, you can make it do the work of a timer as well. Here the blue and red boxes have been combined:

  Object  -> "purple box"
    with  name 'purple' 'box',
          after [;
              SwitchOn: self.time_left = 3; StartDaemon(self);
              SwitchOff: StopDaemon(self);
              ],
          daemon [;
              if (self.time_left > 0) {
                  (self.time_left)--;
                  if (IndirectlyContains(location,self))
                      "^An ominous ticking noise is coming from the box.";
                  }
              else {
                  if (IndirectlyContains(location,self))
                      print "^The box explodes into a zillion fragments.^";
                  remove self;
                  }
              ],
          time_left 0,
    has   switchable ~on;

In a complicated game many daemons can be active at the same time, and you may then encounter problems with the order in which they run (which is not under your direct control); this is most evident with daemons which are frequently stopped and started. For example, suppose that one daemon causes a nasty dwarf to roam though the rooms in your game, while another causes the player’s sword to glow when evil is nearby. You really need to ensure that the 'dwarf' daemon runs first, so that the 'sword' daemon can immediately react if the dwarf moves into the player’s location. There are two standard techniques for controlling the order in which daemons run. One method is to foresake the Library's standard StartDaemon() and StopDaemon() routines, and instead run continuously a single 'superdaemon' which in turn calls the real daemons, in the desired order, if a suitable property (or attribute) is set. For example, to ensure that three daemons run, if at all, in the order X-Y-Z, you could write:

  [ Initialise;
          StartDaemon(superdaemon);
          ...
          ];

  Object  superdaemon
    with  daemon [;
              if (objX.daemon_is_active) objX.daemon();
              if (objY.daemon_is_active) objY.daemon();
              if (objZ.daemon_is_active) objZ.daemon();
              ];

  Object  objX
    with  daemon [; ... ],
          daemon_is_active false;

  Object  objY
    with  daemon [; ... ],
          daemon_is_active true;

  Object  objZ
    with  daemon [; ... ],
          daemon_is_active true;

In this example, you’d code the assignment objX.daemon_is_active = true; instead of the routine call StartDaemon(objX); and objX.daemon_is_active = false; instead of StopDaemon(objX);.

The other approach is to use Andrew Plotkin's daemons.h from the Archive, which enables you to assign priority levels to your daemons (and timers). Higher priorities always run before lower ones, so you could then write:

  Object  objX
    with  daemon [; ... ],
          daemon_priority 50;

  Object  objY
    with  daemon [; ... ],
          daemon_priority 30;

  Object  objZ
    with  daemon [; ... ],
          daemon_priority 10;

No superdaemon is needed, and this time the standard StartDaemon() and StopDaemon() routines can be used as normal.

If you're not concerned about daemon/timer sequence, you can ignore both of these complications and just follow the basic procedures. Otherwise, which one you adopt is down to you: the superdaemon approach avoids the need to patch Library routines, but doesn't control timers (which run in unspecified order, always after the daemons). The priority system controls both daemons and timers, but doesn't allow one daemon/timer to start another (though stopping isn't a problem).

What's the difference between a Daemon and an each_turn property?

Again, each is a routine, defined as an object's embedded property routine. A daemon property needs to be explicitly started, whereupon it runs at the end of each turn until stopped. An each_turn property doesn't need to be started; it is automatically run by the parser, but only at the end of those turns when the associated object is in scope.

Typically, use a daemon to control a process which continues regardless of whether the player is there to watch it, or not (for example, the exploding box). Use an each_turn to control a process which might as well be suspended if there's no audience (for example, telling the player about the sleeping giant who grunts and snores in the corner of the cave).

Why don't my daemons run at the start of a game?

One fairly frequent use for a daemon or each_turn property is to add atmospheric information. For example, consider this specialised Room class:

  Class   Coastal
    with  each_turn "^The sound and smell of the sea is never far away.",
    has   light;

which simply prints the string at the end of the description for each Coastal room. Well, nearly always; this doesn't happen at the very start of a game:

  On the beach
  An interactive Shute story.
  Release 1 / Serial number 040112 / Inform v6.30 Library 6/11 S

  By the sea
  You stand on a small dune overlooking an ocean inlet, watching the waves
  break gently on the sandy shore. A path leads inland to the east.

  >

Since the game has just displayed the description of a Coastal room, you might expect to see each_turn adding its small contribution. The reason that you don't see it is because timers, daemons and each_turn properties are triggered only at the end of a turn, just after turns and the_time have been incremented (see the topic above). The first turn doesn't end until the player types something and presses Return.

Although this library behaviour is logical, it can sometimes be a nuisance, so here's how to work round it: by defining a LookRoutine() entry point. A LookRoutine() is called by the library at the end of every Look action, including the one which prints the very first description. So, by detecting that situation -- that it's the start of a game -- you can yourself activate timers and daemons, each_turn properties or both. Here's the code to run just the current location's each_turn property, which is all that we need to crack the problem illustrated above:

  [ LookRoutine;
      if (turns == 1 && verb_word == 0)
          location.each_turn();
  ];

(The check on verb_word catches the player's first command being another LOOK.) If you want to run all appropriate each_turns, or trigger the timers and daemons, then it's slightly trickier; you need to copy a block of code from InformLibrary.end_turn_sequence, defined two-thirds of the way through parserm.h:

  [ LookRoutine;
      if (turns == 1 && verb_word == 0) {
          ! run all timers and daemons
          for (i=0 : i<active_timers : i++) {
              if (deadflag) return;
              j = the_timers-->i;
              if (j ~= 0) {
                  if (j & WORD_HIGHBIT) RunRoutines(j&~WORD_HIGHBIT, daemon);
                  else {
                      if (j.time_left == 0) {
                          StopTimer(j);
                          RunRoutines(j, time_out);
                      }
                      else
                          j.time_left = j.time_left-1;
                  }
              }
          }
          ! run each_turn for all in-scope objects
          scope_reason = EACH_TURN_REASON; verb_word = 0;
          DoScopeAction(location);
          SearchScope(ScopeCeiling(player), player, 0);
          scope_reason = PARSING_REASON;
      }
  ];

Fortunately, version 6/11 of the Library makes this much simpler:

  [ LookRoutine;
      if (turns == START_MOVE && verb_word == 0) {
          RunTimersAndDaemons();
          RunEachTurnProperties();
      }
  ];

How do I compile a game as Version 3?

Occasionally, the only interpreter available for your computer doesn't support Z-code higher than Version 3 (standard). To compile for this, use:

Can I combine a game and an interpreter in a single file?

Very occasionally, it's convenient to distribute a single ready-to-run package containing both a Z-code game file and a suitable interpreter. I know of a couple of tools which do just this:

Try it: here's my tiny (50KB) Cloak of Darkness example, in the form of a Jzip bundle (155KB), a Monkey bundle with WinFrotz (275KB), and a plain WinZip archive with WinFrotz (95KB).

Could you explain how character sets are handled?

We'll have a go... but it's a lengthy topic, so it deserves a page of its own.

Little-used features: what's a low string?

More information in the DM:
§1.11

Whereas most character strings (other than words in the dictionary) are stored all together, along with the Z-code routines, in the High Memory area of the Z-machine, a handful can be held in a part of the Dynamic Memory area called the Low String Pool. Although you can't modify those strings as a game progresses, you can change the way in which they're accessed. This is best explained by example; suppose that your game includes this statement, which is executed periodically:

  if (the_time > 359 && the_time < 1080) { string 0 "sun"; string 1 "bright blue"; }   ! day:   06:00 - 17:59
  else                                   { string 0 "moon"; string 1 "night-time"; }   ! night: 18:00 - 05:59

What happens is: at compile time the compiler places all four of those strings "sun", "bright blue", "moon" and "night-time" in the Low String Pool area, along with a default string of "   " (three spaces). At run time, the interpreter has 32 Low String pointers, numbered 00 to 31, which initially all point to the default three spaces. When the interpreter executes the statement above, it either adjusts pointer 00 to refer to "sun" and pointer 01 to refer to "bright blue", or it adjusts pointer 00 to refer to "moon" and pointer 01 to refer to "night-time". Although there's a fixed limit of 32 pointers, there's less restriction on the number of strings to which they point; you can if required adjust the string which each references many times during the course of a game.

What use is this? Well, you can access the current values of the 32 low string pointers by embedding the forms @00 to @31 in print strings; the effect is to output whatever those pointers currently reference. Thus, these statements:

  style bold; print "The @00 shines down from the @01 sky."; style roman;

will produce this 'in daytime':

  The sun shines down from the bright blue sky.

this 'at night':

  The moon shines down from the night-time sky.

and this if you try to print the message before having executed any assignments to pointers 00 and 01 (so be careful):

  The     shines down from the     sky.

In fact, low strings can be useful even if their values don't change during the game. Suppose that your family-set game makes frequent mention of "Grandfather". You could code it thus:

  [ Initialise;
      string 0 "Grandfather";
      ...
  ];

  Object  study "@00's study"
    with  description
              "@00 loves to relax in this shadowy book-filled den, and can be found here
              most evenings, dozing before the big log fire. In all the years you've been
              visiting him, you've never known @00 not to have an open book next to his chair.",
          s_to workshop,
    has   light;

  Object  workshop "@00's workshop"
    with  description
              "His workshop is @00's pride and joy, with every tool hanging well-oiled in
              its appointed place, every nut and bolt, nail and screw, rivet and washer
              meticulously filed away in row upon row of neatly labelled tobacco tins.
              @00 can usually be found here soon after breakfast, stopping work only at
              lunchtime and for an occasional nap.",
          n_to study,
    has   light;

The real advantage here is economy of memory. A word like "Grandfather" occupies 12 storage units (two units for the capital "G" and one for each lower case letter, with each unit requiring five bits) every time it's used. A pointer like "@00" needs only two storage units for each use, plus a single block of 12 units to hold the word in the Low String Pool, so for text that's repeated frequently, the savings can soon add up.

For completeness, we should mention that earlier releases of Inform used a slightly clumsier mechanism, requiring a Lowstring directive:

  Lowstring GF_STR "Grandfather";

  [ Initialise;
      string 0 GF_STR;
      ...
  ];

Although this mechanism still works, there's no reason to use it; the new method which doesn't require a Lowstring directive is simpler and clearer.

Little-used features: what's an abbreviation?

More information in the DM:
§45

In the previous topic, we showed how one use for the 32 Low Strings is as shorthand for words or phrases which occur frequently in printed text: you just assign values to them in Initialise(), and then use the forms @01..@31 in your text strings, just as you might use @@64 to print a literal "@", or @^a to print "â".

That's fine for long words or discrete phrases which you'll easily recognise as you're composing your text. However, there are much greater memory savings to be made by abbreviating short sequences, maybe only three or four characters long, which crop up frequently both on their own or as parts of longer words (for example, "the" has already appeared eight times in this topic, "for" six times, " as" four times). Cutting each of those down to two storage units doesn't look much, but over the length of a big game, it soon saves a considerable amount. Note that phrase "over the length of a big game" -- all of this talk about conserving memory is relevant only when you're fighting to keep your game within the overall Z-Machine limits (256Kb for a Version 5 game, or more probably 512Kb for a Version 8 game).

Abbreviations are like Low Strings in that they're stored in the Low String Pool, referenced within strings using just two storage units, and applicable only to printed text. They're unlike Low Strings in four ways:

  1. Each abbreviation you wish to use must be pre-declared by an Abbreviate directive.
  2. You can declare up to 64 abbreviations, versus 32 low strings.
  3. Having declared them like that, you don't have to mark them explicitly in the text; instead, the compiler finds them automatically...
  4. ...but only if you select Economy mode by supplying the -e compiler switch; if you forget that, your Abbreviate directives have no effect.

Each potential abbreviation needs to be specified in a separate Abbreviate directive, which looks like this:

  Abbreviate " the ";

This tells the compiler that you think those five characters occur often enough to be worth abbreviating (bit of a no-brainer, really). To decide which phrases are worth abbreviating, you can (a) just guess, (b) run the compiler (very very slowly) with the -u switch, or (c) use Emily Short's handy list.

Little-used features: what's a fake action?

More information in the DM:
§6

As we explained in How do I define a new verb?, an 'action' results from the parser matching some text typed by the player with a line of grammar, and is by default dealt with by a matching routine. (We showed a grammar for the verbs SMILE, GRIN, SMIRK, BEAM and TWINKLE causing an action of Smile, handled by a SmileSub() routine.)

We emphasise "by default" because it's common to intercept an action before the action routine gets a chance to do its stuff. That's exactly what the before property is there for -- to enable an object which is the subject of an action to behave in an appropriate manner, which may be to do something completely non-standard.

Most actions affect a single target object, a few have no target (for example PRAY, SLEEP, SWIM), and a few mention two objects (for example ATTACH X TO Y, PUT X IN Y, THROW X AT Y). It's this last group that we're interested in here; the ones where two objects are involved in the action. Not unreasonably, the second object might like to have a say in what's going on, but there isn't a mechanism equivalent to before and after -- which apply only to the first object -- whereby the second can automatically be consulted. The closest you get is react_before and react_after, but any react_before properties run prior to any before properties, when what you'd really like is something that runs once the first object's before has decided to go ahead, but before it actually happens.

So, if there isn't a built-in way of dealing with situations like this, you have to devise something appropriate yourself. By way of example, let's consider the POINT X AT Y process which we described in How do I use my new object property?, where the first object uses this code to get the second object involved:

  before [;
    PointAt:
      if (self has light && second provides when_lit) return second.when_lit();
  ],

and the second object deals with that involvement something like this:

  when_lit "The owl blinks in mild surprise.",

Here's that same example, with an alternative implementation using a fake action. What's 'fake' about such actions is that they never appear in a line of grammar (and so cannot be directly triggered by anything the player types); neither do they have a handler routine. Since the presence of both those is what makes a normal action acceptable, you need to persuade the compiler that what you're doing is valid; that's what the Fake_Action directive is there for. The whole thing looks like this:

  Fake_Action PointedAt;

  Object  -> "flashlight"
    with  name 'flashlight',
          before [;
            PointAt:
              if (self has light) {
                  action = ##PointedAt;
                  if (second.before()) { action = ##PointAt; rtrue; }
                  action = ##PointAt;
              }
          ],
          after [;
            SwitchOn:  give self light;
            SwitchOff: give self ~light;
          ],
    has   switchable ~on ~light;

  Object  -> "owl"
    with  name 'owl',
          before [;
            PointedAt:
              "The owl blinks in mild surprise.";
          ],
    has   animate;

  Object  -> "mouse"
    with  name 'mouse',
          before [;
            PointedAt:
              remove self;
              "The startled mouse disappears into the undergrowth.";
          ],
    has   animate;

  [ PointAtSub; "Pointless."; ];

  Verb 'aim' 'point'
      * held 'at'/'on'/'towards' noun -> PointAt;

  Extend only 'shine'
      * held 'at'/'on'/'towards' noun -> PointAt;

The verb stuff at the end is the same as before, but the highlighted object definitions are a bit different. The flashlight's before property now has to adjust the action variable, effectively pretending that the current action is PointedAt rather than PointAt, then manually give the second object's before property a chance to react, then finally reinstate the real PointAt action before letting the action complete appropriately. That's all a bit messy; on the other hand, the objects being pointed at can now deal with the situation by means of regular before properties rather than with our invented when_lit property. (By the way, if you're wondering why we didn't use the <PointedAt second> or <<PointedAt second>> statements in the flashlight, it's because neither of those returns the second object's response, which the flashlight needs to determine whether (if true) the action has been dealt with, or (if false) the default action should be allowed to continue.)

Personally, I think that fake actions have no advantage over the method using local properties. Also, the DM4 labels them "obsolete", so that's a better reason for avoid their use.

How is the parse array structured?

Every time that the player types a command, the parser:

  1. stores all of the typed characters in a buffer array (and, in the Z-machine, converts them to lower case),
  2. divides that stream of characters into 'tokens' -- commas, periods, and words separated by spaces,
  3. attempts to find each token in the game's dictionary, and
  4. stores the information about the tokens in a second array: parse.

For example, the command SAILOR,SAY HELLO is divided into four tokens: SAILOR, the comma, SAY and HELLO.

The library routine KeyboardPrimitive() is responsible for this processing, and you can call it yourself if you need to ask the player for some additional input. Even if you don't, there are still cases where it's useful to be able to manipulate the input command stream (see, for example, the use of the BeforeParsing() entry point in this topic), which requires that you understand the structure of the two arrays.

More information in the DM:
§2.5

The DM4 is a little confused on the arrays' layout, so we'll explain them using our SAILOR,SAY HELLO example. After that command, the contents of the two arrays are as shown below. buffer is a byte array holding the characters as typed. The first byte is preset to the maximum number of characters that can be handled, and shouldn't be altered -- the library sets it to 120. The second byte specifies that 16 characters have been typed. Those character then follow.

Z-machine text buffers

So, that gives us:
  buffer->0   is always 120
  buffer->1   is the character count (16)
  buffer->2   is the first character ('s')
  buffer->3   is the second character ('a')
  ...
  buffer->17  is the sixteenth character ('o').

parse is more complex, being a mixed array of bytes and words. The first byte is preset to the maximum number of tokens that can be handled, and shouldn't be altered -- the library sets it to 15. The second byte specifies that 4 tokens have been identified. Information on those tokens then follows.

In this example:
  parse->0   is always 15
  parse->1   is the token count (4)
  parse-->1  is the dictionary address of the first token ('sailor')
  parse->4   is the number of characters in the first token (6)
  parse->5   is the token's start position in buffer (2)
  parse-->3  is the dictionary address of the second token (',')
  parse->8   is the number of characters in the second token (1)
  parse->9   is the token's start position in buffer (8)
  parse-->5  is the dictionary address of the third token ('say')
  parse->12  is the number of characters in the third token (3)
  parse->13  is the token's start position in buffer (9)
  parse-->7  is zero, because the fourth token ('hello') isn't in the dictionary
  parse->16  is the number of characters in the fourth token (5)
  parse->17  is the token's start position in buffer (13).

Glulx text buffers

If you're using Glulx, the principles are the same... and the arrays are different (see the Glulx Technical Reference for more details). Neither buffer nor parse stores its maximum capacity at the beginning. Also, the Glulx buffer uses an initial word rather than a byte to hold the number of character typed; after that, its content is identical to the Z-machine's. The Glulx version of parse, however, differs from the Z-machine's in that it's a word-only array -- one word for the token count, and then one each for dictionary address, token length and token start position in buffer. (to save space on this page, the width of entries in the diagram on the right has been compressed.) Note that buffer contains the characters exactly as typed, without any case conversion.

To step through all of the parsed tokens, use a loop like this:

  [ tokenCount;
      #Ifdef TARGET_ZCODE;
      return parse->1;
      #Ifnot; ! TARGET_GLULX
      return parse-->0;
      #Endif; ! TARGET_
  ];

  for (w=1 : w<=tokenCount() : w++) { ... }

where variable w numbers the tokens as 1,2,3... Then, use these routines to fetch the three attributes of each token:

  [ tokenDict w;  ! dictionary value of token 1,2,3...
      #Ifdef TARGET_ZCODE;
      return parse-->(2*w - 1);
      #Ifnot; ! TARGET_GLULX
      return parse-->(3*w - 2);
      #Endif; ! TARGET_
  ];

  [ tokenLen w;   ! length in chars of token 1,2,3...
      #Ifdef TARGET_ZCODE;
      return parse->(4*w);
      #Ifnot; ! TARGET_GLULX
      return parse-->(3*w - 1);
      #Endif; ! TARGET_
  ];

  [ tokenPos w;   ! position in buffer of token 1,2,3...
      #Ifdef TARGET_ZCODE;
      return parse->(4*w + 1);
      #Ifnot; ! TARGET_GLULX
      return parse-->(3*w);
      #Endif; ! TARGET_
  ];

Here's a simple example: an intransigent NPC who responds to all commands with "Surely you don't expect me to...?". This is his orders property:

  orders [ bufsize i;
      #Ifdef TARGET_ZCODE;
      bufsize = WORDSIZE + buffer->1;             ! end of Z-machine buffer
      #Ifnot; ! TARGET_GLULX
      bufsize = WORDSIZE + buffer-->0;            ! end of Glulx buffer
      #Endif; ! TARGET_
      if (tokenDict(2) == ',//') i = tokenPos(3); ! NPC, do something
      else                       i = tokenPos(4); ! TELL NPC TO do something
      print "~Surely you don't expect me to ";
      for (: i<bufsize : i++) print (char) buffer->i;
      "?~";
  ],

The only real complexity is the need to distinguish between NPC, DO SOMETHING (where the actual command starts at the third token) and TELL NPC TO DO SOMETHING (where the fourth token begins the command). For example:

  >SAILOR,JUMP IN THE AIR
  "Surely you don't expect me to jump in the air?"

  >TELL SAILOR TO LIE ON THE GROUND
  "Surely you don't expect me to lie on the ground?"

  >YES
  That was a rhetorical question.

How are the standard print rules implemented?

A print rule is simply a routine which outputs its single argument in some form. For example, a print rule for small Roman numerals might look like this:

  [ roman n;
      switch (n) {
        1:  print "I";
        2:  print "II";
        3:  print "III";
        4:  print "IV";
        5:  print "V";
        6:  print "VI";
        7:  print "VII";
        8:  print "VIII";
        9:  print "IX";
        10: print "X";
        default: print "[", n, "]";
      }
  ];

Having defined such a routine, you can either use it as a print rule or call it directly -- the two work identically:

  print "Chapter ", (roman) chapNumber, ": ", (string) chapTitle, "^"; ! Option 1

  print "Chapter ";
  roman(chapNumber);                                                   ! Option 2
  print ": ", (string) chapTitle, "^";

Caution: remember that, as we explained much earlier, you'll get a spurious '1' appearing if you call the print rule as a routine:

  print "Chapter ", roman(chapNumber), ": ", (string) chapTitle, "^";  ! WRONG

Although it's normally shorter and more convenient to invoke your routine as a rule in a print statement (Option 1) rather than as a conventional call (Option 2), there are exceptional cases. One such is when you wish to print to an array rather than to the screen, for example so that you can manipulate the characters prior to display. The library routine PrintToBuffer() does just this, so one way of outputting the chapter number in lower-case roman numerals is this:

  Constant MYBUF_SIZE 10;
  Array myBuf buffer MYBUF_SIZE;

  n = PrintToBuffer(myBuf, MYBUF_SIZE, roman, chapNumber);
  for (i=0 : i<n : i++) print (char) LowerCase(myBuf->(i+WORDSIZE));

All well and good, but what if you wish to invoke one of the standard print rules -- (a), (name), (The) and so on -- in this manner? There's a problem, in that although each rule is implemented by a routine, the name of the routine isn't the same as the name of the rule. So, to help if you wish to use the standard rules in this manner, here are the routines to call (the "__" are two underscore characters):

Standard print rule

Equivalent routine call

(A) object

CIndefArt(object)

(a) object

IndefArt(object)

(address) dictionary_word     

RT__ChPrintA(dictionary_word)     

(char) expression

RT__ChPrintC(expression)

(name) object

PrintShortName(object)

(number) expression

EnglishNumber(expression)

(object) object

RT__ChPrintO(object)

(property) property

Print__PName(property)

(string) string

RT__ChPrintS(string)

(The) object

CDefArt(object)

(the) object

DefArt(object)

Into
the Intro

Setting
the scene

Preparing
to program

Learning
the lingo

Dabbling
in data

Operating
on objects

Verbal
versatility

Bothered
by bugs

History and
hereafter

Worldly
woes

Inside
information

Tips and
techniques