Most common 'mistakes' and 'crutches' for those starting out with inform 7?

Yeah, I didn’t name a lot of rules at first. I didn’t see the point. But then the first time I actually needed to, a bunch of dominoes fell.

I also think some crutches aren’t necessarily bad–they get you going, and later you see why the more general way is best for more ambitious projects. So if you look back and say “boy! That crutch I used was awkward!” don’t waste too much time on it. The next project will go smoother.

It took me a while to come around to how I didn’t need to add as much new stuff as I thought!

I’d add the caveat here that I had a lot of trouble pulling myself away from a main project to open up a sandbox project that tried something new. This has been really valuable to me–a lot of times I got a weird error in a big game, or I didn’t understand how to implement syntax, and I opened up a smaller/blank project and was able to isolate the problem.

You don’t have to reinvent the wheel as much as you think. Smart people ahead of you created inform, and smart people wrote extensions. Smart people wrote in it, too, and they shared the source code, and one big help for me is looking at said source code to see “oh, that’s how someone did things, or did things better than me.”

I have to admit I did! I’ve done so a lot. It’s been really useful for me to poke into I6 as well. But what usually happens is, I wind up poking at what I want and just stopping there. But I think as I learn more I7, the source becomes easier to read, and I never went back to say “OK, that thing that was intimidating once and still feels like it because horizon effect, etc. shouldn’t and doesn’t any more.” So I would add it helps to go back to the source code you cribbed from, to make sure you were doing things right.

I’ve also learned a ton from extensions as well. Once I start using one and wondering “how did they do that?” or “I’d like X, but without the overhead/modified to do Y,” it feels good to be able to build on things.

I know when I dive into a new language I have a fear of not understanding the deeper stuff, but I recognize the worst that happens is, I just don’t understand stuff, but maybe I’m primed for when I have more experience and might understand it later.


I second this. When I was working on Transparent,


I was working in the Mac IDE during a time where for some reason the troubleshooting jump-arrows were not working.

You know how you see an error and can click to jump there in the code? That didn’t work.

So I had to divide the source text with enough grain so I could read the error and then use the outline filter view to cut the text down to just that section and find the error.

It also trained me to keep random rules kind of close to the room or concept that they pertained to instead of just adding things to the end of the source all the time.

It’s also quite satisfying when you get to name a section something like “Section 15 - All Right, Fine, Beta Testers, you think it will be fun to set things on fire with the candle?”

1 Like

One of the easiest pitfalls to repeatedly stumble into is to forget that your are coding a game or interactive story, not a simulation…

If your game requires a car to get you from A to B, it probably needs nothing more complex than for “Enter car. Go North” to work. No need for keys, opening & closing doors, starting & stopping the engine etc. etc. etc.

Furthermore, if there’s a clash between fun game mechanics and realism, always choose the former. Consider the hit-points-based fight mechanics of classical Dungeons & Dragons. Utterly ridiculous from a simulation point of view: People (and monsters) don’t generally succumb in hand-to-hand combat to ‘death from a thousand cuts’. But it works better as an enjoyable approach to risk-taking regarding combat than a more dichotomous but realistic ‘your character will likely die or remain largely unscathed’- albeit this is the situation faced even by a D&D character with a single hit point- which is why many D&D campaigns allow such characters to be re-rolled…


Staying with the car example for a moment, you could of course have the player search the whole house for the key (which obviously involves navigating a remote-controlled robotic mouse under the floorboards), have them fail at opening the driver’s door because it is rusted shut and make them tear down the garage wall at the other side of the car (which is parked too close to it to get in otherwise) using an improvised battering ram before allowing them to enter the car and drive away. One would, naturally, have to keep in mind that while it wouldn’t be necessary to turn the key before going north, the player should be awarded extra points for doing so (and for closing the car door behind them). In the end though, the whole scene would just be another lock-and-key-puzzle and should, for well-known narrative reasons, indeed be cut in its entirety. The story should start on the lonely mountain road after the car has broken down.


