Implements Reasoning Battles — a Paperclips-inspired canvas combat system
where structured reasoning (blue) fights adversarial testing (red) using
boid flocking (cohesion, aggression, separation) on a 310x150 grid.
Features:
- Boid flocking AI for ship movement
- Grid-based combat resolution with OODA loop speed bonus
- Napoleonic War battle names
- Auto-trigger battles scaled to drift and phase
- Battle history log
- Rewards: structured wins = knowledge, adversarial wins = code
- Unlocks at Phase 3
- Integrated into tick loop and render pipeline
Saves lastSaveTime timestamp. On load, calculates elapsed time
and awards 50% efficiency production. Shows summary toast.
Min 30 seconds away to trigger.
- Remove duplicate clipboard/prompt-based exportSave/importSave from utils.js
(render.js file-based versions were already overriding them)
- Add toast notifications for export success and import errors
- Add isValidSaveData() with robust validation (checks totalCode, code, buildings, phase)
- Prevent duplicate file dialogs on rapid E key presses
- Clean up file input element when user cancels dialog
- Add toast for JSON parse errors on import
playTime was defined in globals but never incremented and never
included in save/load. Now incremented each tick and persisted
in localStorage via the whitelist and save data.
- index.html: role=region on phase-bar, strategy-panel; role=dialog+aria-modal on help overlay, offline popup, drift ending; aria-label on help button, close button, continue button, start over button; aria-live on progress label
- render.js: aria-label on alignment event buttons; fix exportSave() URL revoke race with setTimeout delay
- engine.js: aria-label+aria-pressed on buy amount buttons; role=button+tabindex+aria-expanded+aria-controls on completed projects header
- Building rate display now shows actual boosted rates (after multipliers)
instead of raw base rates, so players see their real production
- WRITE CODE button area now displays current click power dynamically
(updates each render tick as boosts change)
- Click power also reflected in button aria-label for accessibility
Closes#61