SOURCE / PINNED RELEASE
Made of little things.
Rail Game
- Release
- ccdd5b913413…
- Author-recorded commit
- ddf0122b6acc…
- License
- LICENSE
- Author’s source reference
- nostr://npub1n8ga89w8h6tvwamxusfyzexw8gjy84yxu9rxgnmk955cxtml4ujswzxydd/wss%3A%2F%2Fgit.napplet.soy%2F/n-91ec90c6fdf
Archive hash verified: dad7b678e25f96a3…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
# Larger battles and camera update
Historical verification for the three-stage version. See the
[eight-stage campaign update](campaign-expansion-verification.md) for the current build.
Verified 2026-09-22 in soyLI 0.18.1 on macOS ARM64.
## Changes
| Mechanic | Original prototype | Updated game |
| --- | --- | --- |
| Starting soldiers | 3 | 8 |
| Maximum soldiers | 30 | 100 |
| Enemies per stage, excluding bosses | 7 / 8 / 9 | 60 / 96 / 150 |
| Recruit gates | +3 to +8 | +10 to +24 |
| Normal volley interval | 0.38 seconds | 0.26 seconds |
| Rapid volley interval | 0.17 seconds | 0.11 seconds |
| Boss health | 100 / 190 / 300 | 2200 / 3800 / 5600 |
| Boss projectiles per attack | 1 | 3 / 5 / 7 |
Enemy formations have three columns and two to four rows. Every soldier still
renders and fires independently. Barriers remove at least six soldiers or 30% of
the squad, making steering relevant at the larger scale. A full squad stays within
a ten-column formation, with enough room above the touch controls.
The camera sits behind and to the left of the straight track. The nearby squad
stays centered relative to steering, while the distant rail converges leftward.
The track is straight, the HUD stays level, and drag input uses the updated scale.
The soldiers' visible backs now have small packs; the commander has a gold helmet.
Collision checks consider nearby targets in distance order, so distant entities
do not add work to every projectile. Cosmetic particles are capped at 420.
No dependencies, external assets, NAP requirements or relay operations were added.
Theme, config and progress storage retain their existing optional SDK boundaries.
## Verification
- `pnpm verify`: guidance, strict TypeScript and single-file build pass.
- `soyli check`: passes with the updated build, cover and recorded preview.
- `pnpm test:game`: 15 tests pass. Added checks cover stage enemy counts, a unique
bounded 100-soldier formation, full-squad projectile output, and boss spreads.
All three stages remain winnable in simulation.
- `pnpm test:conformance`: 5 pass, 0 fail, 5 skip. Manifest, wire and lifecycle
evidence remain unmeasured by this local-directory reference-shell invocation;
see the original [coverage explanation](prototype-verification.md).
- `tests/browser-smoke.mjs`: exact 200×160, 240×280, 320×560, 900×600 and
2400×1200 frames pass in dark and light themes. Keyboard steering, small-frame
pause/resume and touch drag/hold/cancellation pass. Touch viewports: 390×844,
360×640 and 844×390. No browser runtime errors were observed.
- `tests/browser-campaign.mjs`: completed all three stages through the actual
host UI using pointer input and accelerated animation time. Stage results were
7950 / 10900 / 14550 points, with 74 / 92 / 70 survivors. The run reached 100
soldiers, captured the full formation in desktop and portrait frames, and
retained the campaign unlock after reload.
The campaign recorded 3650 JavaScript animation callbacks with at least 80
soldiers: median 1.0 ms and 95th percentile 1.7 ms on this machine. This measures
simulation and drawing-command submission, not GPU completion or physical phone
frame rates. Native timing was retained separately from the accelerated game
clock. Browser results and screenshots are in ignored `.napplet-space/qa/`.
## Preview media
`preview-expanded.png` is a real 1200×750 frame showing 40 soldiers after the first
multiplier. `preview-expanded.webm` uses the same eight-second interaction recipe
as the first prototype, now showing growth from 8 to 20 to 40 soldiers and the
new camera. The recorder's appended frame makes the file approximately nine
seconds. Previous preview files are preserved; the current selections are in
`napplet.json` with the recorder's actual artifact hash.
The host Listing view loaded the updated cover, and the 960×600 preview played
through to its end without an error.
Additional captures: `.napplet-space/qa/squad-100.png`,
`.napplet-space/qa/squad-100-portrait.png`, and `.napplet-space/qa/portrait.png`.
The portrait captures use a real 390×844 iframe after live resizing. No portrait
video was produced. Actual iOS/Android performance and audio activation remain
untested. The update remains a local development build.
