Many years ago, I7 came out, and in those early years, I got to test it, I think mostly as part of my time with ‘IF Whispers’ games. At some point during that time, someone asked me if I found I7’s syntax intuitive, because they found it difficult. I said, “Yeah, because any time I try something that doesn’t work, I file it as a bug report, so by now, it matches my personal intuition.” I don’t know how precisely true that was, but I do definitely remember getting a bunch of better error messages in there, handling the sorts of incorrect constructs I used to throw at it all the time. Never underestimate the power of a good error message that gets you back on track.
But it’s been decades since then, and (like python) I7 seems to revel in discarding backward-compatibility at any opportunity, so even the error messages Graham crafted just for me have mostly faded into obscurity, as has my knowledge of the now-defunct syntax. It’s still recognizable, but overall a lot of the details have changed.
A couple years ago, I finally pulled it up again, and started work on a project that I think I first had the idea for around 2008. But I still felt kind of shaky with it, and when the opportunity came up to participate in ‘Iron ChIF’, I jumped at it, partly just to force myself to really grapple with the language, and see if I could find a setup that worked for me.
The environment I landed on was to set up the bulk of the content of the game as ‘Extensions’, in a separate folder. Those source code files I would create and edit in Visual Studio Code, using the “Inform 7” extension by ‘Natrium729’. In another window, I’d have the I7 Windows IDE open, and that’s where I’d edit the (minimal) story.ni file. While coding and recompiling, I would edit in VSC, switch to I7, click in story.ni, hit ‘space’ and then ‘delete’ somewhere to let it know things had changed, then hit ‘replay’.
In the meantime, I uploaded the whole shebang to github. Ideally github commits are ‘I fixed/added this one thing’. This did not happen in the slightest. The first day of coding, I would set an alarm every hour, and when it went off I’d commit what I had. I was really afraid of futzing around accomplishing nothing, and I needed the external pressure of the timer and a public commit to keep on task. As the days progressed, I needed that crutch less, but still tried to keep up at least semi-regularly with commits.
So! How did it go? Here’s my report.
Where Lucian Went Wrong, and More of Lucian’s Greatest Mistakes
By far my biggest stupid problem was misremembering some phrase with a synonym instead of the actual word. Checking if a scene ‘started’ instead of if it ‘began’. Checking if a cyoa node was ‘visited’ instead of ‘previously displayed’. Or ‘previously viewed’ instead of ‘previously displayed’. This happened with my own things as well: I had one scene I called ‘Everything Falls’ and another I called ‘Everything Is Open’. I can’t tell you how many times I checked to see if “Everything is Falling” or “Everything Opens” were happening.
I also caused myself a fair amount of difficulty using constructs I guessed might exist, and do, but don’t do what I thought they would:
- “
A [if purple]purple[otherwise]invisible cloak” compiles! It prints ‘purple’! It does not actually print ‘invisible’, because it’s not checking if the thing being described is purple, it checks the concept of the ‘purple’ attribute in a Boolean context. I think. - Writing ‘
stop;’ in a routine: it compiles! It exits the routine like I thought it should! And I’m on to the next bit. And then with 6 hours to go, I finally realize that this is the cause of umpteen bugs in my code, because it doesn’t just stop the routine I’m running; it just stops the entire structure of the Inform turn sequence!
This was definitely exacerbated by not having enough time to look everything up, but also was a problem in the first place because it’s not nearly as easy to stumble on compiles-but-wrong syntax in traditional programming languages, meaning I’ve grown to rely on ‘check if it compiles’ as a syntax checker. Also exacerbated by the fact that similar shortcuts do do what I want, and if we went back in time to 2008 and gave Graham Nelson the idea, it might well have worked like I thought it would.
This was, of course, mitigated by all the times I tried something else I thought might exist, and it did, and did what I wanted! So, overall, a win. But definitely something to watch out for: I need to be more robust about checking to make sure my guesses about What Will Happen, Do Actually Happen. I will blame the time constraints.
The only other sort of ‘big issue’ I had was that I first experimented on using Carry Out for doors, and it turns out doors have extra steps I didn’t expect. So I was right about what Carry Out does in general, but I was wrong about what they did in that specific context, so that led me to think I just generally had failed to understand the concept. Not terrible; ‘check’ still worked, and it gave me something to ask about later, but a bit of a hiccup.
I also realized that I don’t really know how to use the various debugging verbs, nor how to utilize the ‘Index’ tab. I spent a lot of time trying to figure out why ‘visited’ didn’t work, and only much later did I realize that all I had to do was switch to the Index and look at the defined attributes for cyoa node. When I asked my ‘carry out’ question, someone suggested the ‘>RULES’ command: I tried it, and was utterly unable to parse what I was reading. So I have some work to do there, but I’m not sure if it’ll happen: if I can’t parse the results of RULES, I’m not going to try it more, which means I’m not going to see those results in different contexts, which would let me figure out what was going on. There doesn’t seem to be an easy on-ramp, in other words. But we’ll see.
An Area Where I7 Shines That Surprised Me
This is something that’s totally unique to Inform 7, and is kind of a secret sauce. Almost more than anything else about I7’s ‘natural language’ motif, it allows source code to have emotive meaning. I can go to the source, read that line, and remember what it’s like to be Horatio. It’s not at all the same as it might look in another language:
Horatio.mem_flag = 0;
Now, one might say I could write ‘Horatio.remembered = 0’ just as well, but when I went to go write that bit of code, my intent was simply 'I need a flag to trigger the ‘horatio is wandering around’ scene. But Inform pushed me to write something with semantic depth, and that in turn helped me write the player-facing text that wasn’t code, just by reminding me more of what the emotional tenor of the scene is. It’s surprisingly effective!
The Setup: review
My ‘Extensions’ setup: overall a win! Just being able to use Visual Studio Code with its much better find/replace system was huge. The biggest problem: remembering to hit ‘space/delete’ in my Inform 7 window when going back to hit ‘replay’. Especially when I was somewhere deep in the game, so the game would take a while to re-run the transcript, which would fool my brain into thinking it had re-compiled when it had not. Umpteen times, I would fix/change something, hit Replay, nothing would be changed, I would be flummoxed, and then finally realize I hadn’t hit space/delete so it would Actually Recompile.
I7 repositories: A win, but wow there’s a lot of fluff in there, with the Skein and a billion Index file and I don’t know what all. There’s probably a better way to do that, maybe with a github action to compile just the source, instead of committing both the source and the compilation files to the same repository. Though this way any I7 archaeologist will be able to see the rise and fall of 'course correction’s Skein. If someone has cause to do that.
My code organization: Mixed! I divided things up how I thought they might be needed later, and for most of the game’s development, it was generally true that if I was working on a single thing, I would probably be mostly messing around in one area in a single file. However, as the game progressed, this started falling apart more and more: stuff for the finale ended up being spread out over (I think) four different files. However, I was saved here by VSC’s global search. I had that window pinned to the lower left of my screen (under the list of files) and used it constantly. With that, if there was a phrase or object I used in different bits of the code, I could jump from one file to another seamlessly. Would 100% recommend.
The takeaway
While I was excited to dive in, I worried that Inform 7’s odd syntax might overwhelm me, especially after so many years of programming in more traditional environments. And as noted, it certainly had its foibles. But overall, it absolutely worked as intended: it helped focus my ideas and translate them into a playable game. In five days!
For any of the ‘pain points’ above: does anyone have a system that helps mitigate them? Or other setups that work for you?