The Almanac Mechanic
This is the whole game, mechanically. If I only get one system right, it's this one.
The core idea: state is what Wren has noticed
Most narrative games model state as variables — met_silas = true, tide_count = 3, saw_the_wreck = false. A little pile of flags the writer has to remember and keep consistent. I did it that way for the first six months and it nearly killed the project (I had forty-one booleans and a branching structure I could no longer hold in my head).
The reframe that unblocked everything: don't model state as variables. Model it as what Wren has noticed. There is exactly one piece of state in this game — the almanac — and it is a growing list of things Wren has recorded. Every scene reads that list. Nothing else exists.
This is Pillar 3 (see Design Pillars): the almanac is the save file. Not "the almanac reflects the save file." Is. The save file is the serialized list of noticed things. Load a save, you're loading Wren's book back into her hands.
Entries are "knots"
Each recordable observation is a knot. I call them that for two reasons and I like that they're both true:
- In Ink, a "knot" is already the word for a passage of content. The language agreed with me before I asked it to.
- It's the older meaning — the knot you tie in a string so you won't forget. A quipu. A net. A thing held by being tied.
A knot is the atomic unit of attention in this game. Kneeling at a pool and really looking ties a knot. Walking past unties nothing, because nothing was there — the absence of a knot is a real, legible game state (it means Wren never saw it, and scenes can respond to that).
How it reads (pseudo-Ink)
The architecture, roughly. Entries is the universe of noticeable things; almanac is what's actually been written down (starts empty — Wren has noticed nothing).
// every noticeable thing in the world is a possible entry
LIST Entries = bishops_bead, oxblood_dulse, bonewrack, silas_boat_gone,
the_west_lamp_dark, the_soft_page, first_frost
// THE game state. Wren's book. Starts empty. This is the save file.
VAR almanac = ()
=== function note(x) ===
// the ONLY way state changes: Wren writes something down
~ almanac += x
=== function noticed(x) ===
// scenes never check flags — they ask the book
~ return almanac ? x
=== tidepool_west ===
{ noticed(bishops_bead):
The bishop's-bead has closed to a red bead again — same as the page
you wrote in the spring set. You know this one now.
- else:
Something red in the crevice, folded shut against the air. You could
kneel, or you could keep to the path and the failing light.
}
* [Kneel and look] { note(bishops_bead) } -> tidepool_west
* [Keep walking] -> the_low_path
Note what's not there: no if first_visit, no visit counters, no boolean soup. The scene asks the almanac one question — has Wren noticed this? — and the answer is the whole branch. Recording is the single verb that mutates state.
first pass at the recto/verso layout — world on the left, the open book on the right, and the knot you just tied sliding into the page
Save/load falls out for free
Because state is one list, saving is serialize(almanac) and loading is restoring it. There's no second bucket of variables to keep in sync — and that's not a convenience, it's the design. The moment I had a tide_count VAR living outside the almanac, saves desynced (see Devlog, the day I ripped it out). The pillar paid rent: if it isn't a knot in the book, it doesn't get to be state.
The refactor that unblocked me (~day 340)
For the record, because I'll forget: the switch from 41 booleans → one LIST + note()/noticed() was the single change that turned this from a stalled prototype into a game I could actually keep building. I wrote it up as a tip once — stop modeling state as variables, model it as what Wren has noticed; the almanac IS the save file — and it's the most useful thing I've ever said about my own project. The mechanic and the theme became the same sentence, and after that I mostly just had to not screw it up.
A save file that is also a diary that is also a net you drag through a disappearing place. It shouldn't have taken me six months. It took me six months.