Small IF Logo

Doe's Main IF Page

Inform Glulx/Glk for Duncies

Unglklib

Storybook Kingdom of IF

An Iffy Theory

IF Art Gallery

My Games

IF Review Conspiracy

IFRC Archive at Brass Lantern

Parsifal
Inform Programming Tips


Contents


Other's Tips
Inform tutorials/resources.
(updated 5/11/02)

Doe's Tips
My Inform primer and sample code.


Others' Tips


Go To Best of Raif Search Engine
Why reinvent the wheel? Or spin it, going around in circles? For years I have squirreling away posts from raif -- those I considered the best Inform programming tips. So now I am sharing my nuts. When my hard disk crashed a couple of years I lost some, but I still have quite a few. They appear as originally posted: question, answer, and credit (who asked/answered). This uses a JavaScript search engine (frames) to search the articles I hoarded. Think of it as a mini-Google, focused exclusively Inform. Note: Q&As are usually intermediate to tricky Inform programing, not newbie Q&As.

Currently there are 50 articles. Enter nothing to list all. If you have problems loading a specific article, push the GO button again. (Click "Best of Raif" for search engine.)

INTRODUCTORY

Inform 6 Home Page
One of the best ways to learn Inform is to study the source code to Graham Nelson's example games. Especially, "Toyshop," which has code for a matchbook, writing on a blackboard, a driveable car, timers, daemons, and more. Sit at the feet of the master, little cricket, oohhmmm. Dr. Nelson's pages have been updated and have a classy new look.

The Inform FAQ
The Inform FAQ by Roger Firth, along with others, answers some very useful newbie questions. The answers at the end also cover more complicated programming problems. After Roger corners the FAQ arena he plans to never volunteer for anything ever again.

Int Fic Inform Tips
I don't know why Lucian P. Smith hides this page so well, but then I am confused about what "Interactive Fictions Patterns" are too. However, I do know that six people contributed to a very nice and UNCONFUSING newbies' introduction to Inform.

Inform for Beginners (Old)
By Jeff Johnson, covers much same ground as Int Fic, some in more detail, some less, plus some additional things. BTW - Who is Jeff? Is he still around? I haven't seen any posts by him. One of those unexplained mysteries of life, I guess, like Turkish delight. Maybe he IS missing, this guide comes to a screeching halt 3/4th of the way through.

Inform Programing (Old)
This is a quick overview of Inform by Andrew Clover. While not really an in-depth tutorial, there is one helpful page answering some basic programming questions. But I wonder how he got to use Dr. Nelson's home page's graphic. Must have connections.

9/27/99 It has been pointed out to me this is page rather dated and also, sadly, unfinished. For help with which files to download to get you up and running with Inform, visit, Help! Where do I download Interactive Fiction stuff? by Jonadab, instead.

INTERMEDIATE

