The experience of a first-time author in Inform 7

A short time ago I started writing my first game with the intention of implementing it in both Inform 7 and TADS 3 in order to figure out which system was right for me. Here are my thoughts about Inform 7.

This post is not spoily, but in case you want to play the game, it’s available at IFDB.

Before even starting the game, I decided to keep it as simple as possible. To that end, I decided on the following rules:

  1. Refrain from using extensions. The reason for this is that it adds a lot of complexity and extra material to learn.
  2. Keep the customizations to a minimum. This means no mucking about with customizing library messages for everything. If the default response for something wasn’t horrible, I kept it.
  3. Don’t ask for help. The game is quite simple and I wanted to see how difficult it would be to figure pretty basic things out for myself. This may or may not have been a good idea, but it’s done now.

Before I start the analysis, let me just say that overall the experence was very positive and I had fun writing the game. Inform 7 is a great system, but invariably, the parts that you remember best are the bad parts. So forgive me if this sounds overly nitpicky - I’ve tried to only include the issues that I think are actually important. There were pleny of frustrating moments that I believe were caused by my inexperience. I’ve left those out.

Rant starts here:
[rant]Almost the first line of the source is Include Custom Library Messages by Ron Newcomb. So much for rule number 1 above. I wanted the game to be in third person, and that’s really the only way to do it. But the transition was painless, so I’m not complaining. The line after that reads Include Pronouns by Ron Newcomb. This one has a story behind it. It was added almost at the very end. You see, after switching the story to third person, I wrote the introductory text that describes the character arriving. After that a logical player command would be X HIM. For the life of me I couldn’t figure out how to make the pronoun ‘he’ refer to the player. When play starts: set pronouns from the player/yourself didn’t work, nor any other thing I tried. So I just left it until most of the rest of the game was finished, at which time I discovered the extention, which does just what I needed.

And this highlights a problem I have with extensions in Inform (and some other things, like LaTeX). There are just too many of them. I don’t have an overview of what is available and when I need some small functionality, I don’t immediately go looking for an extension. That was part of the orginal reason why I decided not to use extensions for this project - I didn’t want to get bogged down in reading the documentation of all the extensions to find out what they do. If I stick with Inform, I will be using extensions for my more serious works, and I imagine there will be plenty of times where I just overlook a really useful extension because I never think to look for it.

A somewhat related problem is the diversity of the language constructs. Again, there’s really no way to know what to actually type for any specific case without diving into the documentation. The descriptions of groups of objects that Inform provides is a powerful way to generalize, but I found that I couldn’t write any kind of complex description that would actually compile. The error messages where very general, so I don’t really know what I did wrong. The result was that I either found an expression that worked and stuck with it, or split up the code over several expressions, so that all the power and versatility of the description system was wasted. One specific example: descriptions used as values can’t contain temporary variables. Why not? The error message said something which basically means that it’s trying to protect me from using a value which might not exist. Dear Inform, I know what I’m doing. Trust me, the value exists - I just created it on the previous line and I know the object is there. And if I didn’t know what I was doing, the error message wouldn’t make any sense to me anyway. Besides, there’s a workaround for it, which compiles, but would still generate a run-time error if the value didn’t exist.

Speaking of diving into the documentation, it just doesn’t work for me. Usually when I tried to find out how to do something, I spent a lot of time looking for the right place in the documentation. For example, I wanted to find out how to crete a new action applying to a topic instead of a thing (at that time I didn’t know it was called a topic, I just knew it had to match some fairly arbitrary text the player typed). Is the section of the documentation in the Actions chapter? No, how about the Advanced Actions chapter? Nope, it’s in the Understand chapter under the header The text token. Sure, the two things are related, but I wouldn’t know it before reading it.

