haxtory/STAGES.md
type-two ffd58fcebc STAGES.md — per-hop direction briefs
One page per hop: what is built, what is thin, what I would add ranked,
and a DIRECTION block to write into. Plus a cross-cutting table for
directing by system instead of by stage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 15:50:38 +10:00

17 KiB
Raw Blame History

HANDSHAKE — stage briefs

One page per hop. What's built, what's thin, what I'd add, ranked. Write your direction under DIRECTION and I'll build to it.

Current state: 13 playable hops, ~5,400 lines, all clean. Each hop is currently 24 minutes of content. The design doc calls for 520. The genres, mechanics and set pieces are all in — the duration isn't. That's the gap this document is for.

Repo: ssh://git@100.71.119.27:222/monster/haxtory.git · run: python3 serve.py 8123

Global rule I'm working to: nothing gets added that doesn't earn its minutes. A longer level is not a better level; a level with a second idea in it is.


1 · COLD BOOT — src/levels/coldboot.js

hop 1 · first person · ~90 s · v.90

In: 512-slot NIC ring buffer, instanced packets breathing in their slots, HEAD and TAIL pointers circling, six lines of script establishing what you are, then the DMA fires and rips the camera out at 1400 units/sec into the title card.

Thin: it's a corridor with narration. You can walk but there's nothing to walk to. The "you have left your slot" beat is the only interaction.

What I'd add, ranked

  1. The tail pointer as a threat you can see coming. It's already circling. Make it actually reach you — a slow, unhurried countdown of the ring, so the DMA feels like something that arrived rather than something scheduled.
  2. One other packet who talks. A neighbour in the next slot who has been transmitted before and come back. Three lines. Sets up FIN at hop 9.
  3. The descriptor you can read. Walk to the slot wall, press E, see your own header laid out — seq number, window size, flags. Establishes the SYN/ACK vocabulary the ending depends on.

DIRECTION:

_


2 · THE STACK — src/levels/stack.js

hops 28 · third-person platformer · ~5 min · v.90

In: seven descending layers, one per OSI layer, each shedding a header shell. NX floors you fall through, rate-limit gates on a real 1.2 s cycle, canaries that scream, ASLR reshuffling the NETWORK layer on every death, CSMA/CD platforms flickering on DATA LINK, and the stateful FIREWALL boss where the solution is to make it send something outbound and arrive as the reply.

Thin: seven platforms per layer generated from one rule, so all seven layers play the same. The hazards are one-note — you meet each idea once.

