Splitting the story into multiple files

Good day, i just recently started learning inform7 and i am quite bothered by the fact that i just got one file (story.ni) to work with, and i was wondering if and how you can split these out into their own files? (similarly to how you write software source code)

my idea was to put… for example each room in its own file, in a folder Source/rooms/garden.ni or something like that, same with perhaps items, actions etc

i figured this should be a really easy task but sadly reading through the documentation and googling all night has not brought me any closer to the solution

any help would be greatly appreciated, thank you ^^

You can create an extension and put it in the project.materials/Extensions/Your Name folder.

Thank you for responding @zarf
i did some googling and testing with extensions and it seems to work great!
one minor flaw though is that i cant do… project.materials/Extensions/Name/action/kicking.i7x for example

this isnt really a problem, i guess i can just type use the name folder to indicate if an extension is a room, action, etc

Extensions are intended for standalone components that you may want to re-use across multiple story projects. Think of each one as a separate “library” in the software-dev sense, if that helps.

For organising content within a single story project, you’re instead supposed to use sections within your main file – see §2.5. Headings.

The Outline tab in the Inform IDE allows quickly jumping between headings, as well as other benefits such as improving ambiguous name resolution and problem messages.

Inform prefers to think of a single story as a single “book”, not as a collection of components in the traditional software-development sense.

So while in principle nothing stops you from writing each room in its own extension or other such things, that’s really not the intended way of writing stories in Inform and the tools will fight you. It’s better not to.

1 Like

Worked fine for me. This is how I built Hadean Lands.

The only way the tools “fought me” was by not recognizing when an extension had been updated (so recompilation was necessary). That was 6G60, though. 6M62 is more enthusiastic about recompiling when you hit “Go”, although it still doesn’t do it every time. (Which might be worth reporting as a bug.)

That doesn’t support multiple-file editing in the way one is used to in general text editors. So I didn’t use it.

2 Likes

The IDE doesn’t support multiple-file editing at all. Perhaps it’s different on different platforms, but the only way you can edit multiple files on Windows is by opening multiple separate instances of the whole IDE. (Or using “open extension” instead of opening it as a project lets you use a cut-down editor, but it’s missing a lot of features and it’s still presented much differently from normal multi-file IDEs.)

That’s fine in small doses when you are genuinely working on a main story and an extension or two concurrently, but it rapidly gets too silly if you’re trying to have a hundred or more open concurrently, which is what was being proposed here. And you miss out on important conveniences such as auto-save-before-build.

This actually works well if you live in the outline-view in the I7 IDE. I’ve totally relied on it when writing a very difficult game during a time when the Mac IDE was broken and the links from the error reports didn’t actually work to jump to where the error was. Unless you’re doing an incredibly compact game, there no downside to throwing in headers to organize an Inform source text.

And agreed - I infer one of the main intentions of Glulx was to eliminate the hard character limit Infcoom started running against with their later, more verbose games.

You can use multiple files as mentioned with extensions in Inform, but why would you want to, other than just being used to it in other coding styles? (Or having some other really good reason like Zarf did for HL.)

I know that ChoiceScript games can and often use multiple files - but that makes sense because those games read like books and that code is more linear. CS tends to be written and flow like chapters in a book with discrete global variables as opposed to parser rules and messages that affect an entire world-model with a map and a player object where they can explore granularly instead of essentially choosing (I’m oversimplifying) what page to turn to next which tweaks stats. ChoiceScripe kind of drove me crazy with separate files and compiler until someone made CSide which is like Notepad++ for CS with auto compile/run/debug just like Inform 7.

So yeah, I can see how it would be unwieldy to have an entire CS plot in one text file when it doesn’t need to check more than a relative handful of stats at any given moment. But when writing simulationist physics in a parser world-model, I’d hat not being able to jump anywhere at any given moment instead of between files.

That’s just the way I7 is. I think TADS follows the more modular multiple files structure and that does tend to make better sense to people used to hardcore coding.

Maybe I just haven’t been using the outline view correctly, but I’ve found that switching between files is much easier than jumping around in one giant file. Navigating the table of contents takes too many clicks and I’m always losing my place.

