haxtory/card.html
type-two bb9decb484 The philes: 200 of 200, written and placed
The writing job, done. 89 new philes takes the store to 200, and every one
of them is now reachable in play — which turned out to be the harder half.

Where they live follows from the voice rule. Each phile is written by
somebody, in the year it happened, who did not know they were in a game —
so the board is 1991 and the board cannot carry a file about WannaCry.

  the board   seven read-online areas: g-philes, the law, the scene,
              v i r u s, the iron, telephony, unix. Reading online is free
              and downloading costs MTU, which is how a board actually
              worked, and is the only way ~60 files fit inside an economy
              built to make you choose.
  the climb   everything after 1992, because the climb is the only level
              that travels forwards in time. Thirty-six years bolted to the
              shaft wall going past at speed. You get the file for having
              been there whether or not you turned your head.
  the shell   man(1) and cat(1) on kruuna, for the unix and network ones.

ctx.phile(id, ..., quiet) collects without a toast — thirty-six
notifications in fifty seconds is a wall, not a level. The count lands once
at the top of the climb.

Two real bugs found on the way:

  handshake   exit() guarded .tone instead of .b, and there is a window
              between S.i++ and enter() where a boss is current but its
              state does not exist. Leave via the traceroute map during a
              title card and unmount throws. Async continuations now bail
              on a dead level too.
  the climb   the camera does not travel, the shaft does. The new signs
              were nailed to the origin and never came into view. They also
              needed dark ink for the one zone whose walls are white.

tools/philecheck.mjs: duplicate ids in an object literal overwrite
silently, and that cost an hour. It also reports anything written but not
placed. 200/200 written, 200/200 findable.

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