What I'd add, ranked

  1. Give each layer its own verb, not just its own hazard. PRESENTATION should be about encoding (platforms that only exist in one representation), SESSION about state (platforms that remember whether you've been on them). Right now they're all "jump accurately, but with a different colour of danger".
  2. Make the firewall a three-stage fight. It currently has one idea. Stage 2: it starts blocking the pad. Stage 3: it inspects the reply and you have to make the outbound packet look like the thing you want to be answering.
  3. Vertical shortcuts. Skipping a layer should be possible, hard, and cost you the header you'd have shed — so you arrive at the bottom still wearing TLS and the copper levels behave differently.
  4. The canaries should be worth waking. Right now they're pure punishment. Make one of them guard something.

DIRECTION:

_


3 · TIME_WAIT — src/levels/timewait.js

hop 9 · walking sim · ~2 min · v.32bis

In: the beige room. Plastic chairs, 50 Hz strip-light hum synthesised from actual 50/100/150 Hz, a wall clock doing a real two-minute lap, six seated half-open connections with three lines each, and FIN by the door with nine.

Thin: it's the shortest emotionally-load-bearing level in the game. Six NPCs is not a room. And FIN's nine lines fire on a single E-mash.

What I'd add, ranked

  1. More people, fewer words each. Twelve to sixteen seated, one or two lines apiece, most of them not about you. A waiting room is oppressive because of volume, not depth.
  2. Someone leaves while you're in there. A connection ages out — quietly, mid-sentence, no ceremony. Nobody reacts. That's the level's thesis in one event.
  3. The clock should matter. Two minutes is MSL. If the player stays a full lap, something happens. If they leave in twenty seconds, they never know it would have.
  4. FIN should refuse to talk if you rush him. Approach and mash E and he says "you're not listening". Come back after you've talked to three others and he opens up.

DIRECTION:

_


4 · THE WAR — src/levels/war.js

hops 1016 · top-down twin-stick · ~3 min · 9600

In: #2600 on EFnet. Sixteen nicks milling and saying things, the op wearing a crown and chasing you to kick you, ten seconds of telegraphed lag, the netsplit, the ghost crown on the empty side, and the rejoin that makes it real. Sub7 body-snatch on the bots.

Thin: two successful split-rides and it's over. The Sub7 possession has no purpose — you take somebody over and then there's nothing to do with them.

What I'd add, ranked

  1. Give possession a point. A possessed client can go where you can't — through a ban, into a +i channel, onto the other side of a split you didn't reach in time.
  2. The trojan arms race. The design doc's best unused idea: every weapon you use gets patched by the level ninety seconds after you first use it. Forces you through four different tactics in one level.
  3. DCC send. Somebody offers you a file. It is obviously a trap. Taking it should do something genuinely bad and genuinely funny.
  4. A second channel. #phreak next door, different rules, and the war is actually over which one the population ends up in.

DIRECTION:

_


5 · SMASHING THE STACK — src/levels/smash.js

hops 1720 · 2D side-scroll · ~3 min · 9600

In: one char buf[64] you walk right along, the canary value on a ledge, the canary bird at the boundary, four return-address bytes you write little-endian by standing on them in order, a 40-tile NOP sled you slide down, shellcode at the end, and Aleph One chain-smoking at the start.

Thin: ret2libc is described in the design doc and isn't in. The level is one straight line — no reason to ever go back.

What I'd add, ranked

  1. ret2libc as a real second route. NX turns on halfway, the sled stops working, and you have to build a bridge out of the ends of other people's platforms — the gadget chain as physical scaffolding. This is the best unbuilt thing in the whole game.
  2. Make the address matter. Right now any four bytes work because they're prewritten. Let the player choose an address and have the level jump there — including to the wrong places, with consequences.
  3. A second buffer. Off-by-one instead of a stampede: one byte over, into the low byte of the saved pointer. Much harder, much more satisfying.
  4. Aleph One should say more than one line. He's the mentor and he's got four words.

DIRECTION:

_


6 · THE WORM — src/levels/worm.js

hops 2128 · RTS · ~3 min · 9600

In: 60 ARPAnet hosts on a graph with real names, three vectors (fingerd overflow, sendmail DEBUG, rsh trust) with different reach and rate, load accumulating per host, hosts dying at load 7, links dying with them, and the 1-in-7 reinfection locked on and displayed and unchangeable.

Thin: you pick a vector and watch. The only input is 1/2/3.

What I'd add, ranked

  1. Let the player try to stop it. The historical thing is that Morris tried. Give them a kill-switch that doesn't work, or works on one host at a time while the spread outruns them. Futility you can operate is much worse than futility you watch.
  2. Named hosts that fall over. When mit-ai dies, say so. Sixty anonymous dots dying reads as a bar chart; six named machines dying reads as damage.
  3. The phone calls. The real event had people ringing each other all night. A line every twenty seconds from someone at a dying site.
  4. A win condition that is worse. Spread to everything before anything dies — it should be possible, and it should require playing so cautiously that you feel the restraint the worm didn't have.

DIRECTION:

_


7 · THE CUCKOO'S EGG — src/levels/cuckoo.js

hops 2934 · terminal stealth · ~3 min · 1200

In: LBL VAX 11/780, logged in as sventek. A filesystem with six real documents, ls/cd/cat/who/ps, and a "lines still being watched" bar that decays on real elapsed connect time. The SDINET bait file costs you a third of your margin for reading it. You get caught; the only variable is what you got first.

Thin: six files and five commands. The tension is a timer, not a decision.

What I'd add, ranked

  1. Make him visible in ps. He's already in there as a joke. Let the player actually watch his processes change — cat /dev/tty01 > /dev/lp0 appearing on your line is the moment the level turns.
  2. Choices that trade time for cover. Clearing logs costs 40 seconds and buys you 10 lines. Reading a file costs time and gains a phile. Right now everything is free except reading.
  3. More filesystem. The pleasure is poking around. Twenty files, most of them boring on purpose, three that matter.
  4. The Hannover number. It's mentioned in roster.txt and goes nowhere. It should go somewhere — even if where it goes is the blue box level, forty hops later.

DIRECTION:

_


8 · THE BOARD — src/levels/board.js

hops 3544 · terminal · ~8 min · whatever you earned

In: the heart, and the most finished level. Busy signal on the first dial, ANSI logo painting at baud/10 characters a second, six message-base messages, five files with a real 1:3 ratio, the ANSI bomb that actually remaps your movement keys, the sysop breaking into chat and telling you he can see you typing, the NUP gate, the elite sub-board that tells you how to leave, FidoNet's overnight run, and a playable LORD in the corner.

Thin: LORD is one fight. Trade Wars is a joke that's closed. The message base is read-only.

What I'd add, ranked

  1. Let the player post. A message base you can only read is a museum. Posting, getting replied to on the next visit, and having the sysop react is the entire social loop of the era.
  2. Come back tomorrow, properly. The FidoNet run already sets this up. Make the board a place you return to across three separate hops with different content each time — that's the mechanic nobody has put in a game.
  3. Finish Trade Wars. A sector map, a trade route, a Ferrengi. It's the second-best joke in the game if it's real and the worst if it isn't.
  4. More messages. Six is a board with nobody on it. Twenty, most of them arguments.
  5. Leeching consequences. The ratio_cop message threatens to leech your account down. It should happen.

DIRECTION:

_


9 · THE HANDSHAKE — src/levels/handshake.js

hops 4550 · rhythm boss rush · ~6 min · sets your baud

In: the showpiece. Five bosses, every one a real frequency doing the real thing. Dial tone as two-circle interference you chase the intersection of; DTMF as a 4×4 grid where you attack at the crossing of a row and column tone; ANSam at 2100 Hz flipping its attack direction on its own 450 ms phase reversals; V.8bis as bullet hell where clean dodges declare capabilities and your score becomes your baud rate for the next two hours; then the carrier ride. Ends on a real CONNECT string.

Thin: the bosses don't escalate into each other. Each is a self-contained idea that stops when it's beaten.

What I'd add, ranked

  1. A second phase for each. Dial tone should eventually stop being patient. ANSam should shorten its deaf window. Right now every boss is at full difficulty from the first second and stays there.
  2. Let the player fail upward. Failing the scream currently just means worse graphics. It should also mean the carrier ride is harder — a bad negotiation is a bad line.
  3. Retrain. Real modems renegotiated mid-call when the line degraded. A retrain event later in the game that drops you back into a 30-second scream fight, at whatever hop you happen to be on, is the best possible callback.
  4. The DTMF number should be dialable wrong on purpose. Dial something that isn't GET-ROOT and see where it goes.

DIRECTION:

_


10 · THE COPPER — src/levels/copper.js

hops 5158 · first person · ~4 min · whatever you earned

In: 300 m of sodium-lit duct with cable bundles, three load coils, a lineman's handset you clip onto a pair to listen to a stranger's phone call, and a central office with 4,200 instanced Strowger switches stepping in a wave, plus the Almon Strowger plaque.

Thin: it's a corridor with three exhibits. The cathedral is the best-looking thing in the game and you walk through it in forty seconds.

What I'd add, ranked

  1. Make the cathedral navigable. Frames you walk between, not past. Get lost in it. It should be the biggest space in the game and feel like it.
  2. Follow one call. Pick a connection at the MDF and physically follow it through the switches as it's set up, step by step, relay by relay. That's the level's reason to exist and it isn't in yet.
  3. More to listen to. One phone call. There should be six, and one of them should be a modem, and one should be somebody who hears you.
  4. Weather. The design doc says it's the first level with weather. There's no water in it.

DIRECTION:

_


11 · THE BLUE BOX — src/levels/bluebox.js

hops 5963 · music/puzzle · ~5 min · whatever you earned

In: the gut punch. A playable thirteen-button blue box with correct R1 MF pairs and real 100 ms KP / 60 ms digit timing. Hold space for 2600 Hz to seize the trunk, then KP + digits + ST to route, four times, stacking tandems. Then the call comes back and rings the payphone six feet behind you and you hear your own signalling a quarter-second late. Then SS7 arrives and it stops working and Joybubbles keeps whistling anyway.

Thin: the routing codes are dictated. You type what you're told.

What I'd add, ranked

  1. Let the player route. Give them a map of area codes and let them work out the path themselves. The instrument is real; the puzzle isn't yet.
  2. The 2111 conference. The design doc's best unbuilt scene: a loop-around with other phreaks in it, all voices, no faces, and you can just sit there.
  3. Joybubbles should teach by ear only. He half does. Take the frequencies off the readout during his lessons entirely and make the player find 2600 by listening.
  4. Free-play mode after SS7. You keep the box. It does nothing. Let the player still press the buttons.

DIRECTION:

_


12 · THE CLIMB — src/levels/climb.js

hops 63→1 · on rails · ~2 min · whatever you earned

In: an accelerating flight up through eight era palettes in reverse, with the three modern toys: Spectre as a split timeline where you carry a token out of the branch that gets discarded, Rowhammer as a wall you bang on 24 times until a bit flips next door, and Log4Shell as a sign you hold up.

Thin: two minutes for what the design doc calls the best eleven minutes in the game. The eras flash past as colour changes with no content in them.

What I'd add, ranked

  1. One mechanic callback per era. Fifty seconds each, each one handing you back a verb you learned there for exactly one more use. That's the whole point of the sequence and none of it is in.
  2. Everything on fire. It's described as burning and it isn't.
  3. The Spectre section should be a real split screen. Two viewports, two timelines. It's a scissor-test and a second camera.
  4. Log4Shell needs its beat of silence. Right now it fires and moves on. It should stop, let the fortress walk over, read the sign, and go and fetch it while you stand there doing nothing.

DIRECTION:

_


13 · ROOT — src/levels/root.js

hop 64 · ~3 min · v.90

In: an empty white room with uid 0 in the middle distance and nobody in it. Four beats of narration at your own pace, then the ACK arrives from 220 units away, ESTABLISHED, a sixteen-second countdown, then FIN / FIN-ACK / ACK / CLOSED, then TIME_WAIT with FIN saying told you, then it loops to hop 1.

Thin: the loop is instant. And the ending doesn't know what you did.

What I'd add, ranked

  1. The ending should read your save. Philes found, hops skipped, whether you got the NUP, what you posted to FidoNet, how many times you expired. It has all of it and uses none of it.
  2. Your FidoNet message should come back. You posted it at hop 35 and it takes until Tuesday. Sixty-four hops later is Tuesday. This is free and it is the best single thing left unbuilt in the game.
  3. New game plus, honestly. The loop should keep the philes and reset everything else, and hop 1 should be very slightly different the second time.
  4. CHECKSUM. The anonymous pass-by. Needs a server. Last.

DIRECTION:

_


Cross-cutting, if you'd rather direct by system than by stage

The philes 40 of 200 written. All in src/philes.js, all readable with P. Pure writing.
Audio Every tone is real but the music isn't built — the design says each level's pad is generated from that era's protocol and right now they're just chords.
The retrain A mid-game renegotiation that drops your baud without warning. One system, touches every level after it.
Difficulty Nothing scales. TTL is the only pressure and it's linear.
The 64 hops 13 levels covering 64 hop numbers. Either fill in more levels or make the existing ones properly own their ranges.