I7 Code Organization and Efficiency

Is there an “optimal” way to organize I7 code for efficiency?

My background is in web application development, so I’m used to organizing my code for linear processing. I also have experience with OOP, which generally requires code to be organized in a specific way. In my current WIP I tried to organize the code in a purposeful way:

  1. Settings
  2. Extensions
  3. Variables, new values and new properties
  4. The Map (rooms, regions and doors)
  5. Things
  6. Rules, activities, and new actions
  7. NPCs and their routines
  8. Data tables (for the help menu)

The WIP source has less than 2500 lines, uses 7 extensions, and has 14 rooms and 93 things. When I try to compile it for Z-machine, Inform tells me “This program has overflowed the maximum readable-memory size of the Z-machine format.” The results console tells me “The story file exceeds version-8 limit (512K) by 119680 bytes.” Using “Use memory economy.” lops off about 32 kb. I can lop off another 10 kb by removing half of the HELP data.

This seems to suggest either:

  1. My NPC routines are so complex they require huge amounts of memory (the most complex NPC is a juggler who drops things and picks things up).
  2. One of the extensions I’m using uses more memory than it should.
  3. The game has too many rules.
  4. The way I have written my code causes bloating when the game is compiled.

My understanding is that it’s unusual for a game built with recent builds of Inform 7 to fit into a z-machine file, just because of all the stuff that is now built into I7. The game would have to be unusually small to fit. gblorb is much more common these days.

I agree with BG.

You don’t need to fit anything into zblorb/z8/z5, and in fact later compilers have more stuff added as overhead before you start to compile. So it’s not you, it’s them. But they do add a lot of useful stuff.

Conversely, if you write in Inform 6, you’ll almost never need to raise memory limits unless you’re doing something really complex.

If your game is still pretty basic, and you’d like to create a z-machine file, then maybe the 6G65 compiler is the best way to go. It’s what I still use. But you may need to tweak the source.

You can also use the code below to see how much memory is being taken up:

Include (- Switches z; -) after "ICL Commands" in "Output.i6t".

Thanks to Zarf for showing me this somewhere earlier on the forum.

I have been wondering how to organize the code myself.

Unlike you, I put persons and things right after the room they belong in. I don’t know how Inform feel about this, but I think I get a better feel for the world if the room and its content is stuffed together. (if I later need to see a neat list of all things, I do a source search for is a thing)

If you need to see a list of things, just go to the World tab of the Index–the Gazetteer will give you a list of things, while the Map tab will tell you where they are at the beginning of play. You can click a plus sign next to one to see more information about it, and an arrow sign next to it to jump to the place where it was defined in the source code.

This can also be useful for catching errors (for instance, I had something where I spelled Holmes’s nemesis Moriarty some of the time and Moriarity some of the time, and that led to Moriarity defined as a person out of play, which led to weird runtime behavior that I couldn’t diagnose until I looked at the Index and realized that I’d defined two different people).

[Edited to add: And then I clicked another thread and the first thing I saw was Mike Gentry singing the praises of the Gazetteer. We have consensus!]

Well, I haven’t been able to compile the project for Z-code yet, but after some tinkering I have managed to reduce the excess memory from 117 kb to 38 kb. The largest chuck came from replacing Wade Clarke’s Basic Help Menu extension with Emily Short’s Basic Help Menu extension. It also helped to remove 92 blank lines from a table (type fast - debug slow: the line of code originally said “with 12 blank lines.” and at some point I meant to change that to 9, but it ended up 92.).

My choices now are either squeeze out 40 kb more without completely eliminating the HELP system, or find an Android app capable of handling gblorb files (“You can’t see any such thing.”).

I will also jump on the bandwagon and point out that the Innards tab of the Contents Index is what helped me track down the memory hog in my code. The table with 92 blank lines was right there at the top of the list clocking in at 938 bytes.

This particular project was my first with NPCs who actually react to the player’s actions. I originally had the code organized with people and things right after the rooms they were in, but that made for a lot of scrolling even with headings. I ended up reorganizing the code so I could use the source “contents” view to jump around. Logically, NPCs and their routines should have been after Things.

Or start over and write the whole game in Inform 6. My very first game was in I6 (back in 1999). It was a large game, and compiled to .z8. (There was no such thing as glulx at the time.) You said you have some background in OOP, so I6 might be a natural for you.

If you don’t want to start over quite as much, you could grab version 6G60 of Inform 7 from the web site and see if you can port your project back to that. Depending on what you’re using, and what extensions you’re using, it may not be too much effort to make your Inform 7 code work in the older version, and it’s much easier to fit games in those versions into the .z8 memory limits (as long as you avoid using indexed text and a bunch of lists).

Someone has to say it, so I will - unless you’re going for a specific platform or a specific non-Glulx effect like easily-handled text colours, there may be no reason to torture yourself into fitting your game in the ZMachine. There are Glulx terps for most platforms out there, including mobile devices and web browsers (Quixe games tend to play slowly in my browser, but I haven’t seen anyone else complain so it must be just me). It may be easier just to switch over to Glulx.

Of efficiency, I cannot speak.

Of organisation, I split up my first I7 game:

Some Settings
Rooms
Scenery
Things
People
Tables
More settings and Test me stuff

In the event, it meant I was scurrying around the source, frequently having to search for what I wanted in several places.

In the game I’m writing now, I’m putting Scenery, things, persons, tables behind the room I associate them with. Much easier navigation. So the room is the major heading for everything. My rooms include Limbo, which is my name for nowhere, and general purpose stuff may go in there, though I haven’t yet found anything I want to put in Limbo.

That is neat. My room is called lalaland, with the bullpen for stuff that’s sort of used.

I organize my code a bit differently.

volume includes, stubs and basic rules

volume standard verbs edited

part simple verbs

chapter score

chapter inventory

chapter

part complex verbs

volume world map

part region #1

chapter room #1

section item #1

section person #1

volume new verbs

part out of world/helper verbs

chapter about

chapter credits

chapter verb listings

part in world verbs

volume tables and other data structures

volume beta testing - not for release (except to testers – I have a way to hack so this is “for release” to a different named blorb)

volume testing - not for release

This is a bit flexible. check giving (item in room 1) to (person in room 2) could go under room 1 or room 2.