Thought of another: if you say

A thing can be dynamic or static.

and don’t specify a default, the default is that it’s not the first thing. Awkward language on purpose to also embrace this case:

A thing can be confiscated. [ by default things are not confiscated. ]

But with enumerated kind of value properties, if you don’t make a default explicit with usually or seldom the default is the first named.

grade-value is a kind of value. The grade-values are A-grade and F-grade.

A person has a grade-value called the grade. [ default grade is A-grade ]

You may well find it easiest to just be sure to always specify the default explicitly than to remember this…


Since this topic popped up, I thought I’d write up one thing I didn’t realize for a long time because I had “good enough I guess.”

Perhaps the silliest thing I did early on was not realizing that repeat loops could have continue; and next;. They seemed to work okay, then one day I needed continue/next type logic, and I did something horrible like

let found-one be a truth state that varies
repeat with x running through touchable things:
    if found-one is false and x is (what we want):
        (do something)
        now found-one is true;

For some reason I just missed something, but then when I read the documentation it was obvious. So as I mentioned above, if you’re just glad something works, it’s worth bookmarking it later to read the relevant documentation, as something might fall out.

The “abide by” syntax was also something I didn’t look at for a while. A lot of times I’d just use the “to do-x:” syntax. And then I had to use some hacky stuff to back out of main rules at first, and eventually I got sick of said hacky stuff or duplicate coding. I wish I’d have gotten sick of it quicker.

Note, for those who don’t know, “abide by” helps avoid duplicating code. Below is pseudocode, but it gives an example.

this is the what can't be moved rule:
    if noun is carried, say "You don't need to." instead;
    if noun is a person, say "You don't want to start any fights." instead;
    if noun is the broken lever, say "The broken lever is broken." instead;
    if noun is the lawnmower, say "The lawnmower is out of gas." instead;
    if noun is the sofa and nickel is off-stage:
        now the player has the nickel;
        say "You find a nickel under the sofa!" instead;

carry out pushing:
    abide by the what can't be moved rule;
    (do the main stuff);

carry out pulling:
    abide by the what can't be moved rule;
    (do the main stuff);

This was one of those things where once I saw it, I felt silly I didn’t find it earlier.

One crutch I still use (I don’t know if there’s a better way) is to have a room called done-room. Then:

to mark-done (th - a thing):
    move th to done-room;

definition: a thing (called th) is done-with:
    if th is in done-room, yes;

I mention it because at first I would get rid of items by putting them back out of play, which caused problems when I said “if x is off-stage and (search and find x), now player has x”.

1 Like

I’m trying to get a demo out the door, and I had a really messy verb that I wanted to clean up so that it made more sense on-screen.

Well, I accidentally used “any thing” instead of “something”. Not sure why, I never do that. Anyway, it compiled fine but I started getting run-time errors about various things: variables, disambiguation messages for objects in other rooms, run-time errors.

It’s a busy verb that goes through the whole processing order and, miracle of miracles, it was all coded correctly, but verifying that was impossible because of the errors. I looked at rules, looked at actions. Was stumped. I wasn’t catching on to the “any thing” and “something.” distinction.

Picked the whole process apart, fed it piece by piece into my test project. Started commenting out values because of the error messages. Starting from a mountain (for me, anyway) of code, I whittled it down bit by bit. Finally got to practically nothing:

frobbing is an action applying to one thing.
understand "frob [any thing]" as frobbing.

check frobbing:
	continue the action.

Was still getting disambiguation messages for items in other rooms. I even wrote a rule for stopping actions applying to such objects :stuck_out_tongue:

So. That was last night (NA CST) and I just now fixed it. Feels kind of dumb, but my brain just edited it out.

That’s definitely my biggest mistake so far as a beginner. “Any thing” is serious business.


