Search Results for: inform

Customizing an interpreter for a Glulx game release

Another technical question from Twitter: the integration of Hadean Lands with its iOS app. How did I set up iOS UI features like the dynamic map and the recipe index?

(Warning: if you don't think C code is interesting, this post is not for you! Sorry.)

The iOS version of HL uses my standard iOS IF interface, extended. I've added two tabs to it. The map tab shows your current location, and you can tap to travel to any room you've visited before. The recipe tab shows an index of recipes and other information you've learned. These work just like the "GO TO..." and "RECALL..." commands, so they don't make the game easier to solve, but they're convenient shortcuts.

I'm not going to post the iOS UI code I used. If you know iOS programming, it's very basic -- textbook UITableView and UIImageView stuff. Instead, I'll talk about the general problem: transferring information between the Glulx VM and your native (C) interpreter.

I should put "general problem" in quotes. There are several Glulx interpreters, after all. But let's assume that you're building a native app for your Glulx game, incorporating the glulxe interpreter engine (in C), and you want to customize it with game-specific features. You've implemented the UI part; now you just need to extract game state information. Say, the player's location to show on the map.

There are a couple of approaches that would work. For example, we could define a completely general system for transmitting game information to an outside observer, and add that to the Glk spec. Sound like a good idea? Well, maybe, but it's both a hard problem and a vague problem -- what's "information"? We'd probably need some kind of structured interchange format (XML? JSON?). Then we'd have to encode and decode that. Plenty of headaches. No thanks, not right now.

Or we could define a new Glk output capability just for this game. No spec, just define a function ("glk_set_map_location") and have the game call it each turn. I thought about this, but I decided it would require modifying too many different modules. Glk function dispatching is kind of ugly.

Instead, I decided to write C code to peer directly into Glulx VM memory! It's stored as a simple byte array, after all. Reading the game state out is just a matter of understanding the memory layouts of objects, variables, and arrays.

Okay, that's not easy, but it's doable in a small amount of code. To make this work:

  • You'll need to know some Inform 6. Sorry. Inform 7 is a wonderful high-level programming system, but it compiles into low-level objects, variables, and arrays.

  • You'll need to extract information from the gameinfo.dbg file that's built along with your game. (This lives in the Build subdirectory of your Game.inform project.) This is where you find the memory addresses of those objects, variables, and arrays.

  • You'll need some boilerplate C code to examine objects, variables, and arrays. I'll attach it to this post; you can copy-and-paste.

How do you use this? Say you're interested in the player's location. (For the map, right?) You know from the Standard Rules that

The location variable translates into I6 as "real_location".

Browse through gameinfo.dbg with a text editor (or an XML editor) and you'll see a stanza that starts:

    <address> 249528</address>
    [...more info...]

This tells you the absolute memory address of the I6 variable real_location. Call gameparse_get_global() with that address -- the function is shown below -- and you'll get the player's location, expressed as the memory address of the room object.

How do you know what room that is? Somewhere in gameinfo.dbg is another stanza:

    <value>     273861</value>
    [...more info...]

This indicates that an object named "Kitchen" has memory address 273861. (It happens to be the 88th item that the compiler defined.)

Obviously this is not very convenient. All of these addresses are liable to change every time you compile your Inform game. So you wind up writing a script to parse your gameinfo.dbg XML, locate the real_location address, locate an object called I#_kitchen (for some integer, might not be 88), and so on. I like to write them out to a C header file looking like this:

#define GLOBAL_REAL_LOCATION (249528)
#define OBJ_KITCHEN (273861)

Then you can include this header in your game project and write code like

if (gameparse_get_global(GLOBAL_REAL_LOCATION) == OBJ_KITCHEN) {...}

But you'll have to write this XML-parsing script yourself, I'm afraid. I don't have one for you. You could start with

Note that you can't do this for I7 global variables (declarations like "Foo is a thing that varies.") Those get tucked into an I6 array and the gameinfo.dbg file has no information about them. If you need to observe a global variable, you'll have to declare it in I6 with an I7 translation. See I7 manual 27.22.

The gameparse_obj_child, gameparse_obj_sibling, gameparse_obj_parent functions let you traverse the I6 object tree. (Although this doesn't give you I7 relations like component-ness.) I used this for HL's recipe index. The game's internal knowledge objects are moved into special containers, for easy scopability, so I can trawl those containers to set up the recipe tab.

Looking at object attribute and properties is easy. The functions gameparse_obj_attribute and gameparse_obj_property do that. Knowing what I6 attribute or property represents a given Inform property is harder. The best plan is to to look at the generated I6 code (the Build/auto.inf in your Inform project) and see what's going on under the covers. For examine, the boolean property open/closed is implemented by the following I6 lines:

! meaning of "open"
if (t_0) return (GetEitherOrProperty(t_0, open));

This means you're looking for an I6 attribute in the gameinfo.dbg file:


Or say you've written the I7 line:

A thing has a number called the weight.

You find that this generates I6 code like:

! [1: let n be the weight of the noun]
tmp_0 = GProperty(OBJECT_TY, noun, p15_weight);

And so you're looking for an XML stanza like:


At this point you start to wonder if the general information API wouldn't be better after all. Maybe it is. Why didn't I go that way? (I realize this is more of a peek into Zarfbrain than you probably care about.) I find that this stuff is the easy part. Drawing a map was hard. Extracting recipes from game output and importing them into an iOS app was work, if not really hard. Extracting state from VM memory was a solved problem; I just had to do it for a lot of objects.

Also, it's fast. I only inspect game state when flipping to the relevant tab, and the inspection code is C. If I'd rigged the game to output state to an API, it would have to be every turn, which would slow down normal gameplay. Or I guess I could have added a secret input event for tab-flipping, which would mean blocking the UI on game code, also slow... Anyhow.

Some other concerns:

  • In my iOS interpreter, the VM runs in a background thread. The UI runs in the main thread, as is usual for iOS apps. How did I synchronize the VM inspection? I didn't! Totally whiffed the thread-safety issue. It's generally not a problem; the player will flip tabs while the VM is blocked awaiting input. But if you have some fancy timed-input code that moves the player around, and the player flips tabs at just the moment when the timer fires, you could get a bum value out of real_location.

  • What about Z-code games? You can take the same approach, but you need different state-inspection code, because the Z-machine's memory layout is different. (For a start, it's all 16-bit words, not 32-bit.) I did some of this for the iOS releases of Dreamhold, Shade, and Heliopause. But I didn't wrap up the C code into nice functions like these. So -- exercise for the reader, sorry.

  • Can you do this in Quixe? (A Javascript interpreter instead of a C interpreter.) Yes, and the plan is just about identical. Quixe maintains a private memmap array, which is a Javascript array of byte values, so you just have to translate the code below into Javascript and you'll get the same results. The only trick is that memmap is in a private scope. You could add the functions below to the Quixe global object, or rely on ReadWord/ReadByte, or just add a one-liner to export memmap:

    get_memmap: function() { return memmap; },

Finally, we have the question of input. When the player taps a room on the HL map, the game must accept it as input.

Again, there are a few ways to handle this. I decided to use a custom Glk event. The Glk spec says that negative event ids (0x80000000 to 0xFFFFFFFF) are reserved for implementation-specific events, and that's what this is. The iOSGlk library has a forceCustomEvent method. The map UI invokes this, passing a negative constant as the event type and the room object address as an extra argument. Conveniently we've already extracted the addresses of all the rooms from gameinfo.dbg.

(Other Glk libraries might not have this sort of API, but it will be easy to add. All events funnel into the Glk library in the same way.)

The only remaining chore is for the game to react to this custom event. Unfortunately, Inform's core parser loop is built to accept only text. This will have to be improved someday! (Not just for custom map hacks, but for hyperlink input, mouse input, and so on.)

But, again, I took the cheap way out. I used the HandleGlkEvent hook to translate the custom event into the input line "MAP-VERB 273861", where the number is the decimal room address.

This is not ideal because a player could type that line by hand! Well, whatever. Players can do what they want. Mind you, I sanity-check the argument very carefully to make sure an invalid address can't crash the game or leave the player stuck in a teakettle.

The relevant I7 code (and I6 inclusions) appear at the end of this post. I just noticed, though: it won't compile with the current Inform 6 compiler (6.33)! This is because I rely on the constants #lowest_object_number, #highest_object_number, #highest_class_number. These were missing from the Glulx compiler until, well, until I was writing this map code and needed them. You can build the latest I6 compiler from source and shove that into your I7 distribution. Then this'll work.

So the conclusion is, this is all a big pain in the butt, isn't it. Yep.

(No comments out of you, Dave. It really was the least-effort solution for my particular problem.)

C code for examining Glulx VM state:

#include "glulxe.h"

/* The glulxe.h header defines the glui32 type and the Mem4() macro.
    Also the memmap global variable (array of bytes). */
/* These functions do a little bit of safety-checking, but you really
    should be careful to only call them with valid object addresses. */
/* Feel free to add warnings or errors to the "error" cases. I like to
    throw exceptions, myself. */
/* All of this code assumes that NUM_ATTR_BYTES is 7, the default
    value for Glulx games. If you increase NUM_ATTR_BYTES, you'll
    have to adjust the object structure offsets. */

int gameparse_mem_active(void)
    return (memmap != NULL);

/* Fetch a global variable. */
glui32 gameparse_get_global(glui32 addr)
    if (!memmap)
        return 0; // error: called get_global with no memory map
    return Mem4(addr);

/* Get the object which contains a given object, or 0 if it
    is off-stage. (The I6 parent() function.) */
glui32 gameparse_obj_parent(glui32 obj)
    if (!memmap)
        return 0; // error: called obj_parent with no memory map
    if (memmap[obj] != 0x70)
        return 0; // error: called obj_parent on a non-object
    return Mem4(obj+5*4);

/* Get the first object contained by a given object, or 0 if it
    has no contents. (The I6 child() function.) */
glui32 gameparse_obj_child(glui32 obj)
    if (!memmap)
        return 0; // error: called obj_child with no memory map
    if (memmap[obj] != 0x70)
        return 0; // error: called obj_child on a non-object
    return Mem4(obj+7*4);

/* Get the next object contained after a given object, or 0 if there
    are no more. (The I6 sibling() function.) */
glui32 gameparse_obj_sibling(glui32 obj)
    if (!memmap)
        return 0; // error: called obj_sibling with no memory map
    if (memmap[obj] != 0x70)
        return 0; // error: called obj_sibling on a non-object
    return Mem4(obj+6*4);

/* Look up an attribute flag on an object. */
int gameparse_obj_attribute(glui32 obj, int attr)
    if (!memmap)
        return 0; // error: called obj_attribute with no memory map
    if (memmap[obj] != 0x70)
        return 0; // error: called obj_attribute on a non-object

    unsigned char byte = memmap[obj+1+(attr>>3)];
    if (byte & (1 << (attr & 7)))
        return 1;
        return 0;

/* Look up a property value on an object. */
/* Returns the first word of the property, if multi-word. (In most I7 games,
    the only multi-word property is "name". So you can't use this function
    to scan through the name list of an object.)
    If the property is not provided for this object, returns 0. */
glui32 gameparse_obj_property(glui32 obj, int prop)
    if (!memmap)
        return 0; // error: called obj_property with no memory map
    if (memmap[obj] != 0x70)
        return 0; // error: called obj_property on a non-object

    glui32 proptab = Mem4(obj+16);
    glui32 propcount = Mem4(proptab+0);
    for (int ix=0; ix<propcount; ix++) {
        glui32 propent = proptab+4+ix*10;
        int pid = Mem2(propent+0);
        if (pid == prop) {
            glui32 paddr = Mem4(propent+4);
            return Mem4(paddr);

    /* Property not provided. */
    return 0;

Inform 7 code for accepting custom input events. (This assumes a "select one room on a map" action, but it can be adapted to other uses.)

Include (-
[ HandleGlkEvent ev ischar args   val;
    if (ischar == 0 && ev-->0 == CUSTOM_EVENT_ID) {
        val = ev-->2;  ! the object address of the tapped room
        glk_cancel_line_event(gg_mainwin, gg_event);
        ! Write a synthetic "MAP-VERB ###" command into the buffer.
        VM_PrintToBuffer(buffer, INPUT_BUFFER_LEN-WORDSIZE, PrintVisitNum, val);
        return 2;
    return 0;
[ PrintVisitNum val;
    print "MAP-VERB ", val;
-) before "Stubs" in "Glulx.i6t".

To decide what object is paranoid-object-check (N - number): (- ParanoidObjCheck({N}) -).
Include (-
! Return val if val is a valid object, otherwise 0.
! This code requires the bleeding-edge (6.34) Inform 6 compiler.
[ ParanoidObjCheck val;
    if (val < Class + ((#lowest_object_number + #highest_class_number) * GOBJ_TOTAL_LENGTH))
        return 0;
    if (val > Class + ((#highest_object_number) * GOBJ_TOTAL_LENGTH))
        return 0;
    if ((val - Class) % GOBJ_TOTAL_LENGTH ~= 0)
        return 0;
    if (val->0 ~= $70)
        return 0;
    return val;

Numeric-visiting is an action applying to one number.
Understand "map-verb [number]" as numeric-visiting.

Carry out numeric-visiting:
    let N be the number understood;
    let O be paranoid-object-check N;
    if O is nothing:
        instead say "That address ([N]) is not an object!";
    if O is not a room:
        instead say "That address ([N]) is not a room!";
    [Check locked doors and so on here...]
    now the player is in O;
    say "You move to [O]."
Tagged , , , , , | Leave a comment

Old Zarf code

In a recent blog post, I wrote: "Maybe we'll even make more of a swing towards releasing game source code."

That thought stuck with me. I asked myself why I haven't posted the source code for all my classic IF games.

Some, I have. I posted source for Hunter in Darkness, Shade, and Heliopause because I thought other game authors might be interested in the techniques. But the larger games (Dreamhold, So Far, Spider and Web) have never had public source releases.

Why not? I didn't put it in words, but roughly: players should experience the game, not the software. If there are secrets, they should be ferreted out by people playing the game, not people browsing the source.

Of course there are Z-code decompiling tools, so I can't truly enforce this. Nor would I want to go down the DRM/obfuscation road to stop people from prying. That would just be a huge waste of my time. But if people wanted to pry into the technology, I wanted them to have to expend some effort. That friction matched my feelings about the right way to play the game.

Only I don't feel that way any more. I can't remember why I ever gave a snort.

Oh, I suppose I do a little. When a game is freshly released and players attack it en masse, the idea still applies -- I want the group experience to be about the game. But a year later? It's meaningless. And some of these games are fifteen years old, or older.

So yeah. It's time to knock that habit over. Here are some source links:

The I5/I6 games are tar.gz files, because for each I had to pack several source files together with the hacked library code that I used. The I7 games are directly readable as (syntax-colored) HTML.

All of these can be compiled with Inform 5, Inform 6, or Inform 7. The exception is Delightful Wallpaper, which was built with a 2006 version of I7 that's no longer available from the web site. I'd have to update the source to recompile it.

I have not used an open-source license. The games all say what Shade has always said: "This source code is provided for personal, educational use only." You can read it, and copy the programming techniques, but you can't make derivative games. (That is: my game text is copyrighted and I intend to keep hold of it.)

(Academic writing about my games is of course fine. That's fair use in the old-fashioned sense.)

(Fanfic -- riffing on the story or characters while using original text -- is another barrel of cephalopods. I figure I'm in the same position there as any other writer. You've always been able to read my story text, as part of the game, and my source release doesn't change that.)

Hadean Lands is an interesting question. I'm going to charge money for that one; it changes the equation. I guess I'll wait a year after release, and decide whether I feel like doing a source release then? Feels right.

(One of the HL Kickstarter rewards was the source code as a printed volume. I won't wait a year on that, obviously. But that was a limited reward, and will only be distributed on paper, not online; so I'm leaving it out of this discussion.)

Tagged , , , , , , , , | 4 Comments

Holiday gifts of Inform source

I shared the source of The Warbler’s Nest to GitHub last weekend, a project that took a couple of hours by one measure and nine months by another. I started getting the codebase ready for sharing last spring, shortly after giving an invited presentation about the game at MIT. I considered the event as good a capstone as any on the game’s active presence in my mind, and releasing the source struck me as appropriate epilogue. As it turned out, this preparation would end up perhaps the last personal project I picked up before a family crisis would occupy much of my attention until wintertime.[1] And when, things calmer, I happened across this MetaFilter thread asking about Inform source examples shortly after I received an email from a Warbler player pointing out an embarrassing typo in the story, I thought: Oh, right. And so GitHub.

Mere hours after announcing all this on Twitter and such, I would laugh out loud from the solid upstaging my little effort would receive next to a truly delightful surprise: Daniel Ravipinto announced a special 10-year-anniversary re-release of Slouching Towards Bedlam, an IFComp-winning masterpiece released by Star C. Foster and himself in 2003. Daniel recast the game into Inform 7 (which didn’t publicly exist ten years ago) as an exercise, and this in turn allowed him to easily publish a web page linking to both the downloadable game file and its source text. I sincerely recommend taking this opportunity to try the game if you haven’t already; I quite look forward to playing it through again, myself.

Casting around a bit, I find that Inform 7 source examples are not quite as scarce as I may have thought. Inform includes a facility for releasing nicely HTML-formatted source text alongside one’s game, and just because I somehow hadn’t noticed it before doesn’t mean nobody else did either. Two publicly available recipients of this treatment come to my mind immediately: Aaron Reed’s Sand-Dancer exhibits intentional beauty and readability at the source level, since it serves as the game slowly built between the covers of his Creating Interactive Fiction with Inform 7 (which we’ve written about before). On another extreme, Emily Short made available the source for Counterfeit Monkey, which proves as eye-wateringly vast as the game itself. I note that one of the headings on that index page bears the title “Volume 5 - The Repository of All Things Possible”, and it does not exactly exaggerate. (Naturally, while this source is also quite readable, you really should play the game before browsing through its laid-bare secrets.[2])

I cannot fail to point out that Zarf quietly posted the source to several of his games some time ago, as well, including both his more recent work and classics like Shade. (Search for the word source in-page after opening that link.)

Lastly, on the topic of GitHub, Dannii Willis created the Friends of Inform 7 group, which contains lots of language extensions from various authors, as well as the open-source repository of Victor Gijsbers’ utterly gonzo Kerkerkruip, a procedural, stats-heavy, permadeathy dungeon crawl in the roguelike tradition, implemented entirely as prose-driven IF.

I have no doubts that many other examples of shared full-game Inform source lurk in the grue-infested darkness. If you know of a non-trivial Inform-based work with source available, do feel free to link to it here with a comment.

Update: As Juhana notes in the comments, “games with source available are neatly tagged at IFDB”. Wow, that’s quite a few games, too. Well, this is why I write these things.

[1]: And yes, dear reader, that would explain why I’ve written so little on this blog this past year, though I’ve no complaint about once again leaving it over to Zarf’s project-EKG in my absence. I have reason to believe that 2014 will be different, but time will tell…

[2]: Earlier this year, I wrote implementation-focused reviews of Counterfeit Monkey and a few other XYZZY Award nominees.

Tagged , , , , | 4 Comments

An Inform 7 cheat sheet

Just noticed this Inform 7 Cheat Sheet designed by Mark-Oliver Reiser. It’s actually a few sheets long, but it covers an awful lot of ground. The front page presents a minimal primer on the language’s syntax and the standard library’s class tree, and from there it manages to compress most every major point of Writing with Inform (the IDE’s built-in documentation) down to four pages.

The effect unavoidably resembles a progammer’s complement to the world-famous IF players’ reference-on-a-postcard, and that is not a bad comparison to invite. If you’re planning on sweating over hot interactive fiction compiler this summer (and I can think of at least one reason why you might be), this guide seems well worth the price of five blank pages and a staple.

Tagged , , , | Leave a comment

More Inform yapping at BarCamp, perhaps

Andy and I plan on attending the sixth annual BarCamp Boston this weekend, April 9 and 10. BarCamp is a geek-centric “unconference” whose schedule of talks is constructed on the fly by attendees. In my experience, each hour-long slot tends to end up with someone talking about jQuery, someone talking about Ruby on Rails, and then someone talking about volcanoes, or food science, or something else they’re passionate about and which doesn’t resemble my day job in any way. So I go to these third talks, one after the other, and have a grand time.

This year, at friends’ encouragement, I plan on myself pitching a talk that I hope falls into that third category. Unsurprisingly, this’ll be my introduction-to-Inform talk, yet again. In the likely event I manage to make it happen, that’ll be three times in the last eight months I’ll have presented it, just weeks after I busted it out for the PAX crowd (with Zarf’s assistance, which he may reprise once again here). It’s starting to develop into what Merlin Mann calls a Shake-and-Bake talk, one that a practiced speaker can perform with increasingly minimal preparation. I can’t say I really expected to ever develop such a thing, and I wouldn’t have predicted Inform 7 to be my topic if I did. But, so it goes.

If you’re in my town this weekend and this sounds like your idea of a good time, feel free to register online — Boston BarCamp is free to attend (though they’d appreciate a $20 donation, which’ll also net you a natty T-shirt).

Posted in Boston | Tagged , , , , , | Leave a comment

Announcing: Inform Extensions Search

I am pleased to announce the Inform Extensions Search site, the product of this past Saturday’s procrastinatory toils. It’s exactly what it sounds like: a simple search engine for Inform 7 language extensions.

I created this tool because I miss not having something like the CPAN Search for Inform extensions, even though “only” 230-ish such extensions currently exist in public. In fact, you can see them all (or all the ones released under a Creative Commons license, at least) on a single page at

Up until now, the best way I knew to look for extensions involved visiting that page and using your browser’s Find command. You can also browse by category, but even then you’re limited to extensions’ titles and summaries, and I found myself wanting to search at a deeper level without manually clicking though everything.

My tool offers a solution via searching extensions’ documentation, as well as their more obvious metadata. In this way, for example, a search for guns brings up David Ratliff’s extension to handle weapons and fighting, and searching for water produces several extensions that variously produce and handle liquids, though none have the word “water” in their descriptions.

So that’s that. I hope that someone finds it useful, and welcome feedback and suggestions.

Tagged , , , , | 5 Comments

I read a book

Last Sunday I finally finished reading and working though Aaron Reed’s Creating Interactive Fiction with Inform 7, a book that Andy’s already written about here. I felt it worth noting my own thoughts, briefly, as someone who isn’t an Inform expert (unlike Andy, whose name appears in the language’s credit roll, for zog’s sake).

I came to this book having already written The Warbler’s Nest using a sort of Pidgin Inform, diving right in and learning the language piecemeal from the IDE’s built-in docs, as well as community resources like Ron Newcomb’s excellent Inform 7 for Programmers. This worked, mind you — I finished the game, more or less on time. I expect that many other recent IF authors have employed the very same strategy, to at least as much success.

Inevitably, though, I remained ignorant about many of Inform’s key features, and had an overall shaky grasp of how the thing worked. For me, Reed’s book spent no more time than necessary on “The Foreman's Office is a room” basics of object manipulation — that’s the easy stuff! — before digging into relationships and rulebooks, two core language concepts I had only a fuzzy notion about. (Yes, of course I wrote a lot of Instead of... rule exceptions in Warbler’s code, but that didn’t mean I knew why it worked, or if there were better ways to do any of it.)

If you are at all interested in learning how to create interactive fiction today, or if (like me) you already know a thing or two but could stand to learn a lot more, I cannot recommend Creating Interactive Fiction highly enough. Rather than offering a language reference (which it isn’t), it provides a guided tour of Inform’s major features by way of a gently iterative traversal of a single, non-trivial IF work’s source text. Crucially, as Andy wrote, Sand-Dancer is not a contrived example game but a solid work in its own right. The process aims to inspire the reader to continue their IF-crafting studies with their own work, and I am here to tell you that it worked for me.

Furthermore, if you plan to follow along with the code examples, and you can swing a dual-monitor work setup, I advise picking up the book’s Kindle edition. Even though the author kindly provided this blog with a physical review copy of the book, I appreciated being able to page through both it and my own, ever-growing ersatz Sand-Dancer source text at the same time with minimal eyesprain.

Tagged , , , | Leave a comment

Creating Interactive Fiction with Inform 7

Creating Interactive Fiction with Inform 7, by Aaron Reed. Cool-looking book, eh? It's been out for a few weeks, and I haven't seen a review beyond short "this book is awesome!" posts. I finished reading it last week. I ought to write a review.

This book is awesome, and... hm. What is it? Hm. Okay, what isn't it?

Creating Interactive Fiction with Inform 7 by Aaron Reed

Aaron has not written a reference manual, nor a tutorial, nor has he duplicated the standard I7 manual. What he's written is example code -- except it's example code that covers the entire game-creation process, step by step, from the first room up to a finished game. By the time you reach the end, you will have had a tour of I7's core features. But it's all driven by "What do I add next to this game?"

This gives the reader an unusual progression of topics: first objects, then relations, descriptions, actions... Traditional programming constructs like if-statements and variables don't show up until halfway in. This may infuriate readers with a traditional programming background. But then, maybe not. The point of this approach is to explain constructs as they're needed, and you can frame out an awful lot of an Inform game without using a global variable. (Okay, "if" is more crucial. But the sorts of conditionals that are most common in I7 -- conditional text and rule conditions -- do show up earlier. They're just not presented in the context of old-school statement-by-statement imperative programming.)

To be sure, the standard I7 manual (which comes built-in with the I7 IDE) tries to use the same model. It, too, offers topics in the order that an I7 programmer might need them. However, without the underlying structure of the game-in-progress, that sequence can seem opaque. Aaron's sample game... well, pun not intended, but it provides the narrative for his manual.

More important: the game, Sand-dancer, is a good game. It is not the sort of example that exists to have one of everything in the manual. It is the sort of game that exists to make IF better. Aaron puts it together on your workbench. You can see the parts going in, and I don't mean rules and action constructs now; I mean character, background, voice, theme, and narrative drive. He explains what he's doing, and what each game element is for. He talks about story structure and shape of interactivity. He discusses what you have to do to get the player involved and what you have to do to put the player in control.

You'll come out the far side of this book with a clear view of what goes through an IF author's head. I won't go so far as to say this is a platform-neutral IF writer's guide. It's about Inform 7, and it spends most of its time teaching you to program in Inform, not to design IF games in general. But if you're an absolute newcomer to the field -- if you have no idea of what this medium is good for, or why anybody bothers -- you could get worse introductions than Aaron's book.

(Or you could play Sand-dancer right now, in your web browser. The source code is also available -- complete, or as of each chapter of the manual's construction process.)

My reviewer's license (nice wallet-sized card, laminated, hologram seal -- ask me sometime) says that I should pick some nits before I go. Well, the "tip" icon -- for highlighted "tip!" paragraphs, you know -- is a weird-looking black light bulb. That's not a nit. The nit is about the "caution" icon, which seems to be a dead alien vampire baby head. I guess those do make me cautious, so it makes some sense. Maybe?

Really, my only complaint is that it's not always clear when Aaron is teaching you his own personal I7 usage style.

For example -- sorry, I'm going to lapse into I7 technicalities for a moment -- Aaron claims that "instead" rules are always for specific situations, and "check" rules are for changing default behavior. Well, you can do it that way. Indeed, the built-in I7 manual makes the same claim -- but neither book digs into the reasons why that might be true. The fact is simply that an "instead" rule bypasses the "check" rules; so if there's a conflict, "instead" takes precedence. You will often want specific checks to take precedence over general ones, but not always. There's a lot of ways you could use this tool, and the book doesn't go into many of them. Is this a fault? Of course not; the book could be twice as long and not detail half of I7's subtleties. But I'd have appreciated a hand waved in the general direction.

Or too: The book leans heavily on the slightly-cutesy mnemonic BENT, for "bracket every notable thing". This is Aaron's proffered solution to the problem of under-implemented objects in games. Basically, you write each room description in such a way that the compiler nags you to implement all the objects (if only minimally). As a solution to a specific problem, it's fine. Is it the most urgent problem for students of IF, and is it the most comfortable solution? Is it what they need to be nagged about? I'm not convinced. But of course, I'm a crotchety old IF guy and my habits are set. Don't put me in front of students.

Really, any programming guide will teach you the author's programming style. Especially in a bactrian programming language (which I7 very much is).

(Eh? Bactrian, as in there's always (at least) two ways to hump your pack across the desert. As opposed to a serpentine programming language, in which there's just one way to slither through, no side limbs. Got it? Good.)

But now the reviewer's license is satisfied; it's cooling down from its red heat with faint pops and pings; I can go back to praising the book.

So yeah. Creating Interactive Fiction with Inform 7, by Aaron Reed. Cool-looking book. Also worth reading.

Aaron Reed provided a free review copy of his book for The Gameshelf. It didn't actually arrive until after I posted this review, though. I bought my copy off B&N like a regular schlub.

Tagged , , , , , , | 4 Comments

Rule-based programming in interactive fiction

This past weekend I gave a talk on Inform 7 at Penguicon, an SF-and-open-source convention in Michigan.

The slides and the text (modulo the umms) are now up on my web site:

Rule-Based Programming in Interactive Fiction

This is not an Inform 7 tutorial. (You can find those on the Inform 7 web site.) Nor do I discuss I7's natural-language syntax. Rather, I try to explain the underlying programming model, and why it exists. I then go on to talk about my crazy ideas for a completely rule-based language, which is not Inform 7, but might be a future mutation of it.

The talk went nicely, in case you were wondering. About eight or ten people showed up, which is pretty good for a programming lecture at 10 AM on a Sunday.

And while I'm at it, let me recommend Penguicon as a darn good time. I've never been to a convention at which Sarah Monette and Elizabeth Bear argued about fantasy, John Scalzi lectured on people skills, while -- in a room party upstairs -- some guys tried to get Debian running on a DEC AlphaStation 200. I've also never been to a convention where I got to be in a panel discussion with Jane McGonigal, the ARG guru.

All these things were awesome! Except the Debian install -- they seemed to be having trouble with that. Mostly because the hotel's wifi network was utterly, utterly crushed.

Posted in Zarf on Games | Tagged , , , , | 7 Comments

Interactive Fiction Writing Month

Lea has announced Interactive Fiction Writing Month:

IF Month is a loosely-organized set of tasks assigned one per week for four weeks, from February 15 to March 15, 2009, hopefully coupled with a few informal live discussion sessions (location-dependent, of course). The goal is to get a group of participants familiar enough with the Inform language to produce some simple games, and to promote discourse on game design in general through the medium of IF.

The organizer is at CMU in Pittsburgh, so that's where the initial "location dependence" is, but interested people may be arranging other meet-ups.

Further details at the IFMonth Blog.

The personal note: CMU is my college stomping ground, and I've met Lea and some of the other CMU folks involved on various visits back there. They are cool. Check it out.

Tagged , , | 1 Comment