It’s true that the IDE isn’t designed for this, so it might be relevant that lately I’ve taken to coding in a text editor and compiling on the command line, and getting that set up might not be something you’d want to spend time on while just beginning to learn Inform. But, if you have a workflow that allows it, I don’t know that there’s anything “unInformed” about using multiple files. I view the bias for single files in Inform as a quality of the tooling, not the language itself.

While that’s true, it’s entirely unrelated to the source text. Z-Machine/Glulx limits apply to the compiled output.

To be fair, I never use the Outline view myself (I don’t like how it hides the other sections as well as simply jumping to them). But using that is the intended use of the IDE, which is why I mentioned it.

For navigation within the text I mostly just use Ctrl-F. (But I still do divide the source text into sections, both for the other reasons that they’re useful and because they’re convenient Find anchors as well.)

Something I will do quite a bit, though (although reportedly this doesn’t work on Mac?) is to switch both the left and right panes to Source. This allows you to edit two different places in the source text simultaneously, which is usually enough for most purposes.

1 Like

Working with extensions as a solution for this works suprisingly well, although it definitely feels very hacky.

myself, i dont use a gui IDE as its seemingly not available for me (im on Manjaro Linux)
so i just use the command line tool, which while it has some downsides, works pretty well in my opinion. (then again, i got nothing to compare to, so problably im missing out big time lol)

1 Like

I think the IDE requires a different folder layout (unless that tree on the left is not representative of the layout), but if that works for you that’s fine I guess.

Although you might want to add this line to each one of your extension files (try typing version in your running story to see why):

Use authorial modesty.
1 Like

oh wow yeah, version prints out all extensions whitout it
thank you @mirality i very likely would missed that otherwise ^^

Since you’re using the command line anyway you could make a shell script that first combines all individual source files into story.ni and then compiles it. Then you can use whatever directory structure you want. The downside is that it’s harder to control the order in which the source files are included, which can sometimes be meaningful, and the compiler won’t know about the original files so error messages point to the generated file instead.

#! /bin/bash

find . -type f -name '*.i7' -exec cat {} + > story.ni
# ni compilation command here
1 Like

Would you be able to talk more about this?

I’ve developed a cursory interest in splitting up my WIP source file into sections so that I can leave some out to shorten compile time, which is decent on my computer and will continue to grow. In practice I’ve found doing so close to impossible. There’s only been one mechanic of the game isolated enough that I could take it out of the main source without (almost) affecting anything else. Otherwise, I’ve got a mixture of code organised by ‘levels’ (game levels), and code organised by commands. The latter refer to things found all over the game, so they alone are mostly a stopper. If I took all the objects and people organised by level and put them into a central hub or something, well, the hub will get really big, and I’ll also lose all the organisational help I get from the level structure.

At the moment I’m just banking on the project taking long enough that I’ll get a new computer that will be faster :slight_smile:

-Wade

excellent idea @Juhana, i decided to to try make a good script for doing just that

#!/usr/bin/env bash

set -e

WORKSPACE="$(dirname “$(readlink -f “$0”)”)"

echo “Workspace: $WORKSPACE”

print_file () {
printf “[$1]\n”
printf “cat "$1"\n”
printf “\n”
}

load_folder () {
printf “\n[ >> $1 << ]\n\n” >> “$WORKSPACE/Source/story.ni”
find “$1” -type f -name ‘*.ni’ | while read file; do print_file “$file”; done >> “$WORKSPACE/Source/story.ni”
}

cat main.ni > “$WORKSPACE/Source/story.ni”
load_folder property
load_folder actions
load_folder items
load_folder rooms

/usr/libexec/ni --internal “/usr/share/inform7/Internal” --format=ulx --project “$WORKSPACE” 2>&1

/usr/libexec/inform6 -kE2wSDGx “$WORKSPACE/Build/auto.inf” -o “$WORKSPACE/Build/output.ulx” 2>&1

/usr/libexec/dumb-glulxe “$WORKSPACE/Build/output.ulx”

