Generally felt unmotivated and without a lot of creative juice. I still got a lot done, through effort rather than inspiration, though somewhat less of it was narrative, and more of it was code.
Almost all of the code work this week happened in the story-compiler.
You see, I had this epiphany – which I should have had quite a lot sooner.
In its early iterations, the Argus engine loaded its data from a simple text file, parsing the whole lot into the proper internal representations.
Later on, the story-compiler was added, which bundled game-assets and the story file into preprocessed blobs.
That gave me some freedom to perform laborious sanity-checking in the story-compiler instead of in the engine. I’ve progressively moved a number of time-consuming tasks from Argus’ runtime engine to its story-compiler.
And yet, even then, I still didn’t quite get it. Must have gotten a bit rusty.
Having that compiler/preprocessor tool means that the source-text that the author produces and the data that the runtime engine soaks up are far less strongly-coupled.
I don’t actually have to maintain the same syntax, or have statements/expressions that are isomorphic between the two. As long as I can turn what we get into what the runtime engine needs, then I can allow whatever directives/expressions that make things easier for the author.
Since source file/line numbers are preserved, I can tag any internally generated statements with the file/line of the command that was responsible for their production – just in case a runtime-error actually does happen, and you need to know where that came from.
Accordingly, the system got some minor, but very useful, syntactical overhauls.
The prototype was for setting/clearing flags on characters – one of the earliest tasks I had, which later got folded into the master knowledge-representation map.
The syntax for this was pretty clunky, and could only take one flag at a time.
Now I have a new syntax that takes a list of flagnames (plain for flags that are set, or prefixed with an exclamation mark for flags that are being cleared), and is just plain easier to read than the old syntax. It makes as many original-syntax statements internally as needed to do the job.
I’ve also tacked on role-aliases. Or at least, the first cut of them.
Remember Alice, Bob, and Christine from week 32’s example?
Scene 101 Meta Summary: Alice and Bob give Christine a lift to the next town. Arc:The Mysterious Hitchhiker Follows:100 Roles Flagged:1,Alice,Bob;car-keys // Whoever currently has the car-keys is driving Flagged:2,Alice,Bob;!car-keys // The other one is the passenger Fixed:3,Christine Fixed:4,Alice Fixed:5,Bob Requirements None Performance ...
Let’s add some role-aliases to that.
Scene 101 Meta Summary: Alice and Bob give Christine a lift to the next town. Arc:The Mysterious Hitchhiker Follows:100 Roles Flagged:1,Alice,Bob;car-keys [driver] Flagged:2,Alice,Bob;!car-keys [passenger] Fixed:3,Christine [c] Fixed:4,Alice [a] Fixed:5,Bob [b] Requirements None Performance ...
So, now instead of referring to everyone by their numeric roles during the scene, the author can refer to them by the friendlier textual-alias that they’ve provided for that role.
Well, for now, that’s limited to narrative targets and speech-enactors, but I’m sure I can extend that significantly.
As an experiment, I added an option to the Argus story-compiler to output a file for Twine, containing a list of all of the scenes, their connections and populating each scene with the provided meta-data summary.
I thought it might make a handy visualisation tool for overall scene-structure.
Okay, not so much, then.
The problem here is that I’ve not sensibly positioned each scene node. But to be fair, I’ve put fairly little effort into it, just calculating an x/y position from the scene id. You can see how poorly that works out. Since I’m using scene-ids for clustering and grouping narratively-related scenes doing it this way almost perfectly erases any visible narrative structure.
Work on this chapter has started out pretty well. It needed some underlying technological support to make it work, but work it does, and like a charm, at that.
Eight (of the eleven) playable characters get presented with a slew of choices each, narrative preambles are presented, vignettes chained together, narrative postcripts executed, and then the story continues – all as seamless as the author wants it to be.
It’s a combination of parameterised macros in the story-compiler, a bit of using scenes as subroutines, and a new scene meta-flag that forces scenes to be marked as complete (and discarded from the pending queue) if their casting conditions are unsatisfiable.
This covers a fair bit of the tech I need for some of the more advanced arc-management planned for – well, probably by chapter 3. There’s still a few more items that have to be designed to handle the evaluation and scheduling of story arcs.
The good part is that it all worked very well and very smoothly. Breaking narrative up into smaller bites and scenes makes a real difference, and makes it a lot easier to account for the multiple variations within scenes. Speaking of variations…
The combinatorics mount up quickly. There’s ~4 trillion combinations of choices, currently.
I need another coffee, and to think this through.
Okay, yeah. That’s actually the right number.
The good bit is that – as the author – you don’t have to think about that too much, if you structure the story properly. Not many scenes actually have invariant content – that is, scenes where the narrative text always comes out the same way.
Instead, the majority of scenes wind up having between about two and ten internal variations, but the underlying system makes it easy to handle that sort of thing.
In some cases, scenes require entirely alternate versions (like the plot twist at the end of the demo, or some of the scenes that follow on from that), but that seems to be a bit rarer. In most cases we can handle variation by branching within scenes rather than branching to alternate scenes.
Even so, not every choice combination ends up creating a unique narrative for every playable character, thankfully. Some choices are far-reaching, and others less so, but choices have both short-term and long-term consequences, and the important thing is that they matter to your character’s narrative.
Today I’m planning out some more of the early vignettes in Chapter two, working on another plot twist that appears (properly foreshadowed, of course, but it will still be quite a surprise), and getting geared up to do more writing and less coding this week.
There’s still a lot of ground to cover.