Wow that would’ve been a great learning experience albeit a frustrating one. So I’m guessing any thing would encompass literally anything vs something which only refers to a thing? This could obviously have very interesting complications depending on the context that any thing is used.

1 Like

I have been thinking about having a room called the graveyard or cemetery to move a dead enemy or the player to in certain circumstances. Seems like while a bit hacky, could be the simplest way to achieve a multitude of things in my game at least.

I definitely think that learning how named rules and rules books work is incredibly valuable. I have already started going through and naming a lot of my rules that I previously didn’t think I needed to mainly be Use as you keep going with adding features to the game, all of a sudden the thing you thought wouldn’t interfere with anything else, becomes just another cog in the machine that needs to all run cohesively.

I’m strangely excited to finish my combat system/extension of sorts so I can go through meticulously and rewrite and streamline the code as much as possible before continuing with the other aspects of my project. Unfortunately Ive set myself a limiting factor in that if this one (very crucial) part of my project isn’t watertight, it will make writing the rest of my game very frustrating.

Yeah, it’s definitely got its uses e.g. “hint [any thing]” or “go to [any thing]” … though to go to a room you’d use “go to [room]”.

I know it was also confusing for me to see

xing is an action applying to one thing.
xing is an action applying to one visible thing.

The second acts on stuff you can’t see.

1 Like

Check out the Nathanael’s Cookbook extension for most of the things which have tripped me up. There is a long discourse on Inform’s line break algorithms there.

( extensions/Nathanael's Cookbook.i7x at master · i7/extensions · GitHub )

The other thing which trips me up is the insistence on hard tabs in rule definitions, which requires retuning my text editor; Python-style space tolerance would be a vast improvement.

If you’re writing extensions, I also wrote an Extension Style Guide after some painful trial and error, explaining motivation for each guideline.

( extensions/Nathanael's Extension Style Guide.txt at master · i7/extensions · GitHub )


I figured this one out early, but reading this thread I realize that many people have not realized the method of:

The unmention things mentioned in room heading rule is listed before the room description body text rule in the carry out looking rulebook.

for getting your rule order correct. If you’re inserting into an existing rulebook, you can slot before a specific rule. If you’re building your own rulebook, you can either make a full ordering or make a partial ordering and let Inform worry about the ones where you’re not so picky. It’s important to know the names of the rulebooks.

If you’re changing core Inform behavior, the cleanest way to do it is usually to replace a single rule with a tweaked version:

The fixed describe what's on mentioned supporters in room descriptions rule
	is listed instead of
	the describe what's on mentioned supporters in room descriptions rule
	in the
	for printing a locale paragraph about rulebook.

… but sometimes slotting in an extra rule “before” another rule does the trick better.

If you’re building your own rulebook, being able to list the entire order of the rulebook is a lifesaver.

I relied on the Inform 7 Programmer’s Manual by Ron Newcomb to learn how the rulebooks work, but it’s several versions out of date.

1 Like

It only insists on hard tabs in tables and the swtich-like if variant. I dislike syntactically significant whitespace for code and hate syntactically significant tabs with a passion, so (unless I’m being consistent with existing code when modifying it) I go without tabs and type “begin” and “end” a lot.

1 Like

Thanks for posting this - I’ve just used your Cookbook to help me get rid of a rogue line break that’s been bugging me since my first game!

1 Like

I think it insists on tabs at the leading edge of examples inside the documentation of extensions, too? This is what tripped me up the most. If there’s an alternative to that I would love to know it.

yeah, there’s that too. It slipped my mind as a non-code per se thing, but shouldn’t’ve 'cause having been futzing with compiling all the Friends Extension repo examples I’ve seen how often they’re misformatted in practice…

With Python as my most used language for work at the moment, I would certainly welcome space tolerance. But, mostly I’m just very happy that Inform 7 supports syntactic white space for conditional statements. More of a way it helped me avoid mistakes as someone starting out, I guess.

1 Like