AliceAlice: An Inform tutorial, part 3

  1. Introduction
  2. Doing It My Way: to reformat (or not)
  3. How Not To Go Backwards: using transcripts
  4. Taking Stock: small additions to the part 2 tutorial
  5. Designing The Midgame: a crossword at war with a chessboard
  6. Afterword

1. Introduction

"Now, if you'll only attend, Kitty, and not talk so much, I'll tell you all my ideas about Looking-glass House."

Alice Several years ago, experienced Informer Gareth Rees used the idea of writing an adventure based upon Lewis Carroll's Through the Looking Glass to produce an excellent Inform tutorial; Doug Atkinson then extended the game, providing a beginner's viewpoint. As a practiced programmer but casual Informer I offer more words and less substance, discussing the process of developing the game as a whole (planning, testing, debugging, modifying code). You may download a zip file containing this entire directory if you wish.

To get the most from this tutorial you will need to have read Gareth Rees' . In some sections I talk about general principles, then use Alice as an example; the "Alice-Head" (visible at the beginning of this introduction) shows where I get down to specifics. There are also a few "diversions", marked with a triangle in homage to Graham Nelson's Fourth Edition Inform Designer's Manual (DM hereafter):

Diversion I have finally updated this page after a number of years, prompted by an email from Thomas Garner. I did so, however, in rather a hurry, and as a result it could do with serious editing, especially prolix §4. Please email me with any comments, questions, suggestions, or requests, as a show of interest is likely to promote further updates!

-- John, Chew Magna, October 2003


2. Doing It My Way: to reformat (or not)

"It seems very pretty," she said when she had finished it, "but it's rather hard to understand!" (You see she didn't like to confess, even to herself, that she couldn't make it out at all.)

Every author has their own preferences for code layout, file use, text style, and so on; shared projects such as this one cause difficulties when the people working on it have differing opinions. If working as a team, the co-authors need to agree on a compromise solution; when writing serially each must work with what they are given, but for the duration of their "tenure" have complete control.

Alice Doug Atkinson's looking.inf, written for Inform 5.5, is 758 lines long. It is short enough that I could reformat and reorganise it completely if I wished (1,000 lines is about my limit) so I have a free hand.

The result of this is alice5.inf, which functions just the same as before but is easier for me to read.


3. How Not To Go Backwards: using transcripts

"Now here, you see, it takes all the running you can do, to keep in the same place. If you want to get somewhere else, you must run at least twice as fast as that!"

It is all too easy to make an innocent-seeming code change in order to get one puzzle to work (or just to make the code cleaner), only to find out much later that it has some entirely unintended consequences elsewhere. By the time you discover this you will frequently have forgotten what you changed.

Avoiding this is a very important part of any programming project, and whole books have been written about "regression testing" -- the art of making sure that adding new features does not break old ones. The process can be extremely tedious if the developer has to do it by hand -- nobody wants to go back over old ground when there are new vistas waiting -- and it is often quietly forgotten, leading to long periods of even more painful debugging later.

Happily, IF authors have an ideal tool for automating this: the transcript. With only a little self-discipline you can double-check your work after each change, no matter how small. [This idea is suggested in the DM, §7, but in small type -- in my opinion it deserves a little more emphasis.]

3.1 Recording scripts

