hallway8 / docs /ARCS.md
alvations's picture
Deploy Hallway 8 (multi-arc memory game)
58e1249 verified
|
Raw
History Blame Contribute Delete
18.2 kB

Arc roadmap

This is the living plan for the game's arcs (skins/backstories). It records the design rules every arc must follow, what's already built, and the queue of future arcs so we can pick up any of them later without re-deriving the idea.

Each arc is one self-contained data/arcs/<id>.json file plus a body[data-skin="<name>"] block in static/style.css. See the README section Adding an arc for the file schema. New arcs appear on the opening screen automatically.


Design rules (apply to every arc)

The mechanic is fixed: move through a place that should be identical each loop; turn back if something changed, go on if nothing did; eight correct calls in a row wins, one wrong call resets. What differs per arc is the story, vocabulary, skin β€” and the flavour of the anomalies. Every arc must include:

  1. A strong motivation ("the hook"). A concrete in-world reason you're stuck doing this, revealed in the intro β€” the equivalent of Stairway 8's out-of-order elevator. Never "you are being tested" with no diegetic cause.
  2. An NPC. A recurring character that is normally passive but can become the anomaly β€” turning, watching, approaching, vanishing, duplicating. Every arc needs its own recurring uncanny figure.
  3. A loop-aware NPC twist. At least one NPC anomaly that breaks past physical change into the uncanny: the character acknowledges you or the loop itself (waves, beckons, mouths/says "again"). Property key convention: knows for silent figures, speaks for ones that can talk.
  4. A psychological layer (sense). A non-physical property whose baseline is your ordinary state and whose anomalies are perceptual/emotional wrongness β€” losing count, a calm that shouldn't be there, a conviction you're going the wrong way. Anomalies beyond objects, per the "twists" requirement.
  5. Meta drift (free). The engine already drifts the heading, wording, pacing, weight, spacing and background every loop β€” no per-arc work needed, but keep title_variants themed.
  6. Win-screen strings (in meta). Three short, arc-flavoured lines the exit screen needs, so the reward matches the place:
    • share_prompt β€” the invitation above the share row, phrased for this arc's exit (Hallway: Leave the door open., Stairway: Leave the door open below., Coach: Hold the doors.).
    • attempt β€” the "look back" line shown when the run took more than one try. Must contain the {n} placeholder (the run count), spliced in front so it localizes cleanly, e.g. {n} times down this corridor, and this time it opened.
    • attempt_first β€” the line for a clean first run (no placeholder), a small reward for a flawless escape, e.g. First time through, and the corridor let you go.

Keep anomalies plausible, never loud. One property mutates per anomalous loop, and it is always among the details shown that loop (the engine guarantees this).


Shared tuning (all arcs inherit this β€” do not re-tune per arc)

These curves are engine-wide, not per-arc. A new arc gets them for free; only change them if you intend to change the feel of every arc.

Difficulty ramp β€” hallway.py

The chance a loop contains an anomaly is a function of the player's level, so the first stage after entering leans toward "nothing changed" (learn the baseline by proceeding) and gets harder as you descend/advance:

anomaly_chance(level) = min(ANOMALY_MAX, ANOMALY_BASE + ANOMALY_STEP * level)
ANOMALY_BASE = 0.02   # level 0: VERY low, no baseline seen yet
ANOMALY_STEP = 0.076  # per level cleared (steep, to reach the cap by ~L7)
ANOMALY_MAX  = 0.55   # capped so "always turn back" never wins

So the opening loop (level 0) is only ~2% (easy 1%, hard 3%), rising steeply to the cap by around level 7 (normal 55%, easy 30%, hard 60%). The very-low opening is deliberate: on your first loop you have no baseline, so being turned back would be a coin flip you cannot win. It is not zero (a rare early jolt keeps the place honest). Level resets to 0 on a wrong call, which re-eases the first stage, intentional re-onboarding, not a bug. There is no level-0 floor (the low opening is the point; levels 1+ ramp well clear of zero so "always continue" still loses). Because content is shown fairly (the mutated property is always among the details displayed), the ramp changes frequency, never fairness. Guard: keep ANOMALY_MAX ≀ ~0.55 or turning back becomes dominant.