placing this script in .inform and symlinking it from where you keep your files in a structure like this (i created my own .workspace folder in the same folder as the .inform and .materials)

image

then running it, should automatically compile the story.ni file from all your .ni files (things are loaded in the order specified by the script) and then launching it in glulx

the Source/story.ni ends up looking something like this

1 Like

Kerkerkruip and Counterfeit Monkey both split their code up into many extensions, if you’d like to see how it works in some big projects. How the main story.ni file includes them is probably the more interesting part than the actual extensions.

CM didn’t start broken up, its story.ni was a single file with over 27 thousand lines, so in some respects how we broke it up is a little bit arbitrary. story.ni still has the original table of contents.

Kerkerkruip’s was already broken up into extensions when we started working on it on Github.

Things in common include having all the game and compiler settings in one place in story.ni so you don’t have to go looking for them, including third party extensions before private game extensions, and there are also a few miscellaneous rule reorderings in the story.ni too.


Most people wouldn’t split individual things/rooms/objects up into individual files, and not just because that would mean a lot of files, but because it doesn’t naturally fit the programming model of Inform 7. Inform 7 isn’t object orientated, with code attached to objects. Instead rules associate custom code with zero, one, or more objects, and one action will often need multiple rules applying to different types of objects in order to specify in full what it does.

The advice I’d give would be to split it up into much larger sections, and usually you’d want to do that by isolating whole systems into files. So you might have files for:

  • aspects of the physical world model simulation
  • magic or science fiction mechanisms
  • linguistic stuff
  • dialogue systems
  • custom actions
  • testing and debugging

And then for the rest of it, rooms, things, characters, custom action responses etc, you could break it up based on the structure of your story, which might be based of geographical divisions, or temporal sections, like the acts of a play.

4 Likes

The organization for the HL source code looks like:

  • (main file) – intro text, credits, dragons, NPCs
  • HL Mechanism.i7x – actions and rulebooks having to do with magic and other game-wide behavior
  • HL Ritual.i7x – reactions for each step in rituals
  • HL Gen Goals.i7x – goals (automation) having to do with rituals
  • HL Game Locs.i7x – locations and scenery
  • HL Game Goals.i7x – goals (automation) having to do with game locations
  • HL Game Recipes.i7x – sheets of paper, texts on sheets, sparks, memories
  • HL Tutorial.i7x – tutorial state machine
  • HL Debug.i7x – debug commands

(Each of those files is divided into Chapters and Sections in the usual I7 way.)

That’s just how I logically divided things up. I could have made those nine sections into “Volumes” within a single gigantic I7 source file. But, as I said, I am comfortable in a multi-buffer text editor; I like being able to flip to a different file and find myself looking at the same point in that file that I left off. The I7 mechanism for narrowing and expanding sections is uncomfortable for me because, well, “because it doesn’t work like Emacs” is the honest nerdcore truth.

So I decided to split everything up into separate extensions, as listed above. I kept IDE open with the project (main file), and then kept all the .i7x files open in BBEdit. (BBEdit is close enough to Emacs and feels better to me when working in paragraph-formatted text.)

This had one enormous benefit for HL in particular. Before I started working on the game itself, I created a separate Inform project which included only the ritual magic elements. That is, it included HL Mechanism.i7x, HL Ritual.i7x, HL Gen Goals.i7x, but none of the game locations or scenery. All the magic components were just jumbled up in a test room. (Then there were some more test rooms with test fires, test swimming pools, test locked doors, and so on.)

This let me test the entire magic system separately from the complications of the game map.

5 Likes

“The Outline tab in the Inform IDE allows quickly jumping between headings”

I didn’t know I could do this. Wow, this is great. Okay, every thing gets a heading now!!! :slight_smile:

1 Like

Thanks for describing it. I remember you talking about the automated testing of the ritual stuff, maybe in your blog a ways back.

My own issue of wanting to test individual sections faster (without compiling the rest) is different to the overall topic of tech ways to divide up a source. I’m happy with my mega-source otherwise. I reckon I’ll have to keep pining for that newer computer.

-Wade