169 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>HANDSHAKE — model card</title>
<meta name="description" content="What HANDSHAKE is, how it was made, which parts are historically true, and what it does not do.">
<style>
:root{--bg:#07080d;--panel:#0d1018;--line:#1b2233;--ink:#dbe6da;--dim:#7b8894;--faint:#47535f;
--phos:#3dff9a;--pink:#ff3ea5;--cyan:#38d6ff;
--mono:ui-monospace,Menlo,"DejaVu Sans Mono",Consolas,monospace;}
*{box-sizing:border-box}
html,body{margin:0;padding:0;background:var(--bg);color:var(--ink);font-family:var(--mono);
-webkit-font-smoothing:antialiased;line-height:1.7;font-size:15px}
a{color:var(--cyan);text-decoration:none;border-bottom:1px solid #1d4152}
a:hover{color:var(--phos);border-color:var(--phos)}
.wrap{max-width:900px;margin:0 auto;padding:48px 22px 90px}
header{border-bottom:1px solid var(--line);padding-bottom:26px;margin-bottom:34px}
h1{font-size:clamp(28px,7vw,52px);letter-spacing:.30em;margin:0 0 6px;color:#eafcff;
font-weight:700;text-shadow:0 0 60px #17627f}
.sub{color:var(--dim);letter-spacing:.26em;font-size:11px;text-transform:uppercase}
.kicker{color:var(--pink);letter-spacing:.22em;font-size:11px;text-transform:uppercase;margin-bottom:14px}
h2{font-size:13px;letter-spacing:.26em;text-transform:uppercase;color:var(--phos);
margin:44px 0 4px;font-weight:600}
h2+p,h2+ul,h2+table,h2+div{margin-top:10px}
h3{font-size:14px;color:#eafcff;margin:26px 0 2px;letter-spacing:.06em}
p{margin:12px 0;color:#c3d0cf}
ul{margin:12px 0;padding-left:20px}li{margin:7px 0;color:#c3d0cf}
.dim{color:var(--dim)}
.box{background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:18px 20px;margin:18px 0}
.box.warn{border-color:#4a2430;background:#140d12}
table{border-collapse:collapse;width:100%;margin:14px 0;font-size:13px}
th,td{text-align:left;padding:7px 10px;border-bottom:1px solid var(--line);vertical-align:top}
th{color:var(--dim);font-weight:600;letter-spacing:.12em;font-size:10px;text-transform:uppercase}
td.k{color:var(--cyan);white-space:nowrap;width:1%}
.play{display:inline-block;margin:26px 0 0;padding:11px 22px;border:1px solid var(--phos);
color:var(--phos);border-radius:4px;letter-spacing:.2em;font-size:12px}
.play:hover{background:var(--phos);color:#04140b}
footer{margin-top:60px;padding-top:22px;border-top:1px solid var(--line);color:var(--faint);font-size:12px}
code{background:#0b0f16;border:1px solid var(--line);border-radius:3px;padding:1px 5px;color:var(--cyan);font-size:13px}
</style>
</head>
<body>
<div class="wrap">
<header>
<div class="kicker">model card</div>
<h1>HANDSHAKE</h1>
<div class="sub">a love story in 64 hops · monsterrobot</div>
</header>
<p>You are <b>SYN</b>, a TCP synchronise packet. Your entire nature is arriving somewhere
and asking <i>are you there</i>, and nobody has ever replied. You have heard there is
someone at the top of the machine who can receive anything. Their name is
<b>root</b>.</p>
<p>The modern network is a fortress, so you go <i>down</i> to go up — back through
fifty years of telecommunications, because the deeper you go the older it gets, and
the older it gets the more it trusts you.</p>
<a class="play" href="./">▶ play it</a>
<h2>At a glance</h2>
<table>
<tr><td class="k">Type</td><td>Single-player browser game. Fourteen hops, each a different genre, over one renderer.</td></tr>
<tr><td class="k">Length</td><td>Roughly 5070 minutes for one pass. It saves, and it is designed to be put down.</td></tr>
<tr><td class="k">Input</td><td>Keyboard and mouse. No gamepad. No touch — it will load on a phone and will not play well on one.</td></tr>
<tr><td class="k">Audio</td><td><b>Required.</b> Several mechanics are inaudible without it, and one boss is unbeatable if you cannot hear the beat.</td></tr>
<tr><td class="k">Runs on</td><td>Any browser with WebGL2 and Web Audio. No install, no account, no server. Progress is in <code>localStorage</code>.</td></tr>
<tr><td class="k">Data</td><td>None leaves your machine. There is no analytics, no telemetry, no network call after the page loads.</td></tr>
<tr><td class="k">Reading</td><td><b>200 philes</b> — text collectibles, all of them findable, none of them required. Roughly 30,000 words, written as if by someone in the year it happened who did not know they were in a game.</td></tr>
<tr><td class="k">Built with</td><td>~9,000 lines of hand-written JavaScript and one vendored copy of three.js. No engine, no build step, no dependencies.</td></tr>
</table>
<h2>The three ideas it is built on</h2>
<h3>TTL is the health bar, and it only goes down</h3>
<p>You start with 64 and every hop costs one. There is no healing item, no shrine, no
pickup. Levels are not <i>hard</i> — they are <i>expensive</i>. Every optional thing
you look at costs some of the distance you have left.</p>
<h3>Bandwidth is resolution</h3>
<p>Your connection speed is wired directly to the renderer. At v.90 the game is full 3D;
at 1200 baud and below it renders as ASCII glyphs, drawn one character at a time. You
earn your rate by performing well in a dial-up handshake fight, and there is no retry
prompt. The game gets warmer and more human as it gets technically worse, which is the
argument the whole thing is making.</p>
<h3>Every header you drop is a piece of clothing</h3>
<p>You descend the OSI model wearing seven layers. Each floor takes one off. At layer
seven you are wrapped in TLS and nothing can see you; at layer one you are bare voltage
on a wire.</p>
<h2>What in this is true</h2>
<p>Most of it. Specifically:</p>
<ul>
<li><b>Every frequency is the real frequency.</b> Nothing is sampled — it is all oscillators. 350+440 Hz dial tone. The full DTMF matrix. R1 multi-frequency pairs at their real 100 ms KP / 60 ms digit timing. 2600 Hz. ANSam at 2100 Hz reversing its phase every 450 ms, which is the actual interval and the actual reason (it disables echo cancellers). Bell 103 FSK.</li>
<li><b>Almon Strowger</b> was an undertaker in Kansas City who invented automatic telephone switching in 1891 because the local operator was his competitor's wife and kept redirecting his calls.</li>
<li><b>The Morris worm's 1-in-7.</b> It asked a host whether it was already infected, then — worried about being lied to — reinfected anyway one time in seven. That single defensive line is what turned it into a disaster. In the game it is on the HUD and you cannot switch it off.</li>
<li><b>The 75-cent discrepancy</b> at Lawrence Berkeley Lab in 1986, and the astronomer who wired fifty printers to fifty lines in a basement rather than round it off.</li>
<li><b>2600 Hz and in-band signalling.</b> The control channel and the voice channel were the same channel, so you could sing to the switch. SS7 moved signalling out of band and the hole closed permanently. The game takes the ability away from you and does not give it back.</li>
<li><b>Linux.</b> 25 August 1991, comp.os.minix. He wanted to call it Freax; the FTP administrator named the directory <code>linux</code> and never mentioned it. The GPL relicence at 0.12 in January 1992 is the date that actually mattered.</li>
<li><b>The port classes in Trade Wars</b>, the Baudot rate of a Model 33 teletype, exponential backoff on shared media, little-endian byte order, ret2libc, W^X, Spectre, Rowhammer, and the Log4Shell JNDI lookup — all as described.</li>
</ul>
<div class="box">
<p style="margin:0"><b>The soundtrack is derived, not composed.</b> No level has a chord
somebody picked because it sounded nice. Each bed is built from a real number belonging
to its era: the 1 kHz telecoms reference tone, 50 Hz mains, the 1200 Hz V.22bis carrier
folded down, <code>0x90</code> read as 144 Hz so the NOP sled has a pitch, 20 Hz ringing
current, the six MF tones of a blue box, and 2600 Hz folded six times until it is a low
room tone. Some of it is beautiful and some of it is ugly. A 1980 telephone exchange was
not tuned to A=440.</p>
</div>
<h2>What in this is invented</h2>
<ul>
<li><b>The people.</b> The sysop, the regulars, the rival crews, the person on the other end of a <code>talk</code> session — all fiction. Where a real person appears, what they say is written for the game, not quoted, except where explicitly marked as a quotation.</li>
<li><b>The board.</b> THE LAST TRUNK never existed. Its nine years, forty-four users and closing bulletin are composed — but the <i>shape</i> of how it ends is how most of them ended: not raided, just quietly out-competed by something with no busy signal.</li>
<li><b>The framing.</b> Packets do not want anything. The romance is a device.</li>
<li>Dates and mechanisms are accurate; dialogue and dramatisation around them are not.</li>
</ul>
<h2>What it does not do</h2>
<div class="box warn">
<ul style="margin:0">
<li><b>It is still short for what it is.</b> A hop runs 512 minutes now against a design document that asks for 520, and the shorter ones are short. The genres, mechanics and set pieces are all in.</li>
<li><b>There is no multiplayer.</b> The design calls for anonymous pass-by contact between players. It needs a server and there isn't one.</li>
<li><b>It is not accessible.</b> There is no colourblind mode, no remappable input, no subtitles for the non-speech audio cues, and at least one mechanic is gated behind hearing a 450 ms rhythm. This is a real limitation and not a stylistic choice.</li>
<li><b>Performance is untuned.</b> It runs on a modern laptop. It has not been profiled on anything else, and one level puts 4,200 instanced meshes on screen.</li>
<li><b>It has not been playtested by strangers.</b> Difficulty, pacing and clarity are one person's guesses.</li>
</ul>
</div>
<h2>Content</h2>
<p class="dim">No graphic content. Mild profanity, none of it aimed at anyone. It is about
computer crime in the sense that a documentary is: it explains how things worked and does
not teach anything that has been usable for thirty years. Two levels are quietly about
loss, and one of them is about a room where nothing happens on purpose.</p>
<h2>How it was made</h2>
<p>Written by <b>Claude Opus 5</b> (Anthropic) in an extended session with John King,
from a one-paragraph idea to the finished thing — design document, engine, fourteen
levels, audio synthesis and this page. Roughly 9,000 lines of JavaScript, no engine and
no build step, on top of one vendored copy of three.js (MIT).</p>
<p class="dim">Every level was verified in a real browser as it was built, and several
genuine bugs are documented in the commit history rather than quietly fixed — the
renderer was 45% too dark for an hour because a raw shader does not get three.js's
colour-space conversion, and the Morris worm level could not reach its own milestones
until the spread rate was made to scale with the infection.</p>
<h2>Source</h2>
<p>The design document and the per-stage build notes ship alongside the game:
<a href="./DESIGN.md">DESIGN.md</a> ·
<a href="./STAGES.md">STAGES.md</a> ·
<a href="./README.md">README.md</a></p>
<a class="play" href="./">▶ play it</a>
<footer>
HANDSHAKE · monsterrobot.games · three.js is MIT.<br>
Headphones. Every frequency in this is the real frequency.
</footer>
</div>
</body>
</html>