Zarf's Handy Inform Tricks
Currently there isn't much here (six tricks on 11/06/02), but, hey, it's Zarf! -- so who cares? About one half are ways to fix bugs, the other half are tips on ways to do something tricky and Zarfian (hmmm, maybe that's synonymous).

Inform Z/Glulx Troubleshooting
Emily Short's Inform tips page covers tricky things she has learned the hard way about regular Inform and Inform Glulx. You can really benefit from her experience.

Alice:  An Inform Tutorial
This tutorial by Gareth Rees is on Graham Nelson's web page. It is based on Rees' "Through the Looking Glass," which was originally written in Inform 5.5. But Dr. Nelson has upgraded it (somewhat) for Inform 6. It takes you step-by-step through the creation of the game, in three stages. Rees is an advanced programmer, so all but the first stage may be too complicated for the newbie. This link appears to be broken.

Inform Developer's Guide
By Jim Fisher, this site has several articles by him and others covering various Inform programming problems -- from intermediate to advanced.

Informatory
Keep getting confused by Inform's mathematical operants? (So similar to c, but not c.) Check here. By Roger Firth, this "quick reference" is intended to be a supplement to the Inform manual. It offers brief summaries of the common Inform 6 commands and is also downloadable. Of course, it helps to read the manual first (hint, hint).

InfLight - an overview of Inform debugging
Another page from Roger Firth, a great one on Inform debugging. Do you have compiling errors? Find out why and how to fix them. Also covers various debugging tools.

ADVANCED/ALL

Raif's (Rec.Arts.Int-Fiction) Frequently Asked Questions
Or maybe instead of learning you need help with a weird problem -- possibly Vile Zero Errors From Hell. (Who named those errors that? Wasn't it the author of this FAQ?) In section 4.6, David Glasser outlines the problem and its solutions. You can also find a discussion of text editors, etc. I am very glad Glasser included vzeh, on the other hand, if he named it, he OWED everyone a explanation. :-) Also check out Zarf's (Andrew Plotkin's) The Vile Zero Errors from Hell.

Library Contributions at the IF Archive
Wait a minute! Maybe some tricky programming you can't figure out has already done and is right under your nose, only you don't realize it. So break down and download ALL the library "add-ons" if you haven't already. Also bump on over to the contributed source code for games and download all of them as well. You also might check out Inform 5.5, some contributed include (.h) files were never updated. Yah! Fill up your hard disk! (Actually, text files take up very little room.)

Last, but NOT least, read the The Inform Designer's Manual (new fourth edition, available in PDF format). Commonly referred to as the "DM," the manual is always your best reference to Inform. No, the D does not stand for what you call it when you are hopping mad because you unable to solve something. Instead of cursing, visit Rec.Arts.Int-Fiction (requires newsreader). Or search Google.


Doe's Tips


My Inform Primer
This primer is a "sort of" Inform tutorial. (This needs an update -- in writing and format and -- but otherwise everything is still relevant.) Updated 11/12/99.
Lower Case Room Names
Useful Find Hidden Objects Routine
An Elevator
A Two-Way Window
Invisiclues Hint System
Add To Scope Problems

Note:  If copying code, you will have to replace all the HTML "&lt;" and "&gt;"s with < and >. Also, all the following code has been tested.




Lower (& Upper) Case Room (Object) Names

Use the same as print (name) location; or print (name) noun; -- print (lowercase) location; To make upper case, change 'A' to 'a', 'Z' to 'z' and ('a' - 'A') to ('A' - 'a').

There might be instances where one would want a room name returned lower case from routine, or to appear in all lower/upper case on the status line.

Array name_buffer->64;
[ lowercase n i;

  name_buffer-->0 = 0;
  @output_stream 3 name_buffer;
  print (name) n;
  @output_stream -3;

  for (:i < (name_buffer-->0): i++ )
  {   if (name_buffer->(i+2) >= 'A' && name_buffer->(i+2) <= 'Z')
          name_buffer->(i+2) = name_buffer->(i+2) + ('a' - 'A');
      print (char) name_buffer->(i+2);
  }

];


A Useful Routine to Find Hidden Objects

When player searches and finds a hidden object, this automatically puts it in the player's "hands." If the player's hands are full, it puts a carried object in the sack object to make room for the new object in the player's hands (if the sack is carried and has enough room). Or it just puts the new object in the location. In other words -- this keeps a hidden object out of the object tree until it is found during a search. Then it picks up the new object automatically, if the player or sack has room.

! Example:
!
! Object bureau "bureau"
! with blah blah,
! before
! [; Search : If (self hasnt general)
!             { give self general;
!               Findobject(key);
!               "You find a key."; }
! ];

[ FindObject item j k;
   k = NCarried();
   if ((k+1) > player.capacity) ! if more than player can carry
   {  if (SACK_OBJECT notin player)
      {  move item to location; ! no sack, move to location
         rtrue;
      }
      k = 0;                    ! otherwise find object can remove from
      objectloop (j in player)  ! player and put in sack (to make room) 
         if (j ~= SACK_OBJECT && j hasnt worn && j hasnt light)
            k = j;
      if (k ~= 0)               ! move object in player to sack
      {  if (SACK_OBJECT hasnt open) give SACK_OBJECT open;
         keep_silent=1; <Insert k SACK_OBJECT> keep_silent=0;
         if (k in SACK_OBJECT)  ! move newly found object to player
         {  give item moved;
            move item to player;
            rtrue;
         }
      }
      move item to location;    ! no carried object that is moveable
      rtrue;                    ! so move newly found object to location
  }
  give item moved;              ! player capacity not exceeded
  move item to player;          ! so move newly found object to player
  rtrue;
];

!From Gareth Rees' Christminister.

[ NCarried i j;
    objectloop(i in player)
      if (i hasnt worn) j++;
    return j;
];


An Elevator (Three Floors)

This is an "old fashioned" elevator. There are two sets of doors. Those inside the elevator and those outside the elevator. Those outside must have a copy on each floor. This is so the player can go to any floor (using the stairs) and find the elevator doors closed on all the floors, except the one where the button was just pushed. I lifted this directly from an unreleased game of mine and think it is the easiest way to code an elevator. It is quite expandable for more floors and, of course, can be new without rattling doors.

If using this code in a game, I would appreciate credit since this is lifted from an unreleased game of mine. (When my game appears I don't want people thinking I copied YOU. Hehe.)

Object elevator "Elevator"
  has light
  with name "elevator",
  cur_floor 2,
  time_left 0,
  description
  [; print_ret "You are in an old-fashioned elevator. Three buttons on the
                wall are labeled  ~1~, ~2~ and ~3~. On a panel over the
                southern elevator doors, the ~", self.cur_floor, "~ is lit.";
  ],
  s_to e_doors,
  time_out
  [; keep_silent=1; <Open e_doors>; keep_silent=0;
     if (player in self)
        print_ret "Rattle. The ~", self.cur_floor, "~ on the panel
        lights up and the elevator doors slide open.";
     if (location==lobby or second_floor or third_floor)
     {  if (location.number == self.cur_floor)
        print "^Rattle. The metal doors on the northern wall slide open.^";
     }
     rtrue;
  ];

Elevator_button -> one_butt "one"
  has concealed
  with name "one" "1",
  number 1;

Elevator_button -> two_butt "two"
  has concealed
  with name "two" "2",
  number 2;

Elevator_button -> three_butt "three"
  has concealed
  with name "three" "3",
  number 3;

Object -> e_doors "elevator doors"
  has door static open
  with name "elevator" "doors",
  when_open "The elevator doors are open.",
  when_closed "The elevator doors are closed.",
  door_dir s_to,
  door_to
  [; switch(elevator.cur_floor)
    {  1 : return lobby;
       2 : return second_floor;
       3 : return third_floor;
     }
  ],
  before
  [; Close : switch(elevator.cur_floor)
             { 1 : give ff_doors ~open;
               2 : give sf_doors ~open;
               3 : give tf_doors ~open;
             }
     Open  : switch(elevator.cur_floor)
             { 1 : give ff_doors open;
               2 : give sf_doors open;
               3 : give tf_doors open;
             }
];
The above opens both the inside and outside doors. The inside doors are part of the elevator. Below is the outside doors class.
class sliding_doors
 has door
 with name "doors" "metal",
 when_open "The sliding doors to the elevator are open.",
 when_closed "The sliding metal doors are closed.",
 door_dir n_to,
door_to elevator;
An instance of the outside doors class, on the first floor. Duplicate for additional floors.
Sliding_doors -> ff_doors "metal doors";
There also has to be an outside button object (class instance) on each floor that is similar to the buttons inside the elevator. This is the first floor button.
Elevator_button -> call1_butt "call button"
  with name "call",
number 1;
How the elevator button works.
class elevator_button
 class button_class
 with
 number 0,
 before
 [ i j k; Push : i = self.number;
                 j = elevator.cur_floor;
                 if (i == j) "Nothing happens.";
                 if (i > j) k = i - j;
                 else k = j - i;
                 keep_silent=1; <Close e_doors>; keep_silent=0;
                 elevator.cur_floor = i;
                 StartTimer(elevator, k);
                 if (self==one_butt or two_butt or three_butt)
                    "Rattle. The doors slide close and the elevator
                     starts moving."; ! inside button pushed
                 "You hear a distant rattling, then a faint
                  grating sound.";    ! outside button pushed
];


Two-Way Window


A simple, unopenable two-way (visibility-wise) window. This uses the lowercase routine from above.

class is_window
 has concealed static openable
 with name "window",
! inside and outside locations of a window
 inside_wind 0,
 outside_wind 0,
 before
 [; Examine,
    Open     : print "The window";
               if (self has pluralname) print "s are ";
               else print " is ";
               "painted shut.";
    Search   : if (location == self.outside_wind)
               { print "Through the ", (name) self, ", you can see the ",
                       (lowercase) self.inside_wind;
                 if (child(self.inside_wind)~=0)
                 { print ". You can also see ";
                   WriteListFrom(child(self.inside_wind),
                     ENGLISH_BIT + RECURSE_BIT + TERSE_BIT + CONCEAL_BIT);
                   " inside.";
                  }
                 ".";
               }
               print "Through the ", (name) self, ", you can see the ",
                     (lowercase) self.outside_wind;
               if (child(self.outside_wind)~=0)
               { print ". You can also see ";
                 WriteListFrom(child(self.outside_wind),
                   ENGLISH_BIT + RECURSE_BIT + TERSE_BIT + CONCEAL_BIT);
                 " outside.";
               }
               ".";
 ];

Object library_wind "library window"
 class is_window
 with name "library",
 inside_wind library,
 outside_wind lawn,
found_in library lawn;


Yet Another Invisiclues Type Hint System


This uses a hint class. One hint is seen at a time, except for previously seen hints, which will be shown without the need to hit the "h" key again. Works with Graham Nelson's menus.h or L. Ross Raszewski's altmenu.h. Hints should appear in the menu help system.

class Hintobj
 with hints_seen 0,
 hint_done 0,
 the_hints "Put list of hints here (in the object of this class).",
 description
 [; self.showhints(); rtrue;
 ],
 showhints
 [ max i k;

   max = (self.#the_hints / 2);

   for (i = 1: (i <= max): i++)
   {   if ((i==1) && ((max > 1) && (self.hints_seen < max)))
          print "There are ", (LanguageNumber) max, " increasingly clear \
                 hints. Press H for another hint, any other key to quit.^^^";

       print "(", i, "/", max, ") ";
       print (string) (self.&the_hints-->(i-1));
       new_line; new_line;

! How many times through this loop? That is the number of the current
! hint. Starting with 1 = 0 hints_seen.

       if (self.hints_seen == (i-1)) self.hints_seen = self.hints_seen + 1;

! Only call read_char if currently on the last hint seen and
! skip on the very last hint.

       if ((i < max) && (i == self.hints_seen))
       {  @read_char 1 0 0 k;
          if (k ~= 'H' or 'h') return;
       }
   }

];
The following puts hints (at appropriate time in game play) on the help screen. Hint_done double checks that a completed hint is not inadvertently put back on on the help screen. Basically it just pops a new hint into the Hint Object, which is a menu. Readying a hint takes place in game code:
! after
! [; Take : if (self hasnt general
!              { give self general;
!                 HintReady(Hint1);
!                 "You pick up the axe.";
!              }
! ];

[ HintReady h;
  if ((h.hint_done == 0) && (h hasnt general))
  {  give h general;
     move h to Hints;
  }
];
Removes old hints. This never need be called. Depends how sensitive one wants one's hint system. Old hints can remain on the help screen. Would also be called in game code for each hint.
[ HintDone h;
  if (~~(h.hint_done))
  {  h.hint_done = 1;
     if (h in Hints) remove h;
  }
];
This is a hint example. This Menu would be part of a larger menu help system. Notice there are no commas between the the_hints.
Menu -> Hints "Hints";

Option Hint1 "How do I get the kitten out of the tree?"
 class Hintobj
 with the_hints "Try chopping down the tree."
                "Too destructive? Try a garden hose."
"No hose? Read raif for other ways to get the kitten down.";


Add To Scope Problems


Basically parent does not work on objects that are added to scope. It returns nothing. It won't return the object that contains the add_to_scope object as its parent. This occurs through out the whole library, since ObjectScopedBySomething is only called twice, in Verblibm.h. Most of the time this will probably not matter or even be desired behavior. However, sometimes it definitely is NOT. Also, I personally, think parent should always return something for an object in the tree, until one has reached the top object. I found this "bug" when updating outofrch.h. My "fix" for IndirectlyContains (which relies on parent) comes from that:

[ ScopedContains o1 o2 o3;
  while (o2~=0)
  {   if (o1==o2) rtrue;
      o3 = ObjectScopedBySomething(o2); ! added line
      if (o3 == 0) o2 = parent(o2);     ! these two lines slightly changed
      else o2 = o3;
  }
  rfalse;
 ];


! Example:

 if (ScopedContains(remote, button)) 
"The button is part of the remote control.";
Another way around this is never to use add_to_scope, but do this instead:
 Object owner "owner"
 has transparent
 with blah blah;

 Object -> part1 "part one"
 has static container openable;

 Object -> part2 "part two"
has static;
Transparent makes the owner's subobjects accessible, while static keeps the parts nontakeable, and both parent(part1) and parent(part2) will work correctly.


Infotips Table of Contents (Top)

Email any questions or suggestions for additional links to: doeadeer3@aol.com .

You are the counter visitor since
Monday, Sept. 20, 1999.