Thirty Minutes to Sixty Hours
How the episode system got built three times before it worked
The opening scenario completed in thirty minutes. It was supposed to take several hours. The problem was not the writing.
The first version of act progression in Midnight Cargo was simple. Each act had a turn range. When the player reached turn five, Act 2 started. When they reached turn nine, Act 3 started. The logic was a few lines. It ran correctly. And it produced an experience where the game sprinted past every scene before the player had done anything meaningful in it.
Thirty minutes from opening screen to credits. That is not a session. That is a demo.
The First Rebuild: Objectives
The turn counter was the wrong signal. The right signal was whether the player had actually done the things the act was built around. So I replaced the turn ranges with objectives.
Each act in Midnight Cargo now has a set of required objectives. The act does not advance until those objectives are detected as complete. A player who spends ten turns examining crates and talking to dock workers before engaging with Thorgrim gets ten turns of that. A player who goes straight to the objective gets three. The act waits for the player, not the clock.
Detection runs in two stages. The first pass is keyword matching against the player's input and the narrative output. It is deterministic, costs nothing, and catches the obvious cases. When keyword matching is ambiguous, a second pass runs a lightweight AI validation call against the specific objective. The AI is checking intent against a defined list of outcomes, not deciding what counts. That distinction matters. The code decides when an objective is complete. The AI only helps read whether an ambiguous action was aimed at one.
The turn ranges did not disappear entirely. Each act has a minimum, an ideal, and a maximum. The minimum stops the system advancing before a player has had time to engage. The maximum is an emergency ceiling: if a player reaches it without completing objectives, the scene escalates to push them toward completion rather than waiting indefinitely. Guards arrive. A character gets urgent. Something happens. The game does not stall.
This was the right fix for act progression. It was not the only pacing problem.
The Second Problem: Sixty Minutes
Act progression controls the story structure. It does not control how long a session runs.
A D&D session at a real table does not run until the DM runs out of material. The DM reads the room, finds a natural moment, and calls it. The game needs to do the same thing, and it cannot read a room. So the episode pacing system uses two proxies: wall-clock time and turn count, whichever signals more urgency first.
Five phases, each injecting progressively firmer instructions into the narrative prompt.
Before fifty minutes, the narrator gets nothing about pacing. It runs normally. Between fifty and sixty minutes, it receives instructions to start looking for natural stopping points. Not to force one. To look. Between sixty and sixty-five, those instructions get firmer: complete the current scene, then steer toward rest. Between sixty-five and seventy, the instruction is to wrap the current action immediately. At seventy minutes, the system forces an end regardless.
The narrator handles this better than I expected. The "seeking" phase instructions produce genuine narrative behaviour: an NPC needing to leave, fatigue catching up with the party, a cliffhanger beat that lands at the right moment. The AI is not being told "the session is ending." It is being told "find a door." Most of the time it finds one.
When the pacing phases do not produce a natural break, the system has a deferral mechanism. It holds the episode end for up to four turns looking for a clean moment: not mid-combat, not mid-conversation, not on a transition. After four deferrals, it fires regardless. The deferral count resets each time a natural break is found.
When the episode end fires, the system generates metadata: an AI-written episode title, an end type (cliffhanger or resolution), and a teaser for the next episode. The title is generated in the background during the final pacing phase so it does not block the ending. The teaser references only threads the player has actually discovered during that session, so nothing is referenced that the player has not encountered.
The Third Problem: Enforcement
The pacing system worked. The episode end fired correctly. The metadata was generated. The signal went out.
The game kept going.
The episode end was a single event on a single API response. If the frontend missed it, for any reason, the signal was gone. Every subsequent action was processed as a normal turn because the server checked whether to fire the episode end, not whether it had already fired. The flag that marked the episode as ended only blocked the end-detection logic from running again. It did not block the turn pipeline.
The fix is not complicated. The server now checks on every request whether the episode has already ended. If it has, it returns the episode summary data rather than processing the action. The frontend receives the signal on every subsequent request until it acts on it. The episode cannot run past its boundary because the boundary is enforced at the server, not signalled once and forgotten.
What the End Screen Does
When an episode ends, the game shows a three-phase sequence before returning the player to the hub.
The narrator writes a closing beat first: the scene landing, the door found, the moment of breath before the next episode starts. Then the episode title fades in over a blurred version of the game screen, with the arc context beneath it and the end type treatment: cliffhanger gets one framing, resolution gets another. Then a card with the AI-generated teaser for the next episode, the companion roster, and a single button to continue.
The player cannot keep playing from this screen. There is no "resume" option, no way to slip back into the session. The episode is over. The hub is next.
This is the part that took the most deliberate thought. The temptation is to make it easy to keep going: a "continue" button that starts the next episode immediately, an option to extend the current one. The episode structure only works if the boundary is real. A session that can be extended indefinitely on request is not a session. It is a session with extra steps.
The Chronicle Book is downstream of this. At the end of the campaign, every episode title, every closing beat, every AI-generated teaser compiles into a formatted narrative the player can order as a printed book. That output only makes sense if each episode was actually an episode, with a shape and a name and an ending that happened at a defined moment. The boundary is not a restriction. It is the thing that makes the rest possible.
The Current State
The objective tracker runs on all six acts of Midnight Cargo. The pacing system runs across all five phases. The episode end enforcement is in place. The end screen is built and wired.
What is not built yet is the full campaign arc above the episode level: the arc structure that groups episodes into named chapters, the Director AI content that populates the episodes after the opening scenario ends, the post-opening thread system that carries consequences forward. Those are the next layer. The episode is the unit they are built from.
The thirty-minute problem is fixed. The session runs until the story finds a door, and the door closes behind it.