SOURCE / PINNED RELEASE
Made of little things.
Conway's Game of Life
- Release
- 230955df1900…
- Author-recorded commit
- c08196c2b050…
- License
- LICENSE
- Author’s source reference
- nostr://npub16nzc4ql748r2kv9202rgzrt0fmtk4n3tzsjl86yf6ty9agqe9u0qjcc7hc/wss%3A%2F%2Fgit.napplet.soy%2F/n-644c45e22c7
Archive hash verified: 2627ce678935a213…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Listing description: byte-identical to napplet.json `description`
(pinned by tests/guidance.test.mjs; frozen with the player at Phase 9). -->
<meta name="description" content="Conway's Game of Life on a wrapping 120 by 90 board: paint cells, drop classic patterns like the Gosper glider gun, and watch it evolve at your chosen speed." />
<title>Conway's Game of Life</title>
</head>
<body>
<!--
A napplet is an applet framed by a runtime: the runtime already shows this
napplet's name, so there is no title header here. The board is the frame
from the first pixel; the HUD is one quiet status line (spec §8 copy).
-->
<main id="app" class="app">
<div class="hud" aria-label="Simulation status">
<span class="hud-item">gen <span id="generation" class="num">0</span></span>
<span class="hud-item">pop <span id="population" class="num">0</span></span>
<output id="status" class="hud-status" aria-live="polite" hidden>Stable</output>
<output id="save-status" class="hud-status hud-save" aria-live="polite" hidden
>Saving unavailable — play stays in this session.</output
>
<!-- Armed-placement hint (spec §6 rework ruling 2026-10-30): text set
by main.ts while a pattern is armed; hidden = not armed. -->
<output id="place-status" class="hud-status hud-place" aria-live="polite" hidden></output>
</div>
<!-- Static control chrome (spec §5): outside any state machine; painting
stays legal while any control state is active. -->
<div class="controls" aria-label="Simulation controls">
<!-- Boots PAUSED behind the welcome gate (spec §5 welcome rule), so
the initial glyph is Play; syncRunButton() keeps it in step. -->
<button id="play-pause" class="ctl" type="button" aria-label="Play">⏵</button>
<button id="step" class="ctl" type="button" title="Step one generation" aria-label="Step one generation">⏭</button>
<button id="clear" class="ctl ctl-word" type="button">Clear</button>
<button id="random" class="ctl ctl-word" type="button">Random</button>
<button id="patterns" class="ctl ctl-word" type="button" aria-haspopup="true" aria-expanded="false" aria-controls="pattern-menu" title="Pattern library">Patterns</button>
<label class="ctl-speed">
<input id="speed" type="range" min="1" max="30" step="1" value="10" aria-label="Speed in generations per second" />
<output id="speed-value" class="num" for="speed">10/s</output>
</label>
</div>
<div id="board" class="board">
<canvas id="cells" aria-label="Game of Life board"></canvas>
<!-- Pattern library overlay (Phase 5, spec §6): static chrome riding
outside any state machine — open/close never touches running,
generation, or paint legality. Items built from PATTERNS. -->
<div id="pattern-menu" class="menu" hidden>
<div class="menu-title">Patterns</div>
<div id="pattern-list" class="menu-list"></div>
<button id="menu-close" class="ctl ctl-word" type="button">Back</button>
</div>
<!-- Welcome gate (spec §5 welcome rule, player ruling 2026-10-30):
full-frame primer overlay at boot; Start dismisses it AND enters
the sim through the same setRunning path as the play/pause
button. Fixed positioning rides the FRAME, not the board box:
at the 200x160 floor the board row collapses under the control
bar, and a board-anchored card would squash to nothing. Markup
lives inside .board; the scrim blocks all controls until Start.
Copy pinned by the browser suite (spec §8). -->
<div id="welcome" class="welcome" aria-label="How to play">
<div class="welcome-card">
<div class="welcome-title">How to play</div>
<ul class="welcome-list">
<li>Left click/drag to paint cells</li>
<li>Right click/drag to erase</li>
<li>Space play / pause, → step, C clear</li>
<li>Patterns: pick one, then tap the board</li>
<li>Slider sets speed, 1–30 per second</li>
</ul>
<button id="welcome-start" class="ctl ctl-word" type="button">Start</button>
</div>
</div>
</div>
</main>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