Aggro-item / late reveal (hallway.py)

Each arc's meta.late_props names a couple of small, inconspicuous properties (existing details, not new ones). Once per climb, build() may hold some out of the early loops so they first surface mid-run. mem.held maps each held prop to its reveal level:

reveal level ∈ [2, GOAL-2]   # ~level 2-6 at goal 8, never the last
hold: hard  β†’ always, 1 or 2 items (the "not everything up front" pressure)
      normal β†’ rare (~15%), a single item; rotation is the everyday replay hook
      easy  β†’ never

Holding 1-2 items reliably is a hard-mode feature. Normal mode leans on the ordinary fact that only 4-6 of ~9 details show each loop (and Act 2 touch outcomes vary), so a normal player meets almost every encounter over a few runs without ever being deliberately starved. Not showing everything every run is a core principle and the replay hook.

Fairness guard (mem.seen_props): an anomaly may only land on a detail the player has already seen at baseline on an earlier loop, so the held item is never the change on the loop it first appears. Its debut is always a calm baseline; only later can it move. This keeps a late arrival a memory test, never pure luck, even at the last level (by then it is long established). Pick late_props that are genuinely minor (a fixture, a small object), never the NPC or the sense.

Doubt prompt curve β€” static/game.js

The confidence prompt is not shown every turn. After a Go-on/Turn-back choice, the chance it interrupts grows as you near the exit:

chance = min(0.85, 0.12 + level * (0.7 / goal))     # ~12% early β†’ ~73% at level 7
  • Certain / Almost sure (conf β‰₯ 3) β†’ the choice commits and is judged.
  • Guessing / I think so (conf ≀ 2) β†’ does not commit; returns you to the scene for exactly one re-decide (the hesitated flag blocks a second prompt that turn). The re-look is the only "reward" β€” no points, no safety net.

This is pure client-side UX: confidence never enters the server's correctness formula (correct = (choice == "back") == has_anomaly). New arcs need no work to inherit it.

Session state β€” app.py

State is keyed by a client-echoed sid (X-Sid header), not the session cookie, so an arc and its progress survive in a cross-site iframe (Spaces). Arcs never need to touch this.

Win screen & sharing β€” engine-wide

The exit screen is shared by every arc; an arc only fills in the three meta strings above. The engine handles the rest:

  • Look back (fleeting run count). A quiet toggle under "You're out." surfaces the arc's attempt / attempt_first line, then fades after a few seconds and reclaims its space so the eye settles on sharing or replaying. The run count is a per-session counter in PlayerMemory (attempts, resets + 1), and the line is localized server-side like win text.
  • Sharing. One of eight cryptic "invitation" lines (shared UI strings share_1..8) is chosen at random, with the arc's share_prompt above it. Mobile-first: where a native share sheet exists it is the single button (it reaches Instagram, Snapchat, X, Messages, everything); otherwise explicit X / Facebook / LinkedIn links plus Copy link. The shared URL unfurls as the game's own "8" Open Graph card (static/img/og.png).

New arcs inherit all of this for free once the three meta strings are set.


Built

These three are the only production arcs for the current phase. Everything in "Planned", "Backlog", and "Brainstorm" below is idea-stage only β€” keep it out of the live 3-arc game until an idea is deliberately promoted up into this table.

Arc Hook Loop unit NPC (+ twist) sense anomalies Skin
Hallway 8 (hallway-eight) Locked in after hours; a sign points to the fire exit corridor man in grey suit (knows: turns/beckons/"again") longer, forget, calm cold teal
Stairway 8 (stairway8) Elevator out of order; descend on foot landing figure on the stairs below (knows: looks up, waves, ascends) deeper, forget, wrong-way emergency green
Coach 8 (coach8) Conductor sent you to coach 8; the train never reaches it carriage sleeping passenger (speaks: murmurs "again", "you were just here") forget, calm, watched cabin amber

Planned (not yet built)

Each entry is enough to implement directly. Ordered by how strong/fresh the loop feels; pick any.

