hallway8 / docs /ACT2.md
alvations's picture
Deploy Hallway 8 (multi-arc memory game)
93a3c54 verified
|
Raw
History Blame Contribute Delete
8.22 kB

Act 2: the interactions ("touch the room")

Act 1 is the memory loop: read the place, decide go on or turn back, eight correct calls escape, one wrong call resets. That never changes.

Act 2 is an optional layer on top: some details in the scene can be touched (a verb per detail), and touching them deepens the story and the dread without altering the win math. This document is the design of record. Read it before adding interaction content to an arc.

The one iron rule

Interactions never change the forward/back judgement. Correctness is still correct = (choice == "back") == has_anomaly, computed only when the player commits. Touching a detail can, very rarely, restart the run or end it in a wrong ending, but it never decides the go-on/turn-back call, and it never reveals whether the place changed. In almost every case touching changes nothing mechanical; the player then makes the normal call, and that call is go on as often as turn back. The interaction never tells you which. The one moment where "just turn back and ignore it" is the lesson is the false exit below, and that is made so rare it almost never happens.

The five outcomes of a touch

When a detail is touched, the server rolls one outcome (weighted by level, never by the detail's actual state, so it cannot be used as a detector):

  1. Flashback (common) — a fragment of backstory, then back to the loop. Free lore, no mechanical effect. Each fragment is collected: the client records its index and text, fills a dot on the Collectibles ledger, and lets the player recall its words later. Seeing every fragment in an arc earns a badge (see COLLECTION.md) — this is what turns the touch from inert flavour into a rewarded habit.
  2. Neutral reaction (common) — the world responds and tells you nothing (you wave, the camera swivels; you call out, the figure may turn). Happens whether or not the detail is the anomaly this loop.
  3. Red-herring reaction (common) — a false clue: a sensory detail that reads as evidence and is not (the poster is freshly printed, the seat is still warm). It appears on normal loops exactly as often as on changed ones, so it misleads as much as it "helps". Raises doubt, never resolves it.
  4. The fold (uncommon) — the place pulls you back to level 0. A self-inflicted reset, curiosity's price. More likely the deeper you are.
  5. The false exit (very rare, trigger-gated) — the run ends in a wrong ending, never a win. This is NOT a low-percentage roll on every touch: a "way out" dressed as salvation only appears on ~7% of loops around the three-quarter mark (levels 6-7), not near the finish, and it only fires if the player chooses to take it instead of turning back. Ignore it, which is the right move, and nothing happens. Most runs never see one.

Weighting (defaults; all tunable in one place in hallway.py). An ordinary touch rolls only flavour vs fold:

Level band flashback / neutral / red-herring fold (reset to 0)
L1–2 100% 0%
L3–5 ~90% ~10%
L6–8 ~85% ~15%

Levels 1–2 are pure, safe flavour: touching only ever gives a flashback or a reaction, so the player learns the verb without risk. From level 3 the different consequences become triggerable (the fold appears), rising to ~15% at the bottom: a deep sting, never frequent. Whatever the outcome, the touch is always optional, and in most cases the player just ignores it and commits forward or backward as normal.

The false exit is separate and gated, not a per-touch percentage:

  • it can only involve the one exit-capable detail per arc (Hallway's lit EXIT door, Stairway's shortcut landing door, Coach's carriage door onto a platform),
  • the "way out dressed as salvation" only appears at all on ~7% of loops around the three-quarter mark (levels 6–7), not near the finish (rare enough to stay a discovery across runs, common enough that a player who keeps playing will eventually meet one). The temptation should bite when the end is in sight but not imminent. It is visually distinct so taking it is always a deliberate choice, never a misclick,
  • even when it appears it does nothing unless the player chooses to take it; turning back or going on normally makes it evaporate.

Net effect: most runs never surface one, and most players who do surface one ignore it. It stays a whispered secret, not a resented punishment.

What the player sees

Only details actually shown this loop can be touched, so the available verbs rotate with the scene (usually one or two). Each is a quiet contextual control next to the loop, separate from the two commit buttons. Touching shows a short line; the player then still makes the normal go-on/turn-back call. A given detail can be touched once per loop.

Verbs are per-detail and themed, not always "open a door":

  • Hallway 8: try the maintenance door · wave at the camera · look closer at the poster · call out to the man in grey.
  • Coach 8: open the luggage · look out the window · read the scratched note · nudge the sleeping passenger.
  • Stairway 8: look out the landing window · read the scratches on the wall · grip the handrail · call down the stairwell.

The story Act 2 tells

The touches are the game's soul: they are the player's own memory, offering lore, a false way out, or a fold back to the start. The through-line (per arc) is that the player has done this walk before and the openings along it are not exits, they are memories of leaving that the place keeps open because an easy lie is more tempting than remembering why they are still here. See the per-arc interactions (flashbacks) and alt_endings (false exits) in the arc JSON for the concrete fragments and endings.

Content schema (per arc JSON)

"interactions": {
  "<prop>": {
    "verb": "try the door",            // the contextual control label
    "flashback": ["...", "..."],       // outcome pools; picked by the roll
    "reaction": ["...", "..."],        // neutral reactions
    "herring":  ["...", "..."],        // red-herring reactions
    "fold":     ["..."],               // flavour shown as the place folds you
    "exit": "break_room"               // OPTIONAL: this prop can be the rare
                                       // false exit -> alt_endings["break_room"]
  }
},
"alt_endings": {
  "break_room": ["...", "...", "..."]  // the wrong-ending screen text
}

Rules for content:

  • Keep flavour lines state-agnostic: they must read the same whether or not the prop is the anomaly (the server never passes the state in). This is what makes a touch un-cheatable.
  • Only give exit to a detail that can plausibly look like a way out (a door, a window, a platform), and only one or two per arc.
  • No em-dashes; no spoilers in the loop UI or intro (players discover the touch, and discover it changed nothing, on their own).

Keys and localization

The interaction strings get deterministic keys via i18n.arc_items:

  • a:<arc>|ix|<prop>|verb
  • a:<arc>|ix|<prop>|<kind>|<i> for kind in flashback / reaction / herring / fold
  • a:<arc>|end|<id>|<i> for the alternate endings

They localize through the normal pipeline (docs/LOCALIZATION.md) and fall back to English key by key until translated, so Act 2 can ship in English first and be localized after. They do not enter the level-composition QE gate (that composes only loop prose), so translate them with per-line QE when the time comes.

Server / client contract

  • The public room carries interactions: [{prop, verb}] for the shown, touchable props (no answer leak; interactability is static per prop, never a function of the anomaly).
  • POST /api/interact {prop} rolls an outcome and returns {kind, line, level, goal, ending?}. fold sets level 0; false exit returns the ending lines and resets progress for a fresh run. Neither reads or returns _has_anomaly. The commit endpoint /api/act is untouched.