When initially testing your code, type the following three commands (assuming you're using the standard library) before doing anything else:

    RECORDING ON
    RANDOM
    SCRIPT ON

RECORDING ON starts capturing your commands to a file, RANDOM makes sure that any random events produce consistent results, and SCRIPT ON starts capturing the output of the program. Perform the actions you wish, then end with

    SCRIPT OFF
    RECORDING OFF

You have now generated two important files, the command log and the output log (what they are called will depend on your interpreter). These are your reference files.

Alice For Alice, I did this with the version compiled by Doug Atkinson using Inform 5.5, producing a command file and transcript. I read the source first to get an idea of what results were intended, then tried to exercise as much of the code as possible without going overboard.

3.2 Testing changes

When you have compiled new code, you can run the same command sequence using

    replay

-- which will generate a new output log. You can then use a file comparison utility (such as 'diff') to see what has changed. If everything is as you expect, all well and good (and the new transcript becomes your "reference copy"); otherwise you may wish to investigate further.

Alice I recompiled Doug Atkinson's code (now renamed Alice4.inf) using Inform 6 and ran the previously-created command file, producing another transcript. Comparing the two is interesting:

5	 <! Release 1 / Serial number 951029 / Inform v1502 Library 5/12 D
6	 <! Standard interpreter 1.0
7	 <! Interpreter 6 Version F / Library serial number 951024
	 !> Release 1 / Serial number 010904 / Inform v6.21 Library 6/10 SX
	 !> Standard interpreter 1.0 (6F) / Library serial number 991113

The banners differ. This is expected, although under normal development only the first line would have changed (and that only on the first compilation of the day).

63	 <! You wouldn't want to catch a chill, would you?  Better leave the window shut.
	 !> You wouldn't want to catch a chill, would you? Better leave the window shut.

I would almost certainly have overlooked this (and the several other instances) if checking by hand. I have a command set up in my editor to run the Inform compiler; this loads "default.icl", a set of compile options I always use. One of these instructs Inform to contract double spaces after full stops, which was presumably not used in the original build of "looking.z5".

Examining the code I find that there are inconsistencies in the use of single or double spaces after full stops, so it looks like a good idea to keep this option (although I will also consider tidying up the source file).

195	    >give her to black
196	 <! I'm not sure what "her" refers to.
	 !> (the red queen to the black kitten)
197	 <- 
198	 <- >give queen to black
199	    You toss the red queen onto the floor and the black kitten scampers after it.
200	    
201	    The white kitten jumps into the ball of worsted and gets tangled up in a mess of
202	    threads.
(197)	 -> 
(198)	 -> >give queen to black
	 !> (first taking the red queen)
	 !> You toss the red queen onto the floor and the black kitten scampers after it.

This is interesting. I thought that the red queen not being recognised as "her" was a bug in the game, but it turns out to be a problem with Inform 5.5. This is good, because it's one less thing to fix. Not so good is the fact that this particular bug messes up the random messages from now on; I'll ignore the resulting differences.

226	    >put it in chair
227	 <! You need to be holding it before you can put it into something else.
228	 <- 
229	 <- The white kitten purrs contentedly to itself.
	 !> You need to be holding the arm-chair before you can put it into something else.

This is just a case of the Inform 6 message being more informative. Checking the whole transcript shows that I had just been talking about the white kitten; the problem is to do with pronouns, and is already on a list of bugs presented toward the end of the first tutorial.

Considering I didn't change any code there were a lot of differences to investigate. Nothing has changed for the worse, however, so I'll make the Inform 6 transcript my new master and continue.

3.3 Extending scripts

Adding new tests to the end of a script is easy. Replay the original, then type RECORDING ON and make sure you write the command log to a different file. Perform the actions you wish to add, then end with RECORDING OFF.

You now have two command scripts. Open them in a text editor and copy the contents of the new one, (excluding the final RECORDING OFF line) into the first, just before the SCRIPT OFF line. This is actually quicker to do than to explain! The last step is to replay it; the transcript produced should be the same as before except for the extra material at the end.

3.4 Modifying scripts

Changing scripts can be harder, but has to be done sometimes (for instance, when you change the actions needed to complete a pre-existing puzzle). There are a few ways to tackle this:


4. Taking Stock: small additions to the part 2 tutorial

"While you're refreshing yourself," said the queen, "I'll just take the measurements." And she took a ribbon out of her pocket, marked in inches, and began measuring the ground, and sticking little pegs in here and there.

Alice Doug's tutorial was hard to find before I put up an html version here, and I mistakenly believed he had not provided one. In some ways this was useful, since it meant I paid more attention to the code while reformatting it (and working out what to put into my original transcript).

4.1 Writing for variable screen widths

One thing I noticed was that two places had hard-coded line breaks: the triple row of asterisks when you pass through the window (reminiscent of the original book) and the centred text for the poem "Jabberwocky". Each supposes a screen width of at least 72 characters, and would look best with 80.

One of the advantages of a virtual machine with a text-based format is that programs written with Inform can be run on a wide variety of computers. Unfortunately this also means that certain features (such as colour) may or may not be present. Screen width varies a lot; it is usually possible to find out what it is, which we need in order to centre text properly, but the technique involves knowing which screen model will be used by the virtual machine when it runs the program. This is advanced stuff; §42 of the DM has the details, but the following should work for all Z-machine versions except version 6:

    [ ScreenWidth;
        #IFV3;
            return 80;      ! Can't tell in early versions, so guess
        #IFNOT;
            return 0->$21;  ! Can look up the actual value
        #ENDIF;
    ];

Diversion It may seem inefficient to use a routine for a single lookup, but clarity is usually a bigger problem for programmers than efficiency. If the game runs too slowly then some code will have to be optimised, but this should only be done when necessary and the above routine is unlikely to be the one creating a bottleneck.

We also need a way to find the length of the string being centred. This can only be done by writing it to an array, like so:

    Array TemporaryStringArray->102;
    [ StringLength str;
        return str.print_to_array(TemporaryStringArray);
    ];

We can now write a routine to centre text. There is one important "gotcha": the screen width only applies to a fixed-pitch (or non-proportional) font, where all the characters are the same width. We can guarantee that this is the case using the 'font' statement:

    [ PrintCentredLine str leading_spaces;
        font off;
        leading_spaces = (ScreenWidth() - StringLength(str)) / 2;
        if ( 0 < leading_spaces )
            spaces(leading_spaces);
        print (string) str;
        new_line;
        font on;
    ];

Diversion The test to determine whether the screen width is greater than the string length demonstrates another programming rule: handle "edge cases" simply. What this means is that situations which are possible but unlikely shouldn't cause a crash (I don't know what would happen if I allowed 'spaces' to be called with a negative argument), but neither should they take up too much effort (so I'm not going to attempt to introduce new line breaks programmatically).

We can also make the technique nicer to use for multiline text:

    [ PrintCentredText s1 s2 s3 s4 s5 s6 s7;
        if ( 0 == s1 ) return;
        PrintCentredLine(s1);
        if ( 0 == s2 ) return;
        PrintCentredLine(s2);
        if ( 0 == s3 ) return;
        PrintCentredLine(s3);
        if ( 0 == s4 ) return;
        PrintCentredLine(s4);
        if ( 0 == s5 ) return;
        PrintCentredLine(s5);
        if ( 0 == s6 ) return;
        PrintCentredLine(s6);
        if ( 0 == s7 ) return;
        PrintCentredLine(s7);
    ];

We can now rework the 'Read' case of the book's 'before' routine ('Reflect' is similar):

         Read: print "It's written in some language you don't know. The first 
                      verse looks like this:^^";
               PrintCentredText(".YKCOWREBBAJ",
                                "",
                                "sevot yhtils eht dna ,gillirb sawT'",
                                ";ebaw eht ni elbmig dna eryg diD",
                                ",sevogorob eht erew ysmim llA",
                                ".ebargtuo shtar emom eth dnA");
               rtrue;

We could just use this centring to improve the scene-changing pattern as well, but since the number and spacing of the asterisks has only aesthetic importance we can try to be a little cleverer. The following routines attempt to print something suitable in all cases:

    [ PrintSceneChangeLine count gap width;
        width = gap*(count-1)+count;
        font off;
        spaces((ScreenWidth()-width)/2);
        print "*";
        for (i=1: i= 60 )
            count = ScreenWidth() / 12;
        else if ( ScreenWidth() >= 32 )
            count = ScreenWidth() / 8;
        else if ( ScreenWidth() >= 12 )
            count = ScreenWidth() / 4;
        else if ( ScreenWidth() > 2 )
            count = 2;
        else
            rfalse; ! No room for anything
        gap = ScreenWidth() / count;
        if ( gap % 2 == 0 )
            --gap;
        new_line;
        PrintSceneChangeLine(count, gap);
        PrintSceneChangeLine(count-1, gap);
        PrintSceneChangeLine(count, gap);
    ];

Diversion One minor question that comes up for programmers concerns when to use local variables to store the result of a routine call -- if you do so, the code is more efficient but harder to reorganise ("refactor"). In this case, ScreenWidth() is simple enough that efficiency doesn't matter, so I have opted to make the call repeatedly. This is a special case of preferring clarity over efficiency.

That finally completes the changes arising from one minor observation!

4.2 Listening to feedback

An Interactive Fiction author (or indeed any programmer) cannot create a top-quality product without help. While every project needs someone with vision and drive, it also needs playtesters to keep it on track, and it is only polite to listen to their feedback. Bugs should be fixed, confusions resolved, and opinions considered -- although it is also important for authors to have the final say in any matters of opinion (if your fiendishly hard guess-the-verb puzzle is really so important to you, go ahead and ignore the critics).

The problems pointed out to Gareth Rees during betatesting of part 1 deserve consideration, but he also earmarked them as "exercises for the reader". Out of respect for Gareth I shall leave most of these alone, but it feels wrong to do nothing, so I shall restrict myself to fixing the verb issues from report 10. The process of adding and extending verbs is already adequately described in part 1; the only new feature here is the 'first' keyword, needed so that the command GET DOWN works properly, rather than reporting that you can't take the floor:

    Extend 'get' first
        * 'down' -> Exit;

Similar reasoning applies to CLIMB DOWN and JUMP DOWN. I made one other change while doing this, which was to replace the use of double-quotes in Verb and Extend declarations with single-quotes, the better to emphasise that these are dictionary words rather than strings.

Diversion At this point, I saved my updated version as alice6.inf. Replaying the command file shows the only things to have changed are the width-based items described above. This demonstrates both the limitations of the technique, since I never thought to try GET DOWN from the mantelpiece before, and the value of playtesters!

4.3 Reuse: using a library for hints

When first playing the game I did not guess that I needed to curtsey to the queen, and eventually had to resort to reading the source code (having at that time no access to the part 2 tutorial). I believe that this puzzle is probably too hard, but will go along with Doug's suggestion that we leave such decisions to the playtesters. Even so, it occurred to me that the tutorial so far lacks a hint system -- adding one offers an opportunity to introduce some new techniques.

While it is certainly possible to code your own hint system, this is such a standard feature of IF that other people have produced add-on libraries to avoid re-inventing the wheel. The first place to look for such things is in the IF archive, at http://ifarchive.org/indexes/if-archiveXinfocomXcompilersXinform6XlibraryXcontributions.html (or ftp://ftp.ifarchive.org/if-archive/infocom/compilers/inform6/library/contributions/ if you prefer FTP -- the index file describes the files). The site can be slow, so check out the mirrors on the main page.

Sure enough, there is L. Ross Raszewski's "Hints.h". As with any other add-on library, the first thing to do is to download it and put it somewhere where the Inform compiler can find it. For this tutorial I have simply put the files in the same place as "Alice#.inf", but you can set the compiler's include_path to look in a common location.

Next, we need to read the instructions (usually included in a comment at the top of the file). This tells us that we need to download three more files -- "DoMenu.h", "AltMenu.h", and "Center.h". Requiring multiple files is common with libraries, but in this case there is a problem: "Center.h" does not exist. Reading the other instructions shows that the author probably meant "Utility.h", which I download, making a mental note to contact the author to report the error.

Diversion Comments not matching the code they accompany is a common situation (which is one reason for keeping comments to a minimum and making the code as clear as possible instead). It is easy to see how this happens: a header containing a single function has others added, then its name is changed to more clearly reflect its use, but the comment referring to it is forgotten. Since library-writers need to provide documentation, they cannot avoid including the comment, and in this case playtesters are unlikely to spot it (since they will be provided with all the necessary files to test).

The instructions tell me what I need to do for the library to work, so I modify the place where I include the standard library files:

    Replace DoMenu;
    Replace LowKey_Menu;

    Include "parser";

    Include "Utility";
    Include "DoMenu";
    Include "AltMenu";
    Include "Hints";

    Include "verblib";
    Include "grammar";
    ...

This produces a number of errors and a warning; reading AltMenu's documentation more carefully tells me that I need to define a constant ALTMENU_PROP_STUBS at the beginning unless I am using all its features, and doing so eliminates the errors. The warning concerns a constant WORDSIZE defined in "Utility.h" but not used. Looking at the code, this is needed if compiling for Glulx (which I am not). I don't like having spurious warnings, since they make it harder to spot the real problems, but I don't wish to modify the library file. Instead, I'll add some harmless dummy code to make use of it for now, and ask the author later:

    Replace DoMenu;
    Replace LowKey_Menu;
    Constant ALTMENU_PROP_STUBS;

    Include "parser";

    Include "Utility";
    #ifdef WORDSIZE;
    Include "DoMenu";
    Include "AltMenu";
    #endif;
    ...

Finally, about half an hour after I started, I add a small dummy hint menu and the system is in place. Things didn't go smoothly, but it was still a lot less work than writing my own menu code.

Diversion Object-oriented languages such as Inform make reuse easier, but producing a library is still not trivial. It is rarely worth the extra effort required to design code for general use initially: a better technique is to make the code as simple, clear, and easy to change as possible, then see if it's ever needed again. A good rule of thumb is provided by the "three strikes" rule:
  One use: Write it as simply as possible.
  Two uses: Consider whether generalising the original code would really be more work than writing something specifically for the new case.
  Three uses: You'll probably need it again, so it's time to bite the bullet and seriously consider generalising the code, even if this is more work.

4.4 Style: the hints and messages

At this point, I paused to consider what I wanted to put in the help system, and how to organise it. I took a look at some other games, and it seemed to me that the standard style jars with the atmosphere of the tutorial. I therefore decided to treat the hints as an opportunity to practice my Carrollian English, presenting them as Alice thinking out loud. An example:

    HintTopic -> -> "What shall we do today, kitty?";
        Hint -> -> -> "It's so cold outside--do you hear the snow against the window-panes, kitty?.";
        Hint -> -> -> "I do so wish I could go somewhere warmer.";
        Hint -> -> -> "I'm quite certain it's still summer in Looking-glass house.";
        Hint -> -> -> "Oh, kitty, how nice it would be if we could only get through into Looking-glass house!";

Having done this, I decided it was necessary to make the game's style more consistent -- for instance, typing EXAMINE KNIG resulted in the response "You can't see any such thing", which should at the very least have an extra apostrophe. Inform allows simple customisation of such text using a LibraryMessages object defined between the inclusion of "Parser.h" and "Verblib.h"; this technique is described in the DM, §25. Unfortunately, there are a lot of messages to change -- searching through "English.h" reveals 26 instances of "can't" alone. An alternative would be to replace the "English.h" file with a customised "Carroll.h". This would be easier for me, but requires the person compiling the tutorial to specify the language file. Since I am doing this for fun, I decide to create the new language file; but I also create an ICL file to make compilation easier.

4.5 Refactoring: when to change code that already works

As expected given the error in its documentation, the hints library provides me with one other, unanticipated feature: a routine for centring text called, appropriately enough, Center. I remove my PrintCentredLine and StringLength routines, and modify PrintCentredText to use Center (including adding new_lines, since Center doesn't do so).

Why remove code I've already written, checked, and gone to the trouble of describing in this tutorial? Because duplicate code (and, in particular, code which does almost but not quite the same job) can lead to inconsistency and confusion, making the game harder to modify in the future. Cleaning this up (sometimes called "refactoring") helps me to keep on top of the code. Refactoring is more than just a posh name for editing, though, with a carefully-defined process to follow:

  1. If there isn't a script (or other test) to show how the existing code works, write one. In this case, the existing script already tests the centring code.
  2. Run the test on the old code.
  3. Make the change.
  4. Run the test on the revised code. If it doesn't work as expected, correct any problems and try again.

This process ensures that you make the change correctly, and the closer you can get to automating it the better.

Diversion One of the disadvantages of using library code is that the author's style may differ from your own -- in this case, through the use of American spelling ("Center" rather than "Centre"). Although this does create some confusion the benefits usually outweigh the problems. On the gripping hand, you should try to be consistent within your own code!

The result of all these changes is alice7.inf, the last version which will be produced for this tutorial. I also provide the language file Carroll.h and alice7.icl, which sets the language (and contracts double spaces after sentences). Alternatively, download a zip file containing this entire directory.


5. Designing The Midgame: a crossword at war with a chessboard

"A pawn goes two squares on its first move, you know. So you'll go very quickly through the Third Square--by railway, I should think--and you'll find yourself in the Fourth Square in no time. Well, that square belongs to Tweedledum and Tweedledee--the Fifth is mostly water--the Sixth belongs to Humpty Dumpty--But you make no remark?"

So much for coding (at least for the present) -- it's time to take a step back and examine the structure of the game as a whole. This section draws heavily upon chapter VIII of the DM.

5.1 Structure and Narrative

To summarise: most games have a prologue (which sets the scene), a midgame (featuring most of the action and puzzles), and an endgame (which draws everything together in a satisfying conclusion). Midgames in particular can also be categorised as "wide" (allowing players to see much of the landscape and solve puzzles in almost any order) or "narrow" (walking the player through, one puzzle at a time). Literary adaptations can be problematic because the narrative structure of a book does not generally translate well into a game -- few successful adaptations stick closely to the plot. In addition, the scope of a typical IF game more closely matches a short story than a novel.

Alice The terms "midgame" and "endgame" are reminiscent of (and quite possibly derived from) chess, which of course provides the thematic structure of the book. So far, the tutorial has a prologue (or "opening", in chess terms) developed in part 1, and the start of a midgame. We can map the endgame quite nicely to the final chapters of the book, either from the point where Alice becomes queen and the White King is placed in check, or from the moment when Alice enters the hall for her party (which we use will depend on how the game develops).

So, what are we going to do with the rest of the midgame? The book maps to a game of chess (or chess problem), with Alice sticking to valid moves as a pawn who is promoted to queen upon reaching the eighth row. If we allow Alice to roam free over large parts of the map we destroy this relationship, but if we do not the game will be very narrow and linear…unless we can provide enough freedom within each square.

5.2 A Serial Game

Alice This idea of keeping the overall structure linear while providing localised freedom fits well with the unusual nature of the Alice project (a series of tutorials with serial authors). An analysis of the book suggests eight sections (prologue, a midgame of six parts, and the endgame):

Prologue
Before Alice enters the mirror. Covered in part 1.
Q2: Becoming the White Queen's Pawn
Looking-glass house (with the small chess-pieces), the garden of live flowers, the hill, and the Red Queen. Largely covered in part 2, although we could open it up if necessary.
Q3: The Train Journey
The railway carriage and its inhabitants. Little more than a transition from Q2 to Q4.
Q4: The Wood
Looking-glass insects, the wood with no names, the Fawn, Tweedledum and Tweedledee, the dreaming Red King, the White Queen in her shawl living backwards. Plenty of material here.
Q5: Wool and Water
Things out of reach, the Sheep's shop, the river. An obvious puzzle or two, but not much to work with if we're trying to allow freedom.
Q6: Humpty Dumpty's Forest
Humpty Dumpty, the White King with his soldiers and horses, the Mad Hatter and the March Hare, the Lion and the Unicorn, the plum-cake and the drums. Like Q4 there is plenty of material, but here it is even more heavily character-based, so tough to implement!
Q7: It's My Own Invention
The Red and White Knights' battle and the latter's inventions. This looks very tricky to me.
Q8: Endgame (Queen Alice)
The three queens and the feast. As mentioned above, a good place to tie things up.

A six-section midgame is certainly close enough to linear that it raises some alarm bells for me; I gave up on Infocom's The Hitchhiker's Guide to the Galaxy (despite the quality of Douglas Adams' writing) because of the way it presented a single puzzle at a time. With careful planning, however, I believe this danger can be minimised. My initial thinking would be to make Q2, Q4, and Q6 as broad as possible, while de-emphasising Q3, Q5, and Q7, producing something more like a three-section midgame with lock-gate puzzles in between.

One big advantage of this layout is that the section-by-section outline makes it easy for future authors to choose what to work on, and to have some idea of scope in advance. Want something small and puzzle-based? Q5 fits the bill. Want to provide a guide to advanced NPC design? Tackle Q6. Intent on proving how much more creative you are than me? Q7 gives you that opportunity. More interested in expanding existing work? Open up Q2. Since the midgame is only loosely coupled you don't have to wait for earlier parts to be completed, just dive in with whichever you want (although the endgame should probably be left until later). I would recommend that authors working on the larger sections don't try to explain everything in their tutorials, just the novel features.

Since I don't wish to provide a straitjacket for future authors, I will stop here. With a plan such as this in place, it should be possible to develop parts of the game while still keeping an eye on how the work is progressing as a whole; the plan should certainly be revisited from time to time to make sure it is still viable and to incorporate experience gained while writing tutorials 4+. Maybe two authors could get together and offer some thoughts on the benefits of brainstorming (which I found indispensible when writing commercial games)? Or maybe you just want to get back to the coding and puzzle design? The future of the Alice project is in your hands.


6. Afterword

"Now, Kitty, let's consider who it was that dreamed it all."

Lewis Carroll taught Mathematics at Christchurch college, Oxford, for more than a quarter-century; Graham Nelson now teaches it at another Oxford college, St. Anne's, where I studied the subject at the start of my twenty-year stay in the town. All three of us share (along with Martin Gardner, another mathematician) a love of words, games, and word-games. Beyond this, I hesitate to compare myself to such men, but by writing this tutorial I have, I suppose, placed myself in their orbit.

Why write this tutorial? I was spurred primarily by a desire to give something back to the IF community which has given me a so much pleasure over the years, but I also wanted an excuse to play around with Inform even though I have more important things to do. My goals during writing were somewhat different: to have fun, to learn, to teach, and to keep the Alice game alive. I would be delighted if someone were to take up the baton and provide a Part Four -- I promise I won't be cross if all my advice is ignored.

Go on. You know you want to.

*       *       *       *       *
*       *       *       *
*       *       *       *       *

Finally, and without further ado, some of the books I referred to (or thought about) while preparing this tutorial:

Lewis Carroll and Martin Gardner, The Annotated Alice
As a fan of both author and annotator I treated myself to the Definitive Edition (ISBN 0-713-99417-7) as a new millennium present. I find it easier to read a book than a computer screen; sometimes it's handy to have an online copy of the text as well to help when searching for a phrase, but I personally couldn't manage without a hardcopy of some sort, and this version does the job admirably. In addition, Mr. Gardner's notes promote a deeper understanding of the source material (and started the train of thought which led me to believe I had something to say in this tutorial).
Lewis Carroll and Martin Gardner, The Annotated Snark
Not directly relevant, but certainly Enlightening. My copy has no ISBN, and was published before my birth; I do not know whether it is currently in print. Seek it with thimbles, and seek it with care!
Graham Nelson, The Inform Designer's Manual
The book to refer to on all matters Inform. One of my small delights is making it into the acknowledgements list for comments I made on an early draft of chapter 1 -- I'm in the index twice, since Graham also kindly refers to an article I wrote for XYZZYnews. Not that you wished to know that. If you can afford it, I recommend the printed version (ISBN 0-9713119-0-0).
Martin Fowler, Refactoring
Again, the best book on its chosen topic, with a chapter of typical code problems needing cleanup ("bad smells") and a larger catalogue of techniques to deal with them. ISBN 0201485672.
Ken Auer and Roy Miller, Extreme Programming Applied
XP is a much misunderstood process, a situation made worse by the choice of name and the evangelical approach of early advocates. This book (ISBN 0-201-61640-8) is my favourite for explaining everything in a down-to-earth manner. A lot of it is likely to be irrelevant to most IF projects (where hobby programmers work alone for their own satisfaction), but the general principles and some of the specifics (testing, refactoring, simple design, small releases, coding standards) are useful.

This page originally found at http://www.elvwood.org/InteractiveFiction/Alice/Alice3.html
Last updated: 11 April 2010

Notices & Disclaimers

Home
Home

Interactive Fiction
IF