Compilation time is a real problem in my opinion. It’s just annoying when I make a small change and have to wait almost a minute to test it. It’s probably even worse in a large project. Separate compilation and the ability to split the source text among several files would help a lot, but that would probably require a complete redesign. A smaller redesign could be to keep the extensions and standard rules compiled. That would shave off a lot of time. Another thing: why do we need to recompile when I haven’t actually made any changes to the source? That’s a really easy fix. Also, what happens to the index when I close the application? The next time I open it, the index is gone and needs to be recompiled before it will appear. Does the program just delete it when it closes? Or does it keep the whole thing in memory? Either way, it’s silly. This is a problem, because I’m frequently in a situation where I make a lot of changes that no longer compile. I get frustrated with them and take a break from the whole thing. The next time I come back, the source still won’t compile and I have no way to use the index until I fix it.

Another thing I found annoying was the verbosity of the language. ‘Description’ and ‘Understand’ are long words and it’s easy to make a typo while writing them, but these are among the most common things you need to type. Some sort of shortcut for those would be nice. There is a shortcut for descriptions of rooms - just write a quoted string after creating the room. That same shortcut for things sets the initial appearance instead. Why? Every object needs a description, but not every object needs an initial appearance.

I struggled with naming things. Forgive the comparison to TADS 3 here, but I really missed the ability to have anonymous objects. I have lots of similar objects in different rooms with slightly different behaviours. The behaviour is completely defined in general rules, so I don’t really care what it’s called as I don’t have to refer to it anywhere, but I have to keep thinking of different names for everything. Making it privately-named is two extra sentences for every object, so that’s annoying too.

After all that whining, let’s talk about something good. I’m really impressed with the index, skein and transcript tabs. I frequently used all the subsections of the index tab to see what actions are available to the player and what commands lead to those actions, what rules govern the standard behaviour, and so on. The most useful feature has to be the ability to jump to the place of definition of various things from the index, though that gets screwed up if you edit the file before recompiling. The skein was also very nice, though I imagine that a less linear game might see more use out of it. Right now, I just did a walkthrough of the game and annotated some checkpoints so I could quickly get to them. The transcript is good too, it allowed me to quickly scan the output and only note the places that actually changed. This saves a lot of time as you don’t need to reread everything.

Also, a word about the parser and understand rules. Though I didn’t go very deep into it, it seems to me that with skillful use of understand rules the parser can understand some rather complicated phrases. Actually writing the rules is clunky and verbose, but it’s straightforward and very doable. One feature I missed was the ability to match all the vocabulary of a game object as a token. I know that several extensions provide an equivalent functionality, but again, I decided not to use extensions.

I like the fact that the standard behavior is broken up into small rules, which made it easy to modify specific parts of it.

The built-in spellchecker is a nice feature, though I wish it would only check quoted strings.[/rant]

Despite what it might seem like from this post, there are more positive than negative aspects to Inform 7. I’d readily write another game with it and I’d probably have less complaints doing so as I know to avoid some of the annoyances and utilise the more powerful features of the language.

This strikes me as a very balanced and reasonable review of the issues and annoyances with Inform 7 (and of some of the good things with it). Will you share your experience of implementing the game in TADS, too?

As for the Inform index, I think there is an option in the preferences for whether or not to clean the index on closing. At least this is so with the Mac version of the IDE (where the default, I think, is NOT to erase the index).

I’ve noticed similar preconceptions before, also with plugins or libraries in other (non-IF) programming languages. The truth is, as you found out, that the purpose of extensions is to reduce complexity and development time.

It certainly is a bit of a problem that the amount of available extensions can be daunting, especially since many of them are not very good or they haven’t been updated for newer versions of Inform. I believe a re-design of the extension repository is underway.

That doesn’t sound right–it has never taken me more than maybe 5 seconds max to compile even large (~50,000 words) projects on a Mac or on Windows. What’s your hardware and OS setup?

The Mac IDE doesn’t recompile if there haven’t been any changes to the source, it just restarts the story. It also saves the index. I don’t remember how it works on Windows. (You can also restart the story by typing RESTART if you just want to replay from the start.)

It’d be nice to see an example of what you mean exactly, but it sounds like you could use anonymous instances of kinds:

A table is a kind of supporter. There is a table in the living room. There is a table in the kitchen.

Yeah, this pretty much hits the various nails on their heads for me, too. One thing I’ll point out is that, as far as I understand it, the specifics of that first annoyance (about having to use an extension for third person) should be cleared up in the next release of Inform, which will generally have better built-in support for tinkering with library messages. In the general case, I agree that the way extensions are organized/presented is hard to know what to look for; likewise with the documentation. My own approach is to read through the extensions listing and documentation in full from time to time, and hope that I’ll remember enough salient details to find what I’m looking for when I need it. In the case of the documentation, I find that I often remember some detail about the example code better than I know where it was. Like: “oh, I know there’s an example about concealed possessions and Clark Gable…” There’s also eblong.com/zarf/i7index/ but I couldn’t get where to find actions on topics out of it, either.

Yes, implementation in TADS is underway and I plan to do a similar writeup when it’s finished.

Yes, I agree that extensions reduce development time and make certain tasks easier, but I still think they increase complexity. What I mean is that every extension adds to the number of available functions and expands the relevant documentation. For my first project I wanted to keep things as limited as possible.

I now realize that I was actually unfair at this point. My processor is currently limited to 25% of maximum performance due to a faulty fan. I’m using Windows 7 on a 2-year old laptop, so once it’s fixed it should be much faster.

I have now found the option to keep the index in the Windows IDE. Thank you for pointing that out. There doesn’t seem to be an option to not recompile an unchanged project, however. The problem with just typing RESTART is that the skein keeps recording all the subsequent commands in the same thread. If I wanted to start a different thread in the skein, I’d still need click to go button.

I did use this technique at one point, but what I meant was this: I have a distant object that is visible from several rooms, but described differently in each. So I had to come up with different but similar names to describe the same thing. I realize I could have done it better by having a single object and varying its description depending on the location of the player, but that is hindsight.

If you get time, it would be interesting to hear your experiences of implementing the game in Quest as well…

That’s handled pretty well by I7.
Just make a Region, put all your rooms into that Region, and create a backdrop.
Example – non-tested – code:

[code]The Moon Soil is a Region.

The distant Earth is a backdrop in The Moon Soil. The description is “Cyanotic. Yeah, you know it. And distant. You feel like breathing is hard from this perspective[if the location is First Yard]. You must be one trillion yards away from home[else if location is Second Yard]. You must be one trillion yards away from home, minus one. If you walked the right direction, I mean[end if].”

The First Yard is a room. “Blah, blah.” It is in the Moon Soil.
The Second Yard is north of The First Yard. “Again: blah, blah.” It is in the Moon Soil.[/code]
This helps a lot when combining actions for different rooms, also:

Instead of listening when in the Moon Soil, say "[if the location is First Yard]You can hear nothing. Really[else]Now that you came closer, you can hear the traffic rumbling on Broadway[end if]."

Both 1. and 3. would give Inform a major handicap:

  1. I don’t know TADS well, but I know it includes a huge amount of functionality without extensions. Inform’s design is pretty much the opposite - don’t include anything unless you’d always need it. Compared to I6 extensions, I think the I7 website’s selection is much more focused. The maintainer’s curation of extensions (or at least standard for submission) does a lot to help authors find exactly the right extension they need.

  2. Once again, I don’t know the TADS documentation well, but I do know that Inform 7’s documentation is VERY hard to use - especially when you compare it to the wealth of help you can get very quickly by asking questions here. I’ve said before that I consider this forum to be the real source of documentation for I7.

I wouldn’t say that your criteria are unfair, but if they reflect your ideas about what learning a new language should be like, maybe Inform is not for you.

The T3 documentation is spread out across a bunch of files, and there is no overall index. There is an overall Search function that locates terms no matter which doc file they’re in … but to use it you have to know what you’re looking for. (And of course you need to be working in Workbench.)

If you’re online you can use the search on tads.org too.