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>
169 lines
11 KiB
HTML
169 lines
11 KiB
HTML
<!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 50–70 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 5–12 minutes now against a design document that asks for 5–20, 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>
|