Platform 8 (platform8) β€” the underpass

  • Hook: last train of the night; the turnstiles are shut and a sign routes you through the pedestrian underpass β€” FOLLOW SIGNS TO PLATFORM 8.
  • Loop unit: identical tiled underpass segments. Go on = walk on / Turn back = double back.
  • NPC: a busker sitting against the wall with an open case. Twist (knows): stops playing to watch you; case is suddenly empty/overfull; plays the same bar as you pass "again."
  • Physical anomalies: tiled advert, the drip-puddle, map's "YOU ARE HERE" dot, poster date, platform number on the sign, tile colour, a pigeon.
  • sense: the tunnel feels longer; you forget which platform you wanted; a certainty you already caught the train.
  • Skin: cold blue-white station tile (--hue: 205).

Aisle 8 (aisle8) β€” locked in the supermarket

  • Hook: you looked up and the shop had closed around you; the tannoy loops "please proceed to checkout 8 to exit."
  • Loop unit: identical grocery aisles. Go on = next aisle / Turn back = previous aisle.
  • NPC: a night-shift stocker with a trolley, back to you. Twist (knows): turns and stares; trolley abandoned mid-aisle; softly says "again" over the muzak.
  • Physical anomalies: a shelf gap, a product facing the wrong way, a price label, the end-cap promo, the muzak track, the abandoned trolley, floor sheen.
  • sense: the aisle feels longer; you forget your list; a calm certainty you've already paid.
  • Skin: flat retail fluorescent, a touch too bright (--hue: 60, high L).

Ward 8 (ward8) β€” the hospital at night

  • Hook: visiting hours are over; the night sign says the way out is via Ward
    1. (Handle tone with care β€” dread, not gore.)
  • Loop unit: identical hospital corridors. Go on / Turn back.
  • NPC: a patient in a gown standing in a doorway, or a nurse at the far station. Twist (knows): the figure has moved to the next doorway; is facing you; mouths "again."
  • Physical anomalies: a gurney's position, the room-number plate, a flickering "NIL BY MOUTH" sign, the hand-gel dispenser, a chart on a door, distant monitor beeps, a wheelchair.
  • sense: the corridor feels longer; you forget why you came; a wrong calm.
  • Skin: pale clinical green-grey (--hue: 160, low sat).

Level 8 (level8) β€” the underground car park

  • Hook: your ticket says Level 8; the lift to the street is dead, so follow the ramp up. (Ascending mirror of Stairway 8.)
  • Loop unit: identical parking rows. Go on = up a ramp / Turn back = back down.
  • NPC: a figure between the parked cars, or someone sitting in a driver's seat. Twist (knows): the seated figure's headlights flick on as you pass; it has moved cars; it waves.
  • Physical anomalies: a parked car's colour, the level number on the pillar, a flickering strip light, the arrow painted on the floor, an oil stain, a distant engine, a car alarm.
  • sense: the level feels deeper; you forget where you parked; certainty you're descending, not climbing.
  • Skin: concrete grey with sodium-orange pools (--hue: 30, low L).

Gate 8 (gate8) β€” the airport after the last flight

  • Hook: you dozed off; the terminal's near-empty and the board shows one route left β€” EXIT VIA GATE 8.
  • Loop unit: identical concourse stretches / travelators. Go on / Turn back.
  • NPC: a lone cleaner with a floor-buffer, or a single seated passenger. Twist (knows): stops buffing to watch; the seated passenger is gone/closer; a gate announcement says your name.
  • Physical anomalies: the gate number, a departures-board row, the duty-free window display, an abandoned bag (unsettling), the announcement chime, a clock, a potted plant.
  • sense: the concourse feels longer; you forget your destination; a calm that you've already boarded.
  • Skin: glassy blue night-terminal (--hue: 215).

Backlog ideas (thin β€” flesh out before building)

  • Museum after close β€” galleries loop; NPC is a security guard or a statue that isn't always in the same pose.
  • Motel corridor β€” reach room 8 / the exit; NPC is someone at an ice machine.
  • Ferry decks β€” climb decks to the exit; NPC a lone smoker at the rail; motion + sea outside the windows.

Brainstorm β€” later phases (idea-stage, NOT production)

Fresh settings that complement the transit/civic bias of the Planned queue: a knowledge space, a money/dread space, a modern-tech space, a sacred space, and a play-gone-wrong space β€” five different emotional registers, still melancholy rather than violent. Each satisfies the design rules (hook, loop unit, NPC with a loop-aware twist, physical anomalies, a sense property). Suggested skin hues are candidates only; whichever get built must stay visually distinct from the live blue/amber/green and from each other.

Stacks 8 (stacks8) β€” the library at lockup

  • Hook: the lights dropped to night mode while you read; a card says the way out is past Aisle 8 of the stacks.
  • Loop unit: identical rows of tall shelving. Go on = next aisle / Turn back.
  • NPC: a night librarian re-shelving from a trolley, back to you. Twist (knows): stops, turns to watch, mouths "again". Or a reader asleep at a carrel (speaks: "you already returned it").
  • Physical anomalies: a book's spine title, a shelf gap, a volume shelved upside-down or backwards, the aisle-number sign, a reading lamp on/off, the step-stool moved.
  • sense: the aisle feels longer; you forget which book you came for; a wrong calm that you've already checked out.
  • Skin: violet dusk through high windows (--hue: ~275). Books are an unusually strong anomaly engine β€” probably the richest of these five.

Vault 8 (vault8) β€” the bank vault, timelock running down

  • Hook: your safe-deposit box is in aisle 8; the outer door is on a timelock that reopens at dawn, so keep going.
  • Loop unit: identical corridors of numbered brass boxes. Go on / Turn back.
  • NPC: a night guard on his rounds (knows: stops, watches, nearer) or a customer at an open box who won't leave (speaks: "you were just here").
  • Physical anomalies: a box number, a box door ajar, a dropped key on the runner, the timelock clock's hands, the carpet runner's colour, a convex security mirror's angle.
  • sense: the vault feels deeper; you forget your box number; a calm that you've already emptied it; wrong-way.
  • Skin: crimson carpet + burnished brass (--hue: ~350).

Data Hall 8 (datahall8) β€” the data-centre cold aisle at 3am

  • Hook: the badge reader sent you to Hall 8 to reseat a server; the lift back is locked to your card, so walk the aisle.
  • Loop unit: identical rows of caged server racks. Go on / Turn back.
  • NPC: a lone technician with a laptop cart far down the aisle (knows: turns, watches, closer) β€” very modern loneliness.
  • Physical anomalies: a rack's blinking-LED count, a cage door ajar, a coiled cable on the floor, a KVM screen showing your own login, a warm aisle where it should be cold, the hum's pitch.
  • sense: the hall feels longer; you forget which rack; the hum stops (a diegetic "wrong silence"); a wrong calm.
  • Skin: indigo LED wash (--hue: ~265). The only contemporary/tech setting.

Cloister 8 (cloister8) β€” the abbey at night

  • Hook: locked in after the last visitors; complete the eighth circuit of the cloister to reach the chapel door.
  • Loop unit: identical vaulted arcades around a dark garth. Go on / Turn back.
  • NPC: a cowled figure with a taper at the far arcade (knows: turns, raises a hand, nearer each loop, mouths "again").
  • Physical anomalies: a wall sconce lit/dark, a carved boss or gargoyle, a statue's pose out in the garth, a grave-slab inscription underfoot, the bell (tolls once too many), a stained-glass panel.
  • sense: the walk feels longer; you forget which office you came to pray; a wrong serenity; wrong-way (the cloister circles anticlockwise now).
  • Skin: candle-lit stone, very low saturation warm grey (--hue: ~35, desaturated so it reads neutral, not Coach's amber).

Midway 8 (midway8) β€” the shuttered funfair

  • Hook: you stayed past closing; the only lit exit sign is down the midway, past booth 8.
  • Loop unit: identical stretches of game stalls and strung bulbs. Go on / Turn back.
  • NPC: a costumed mascot standing dead still by a stall. Twist (knows): it has turned to face you; it's closer; its head is tilted. (Unsettling without gore.)
  • Physical anomalies: a prize wall, a strung bulb dark/lit, a carousel horse's position, a ticket-booth number, the calliope music (loops backward), a balloon snagged on a wire.
  • sense: the midway feels longer; you forget which ride you were heading to; a wrong festive calm; wrong-way.
  • Skin: faded pink-and-gold neon (--hue: ~320).