fuzzyworld

explodorama / files / CHANGELOG.md

CHANGELOG.md

Blame: the commit that last changed each line · file · history

7ce1fb51 2026-10-23 Pavel Safronov1# Changelog
2
3All notable changes to Explodorama are written down here. The format follows
5607bea2 2026-10-31 Pavel Safronov4[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Releases are semver, git-tagged
5by Pavel. **0.1.0 is the base**: everything under it below is part of it, and the player-facing list
6of changes in the game ([src/changelog.ts](src/changelog.ts)) starts there. From now on, each entry
7that reaches players is also added to `UNRELEASED` in that file. "Version N" in older entries is
8the rules version N (`SIM_VERSION`).
7ce1fb51 2026-10-23 Pavel Safronov9
10A saved run is only resumed if it was made with the same version of the rules
11(`SIM_VERSION` in [src/sim/record.ts](src/sim/record.ts)). When a change below bumps it, a run
12saved before the change is dropped and the next visit starts a new run.
13
14## [Unreleased]
15
351348d1 2026-11-04 Pavel Safronov16### Added
17
18- **Replay page for bug reports** (Q103, user request, 2026-11-03; dev only, nothing in a build): `npm run report-replay -- <mail>` turns a report's run record into `replays/<name>.json` and prints `http://localhost:5173/?replay=<name>`. The page loops the last level's last turns with two players on one board, a little off centre: red (left) plays the report's recorded turns, blue (right) the same until the autopilot took over, then today's autopilot (`rival` in `render/board.ts`); the label tells how long they are in step and when they split, and how each ends. New `sim/replayCompare.ts` (`buildReplay`), `tools/report-replay.mjs` (reads quoted-printable mail), a dev-server plugin in `vite.config.ts`, `?replay` counts as a test URL (no save, no scores). Test: `test/replayCompare.test.ts` with the Q101 report as a fixture. **The page takes no input** (window-level capture handlers stop pointer, key, touch and wheel events; the pad is not polled), and has a second mode, `&rules=<commit>`: the whole run played by the rules of an older commit (red; its `src/sim` made by `git archive` into git-ignored `rules-versions/<commit>/` by `tools/report-replay.mjs`, which takes the commit from the report's "commit …" line) and by today's (blue), `sim/ruleCompare.ts` `compareRules`, with the quiet stretch jumped through and the first difference named in the label. Test: `test/ruleCompare.test.ts`.
19
20### Fixed
21
22- **The autopilot no longer walks into a bomb's blast** (Q101, user bug report, 2026-11-03, seed 1464004408, level 4): with Bomb Pass, a power-up behind the player's own ticking bomb counted as reachable, and the autopilot stepped onto the bomb's tile and back, inside the blast, and lost a life. `safeStep` and `isDeadly` only look at this turn. `autopilotPlan` (`sim/autopilot.ts`) now keeps off every tile in the danger overlay (`now`, `next` and `later`: what will burn while the player waits), waits (phase `bombs`) when the way is shut by it, and when standing in such a zone first walks out by the shortest way (`fleeAction`). Spikes are left out of that zone (they are always up in one turn of two, and `safeStep` already times the crossing), and the `bombs` wait only applies while a bomb, flame, smouldering bush or ceiling is on the board, so the stall limit still catches a wait that leads nowhere. Flame Pass-style `flameSafe` runs are not held back. Test: `test/autopilot.test.ts` (Bomb Pass scene, fails without the fix). Autopilot moves are ordinary `move` actions, so **SIM_VERSION is unchanged** (43).
23
805e7a9f 2026-11-03 Pavel Safronov24## [0.2.0] - 2026-11-02
25
92cc4ee3 2026-11-02 Pavel Safronov26### Added
27
805e7a9f 2026-11-03 Pavel Safronov28- **End-of-level screens are panels; demo controls on a controller** (2026-11-02): the level-cleared, "Ouch!" and game-over/victory banner (`#banner`) is now a parchment `.panel` with the dialog's `.ui-button` buttons and backdrop (HTML wrapper in `index.html`, CSS in `style.css`; the ids and the pad glue in `padDialog.ts` are unchanged). In the demo the d-pad up = shuffle, down = first scene, R1 = next input, with pictures on the buttons (`syncDemoGlyphs` in `main.ts`). Menu: a Changes button.
92cc4ee3 2026-11-02 Pavel Safronov29- **Faded blue for auto-move's reach; the way previewed; faster d-pad repeat** (Q69, 2026-11-02): with the pad's or keyboard's cursor, every tile auto-move can walk to (`farTiles` in `ui/padTiles.ts`: `tapMeaning` says 'walk', `autoMoveAction` finds a safe, not deadly first move; minus the bright tiles and your own) is tinted a fainter blue (`C.targetFar`, `View.faded`) and is a cursor candidate (`cursorCandidates`, `FarTile`). Move/Go there (M or Enter on the keyboard) does what a tap does (`padDo` taps the tile with nothing picked), label "Walk here · N steps" (`farActions`; "Keep walking" when it is the set destination, which is then the only faded tile). Computed once per state in `currentFar` (`main.ts`); `afterChange` now works out danger and the destination before `refreshCursor`. **Preview:** with the cursor on a faded tile, or the mouse (not touch) hovering over one with nothing picked, the board draws auto-move's way as the real one is drawn (landing tiles, arrows, first one red when unsafe) without setting it or stepping (`routePreview` in `ui/routePreview.ts`, `View.preview`, `previewNow` in `main.ts` caches per tile, state and danger; `farTileAt` tests one tile). D-pad repeat: `REPEAT_DELAY_MS` 300 to 250, `REPEAT_MS` 110 to 75 (`ui/padMap.ts`; menus and dialogs share it). Tapping and clicking are unchanged. Tests: `test/farTiles.test.ts`, `test/routePreview.test.ts`; the repeat tests in `test/padMap.test.ts` now use the constants.
30- **The demo for the keyboard** (Q65 part B, user request, 2026-11-02): **Input: keyboard** is the input button's third entry (touch, mouse, keyboard, then the controllers; `ui/demoInput.ts`, `isKeysInput`). The scenes are the controller demo's shape (the touch scenes without the touch-only ones and the charge swap; own saved place `demoAtKeys`), acted out with keys on a new **key overlay** (`ui/keyOverlay.ts`: Kenney Keyboard & Mouse glyphs, 15 files copied into `assets/kenney-input-prompts/`; arrows, Alt, Shift, M B V, Space, ? Home Enter Esc; white at rest, lit for 0.7 s) and the dashed cursor when Shift is used. `ui/keyDemo.ts` (pure, tested) turns each turn into the fewest key presses (a plain arrow, an action key then an arrow, the key twice for Freeze, or Shift + arrows then the key) and verifies each by replaying it through the game's rules. New scenes: the Shift cursor, `?` + arrow + Enter, Alt + arrows with Home, Esc for the menu; keyboard captions (`SceneDef.keyCaption`, `keyCaptionHtml`); hint "Press Enter or Esc to play". Clips are unchanged.
31- **A keyboard cursor, and the keyboard fully playable** (Q65 part A, user request, 2026-11-02): Shift + arrows (or Shift + W A S D) wake the controller's tile-first cursor for the keyboard (`ui/keyCursor.ts`, pure, tested; `inputMode` 'pad' | 'keys' | null in `main.ts` replaces `padActive` as what shows the cursor and aim); M B V R K T P F I L X Space act on its tile, Enter does the first action or confirms a picked one, Esc backs out stepwise; its label and hint show key caps. Plain arrows keep "nearest valid tile that way". `?` now aims over the explainable tiles (arrows, Enter or `?` explains), and no longer lets an arrow move you; Alt + arrows pan, Home recentres. Fixed: Enter on the banner pressed the first button whatever had the focus, and Space waited when a button had the focus; now Enter and Space press the focused button instead of acting in the game (`targetTakesKey`; a mouse or touch click does not leave the focus on a board button); a dialog opened on its panel now answers Enter with its green (or only) button, and closing one blurs the button the browser hands the focus back to. README *Keyboard* section is new.
32
bb3823d2 2026-10-31 Pavel Safronov33### Changed
34
720cc9d3 2026-11-03 Pavel Safronov35- **A missing choice dialog comes back** (Q90, user bug report, 2026-11-02, seed 395025326 level 5): replaying the report's run ends with a gem's choice AND a charge's sell-or-swap pending (one slide crossed an Acid charge, coins and a gem) while the player "couldn't move": the rules refuse every action until the choice is made, but nothing showed it. `reopenPendingChoice` in `main.ts` (every frame) reopens the dialog if a choice has waited 1.5 s with no dialog open (the menu or an info dialog opened over it also loses it until closed). Why the dialog was missing is not known (it is `required`, so it cannot be closed).
36- **Autopilot slower; a Cancel button** (Q89, user report from a bug report, 2026-11-02): the autopilot's step is 0.4 s (2.5 moves a second, was 0.25 s). A round **Cancel** button (cross, `kenney-icons/cancel.png`, in `ui/controls.ts`) shows over the action bar's top right while an action is picked or auto-move has a destination (not with "What is that?" on, which has its own ? button; hidden for the pad, whose L1 cancels, and in the demos); it does what Esc does (`cancel()` in `main.ts`). Touch had no way to put these away.
37- **"What is that?": one press, not a hold** (Q88, user request, 2026-11-02; amends Q85): Cross explains and Circle leaves at the first press, since nothing in the mode can hurt (`instant` in `ui/gamepad.ts`, answered by `main.ts`; the label says "Press"). The explanation dialogs it opens take a single press too (`inspectDialog`), and so does any dialog opened from them in turn; the menu and other dialogs keep the hold. Holding there is to become an option (`INSPECT_HOLD`, Q71).
38- **"What is that?" stays on after an explanation** (Q87, user request, 2026-11-02): with the pad or the keyboard's aim, closing an info dialog returns to the mode with the aim where it was, so the next thing can be checked at once (`aimExplain` in `main.ts` no longer ends the mode); leaving is a held Circle, Esc, or "Walk there". A tap or click on a tile still ends it.
39- **"What is that?" can be aimed at yourself** (Q86, user report, 2026-11-02): your own tile now has an explanation ("You": lives left, how a turn goes; `tileInfo`), so L1 can put the aim on you and the d-pad can reach you; the aim still starts on the nearest other thing. Tapping yourself in the mode explains you too (no "Walk there" on your own tile).
40- **"What is that?" with the pad: hold Cross to view, hold Circle to leave** (Q85, user request, 2026-11-02): the same hold-to-confirm scheme as the rest of the pad. R1 turns it on (and does nothing once on), the d-pad moves the aim, **holding** the confirm button explains, **holding** the cancel button leaves; L1 only brings the aim back to the player's side, and no longer leaves or explains. The label shows both buttons with their rings (`main.ts` `leaveInspect`, `padBack`). Supersedes the L1/R1 wording of Q84 for inspection.
41- **The L1/R1 hints move to the top of the board, in full words, with symbols** (Q84, user request, 2026-11-02): under the top bar instead of above the bottom label; "Move cursor back to you" / "Cancel what you picked" / "Leave inspection mode" for L1 (an undo arrow), "Activate inspection mode" / "Explain what is aimed at" for R1 (a magnifying glass); both icons are Game Icons (`assets/kenney-icons/zoom.png`, `return.png`, listed in `docs/art-provenance.md`). The keyboard's legend says "Activate inspection mode" too.
42- **"What is that?" with the pad says to hold** (Q83, user report, 2026-11-02): the four action buttons are greyed while it is on (it explains, it does not act), and the label shows the confirm button's picture with "Hold to find out what this is"; the hold ring goes round that picture (`main.ts`: `barInspect`, the label, `hold`). The keyboard's label is unchanged.
43- **"What is that?" with the pad reaches pillars, walls and the top bar** (Q82, user report, 2026-11-02): the d-pad aim included only tiles with something special, so a pillar or wall could not be asked about. It now includes them (`explainableTiles(s, true)`), still starting on the nearest interesting tile (`aimStart`). Up from the top row goes on to the status icons of the top bar, Left and Right move along them, Down comes back; the confirm button explains the item (`main.ts` `aimStep`, `aimExplain`, `syncHudAim`).
44- **Three pad cursor fixes** (Q79-Q81, user report, 2026-11-02): (Q79) Wait pressed with the cursor on the player leaves it on the player, even while an auto-move walk is still set (`cursorPinned` in `main.ts`); (Q80) the cursor no longer starts on a walk's destination that a flame made unsafe (`cursorStart` takes the candidate tiles), and a d-pad press from a tile with no action moves to the nearest one that has, so it cannot be stuck; (Q81) a modifier key alone, or any Cmd combination (a screenshot's Cmd+Shift+4), no longer hands the board back from the pad (`ignoredForMode` in `ui/keyCursor.ts`).
45- **Turns count from 1 on screen; the menu's links all reachable by pad** (Q76-Q78, user report, 2026-11-02): the top bar, its info box and the menu say the turn you are on (`turnNumber` in `sim/state.ts`: `turn + 1` while playing, the count itself once the level is over), so a level starts at Turn 1; the sim, par and scores still count turns taken, and the bug report says "N turns taken". In the controller's dialog selector, any link (`a[href]`) can be selected, not only `#` ones: the menu's commit and Source code links, and the Try it early link. In the menu, the controller picture on the small Almanac / Scores / Demo / Bug buttons hangs on their corner instead of pushing the word aside (CSS only; not yet looked at on a real pad).
92cc4ee3 2026-11-02 Pavel Safronov46- **Move works on a tile that is also a bomb target** (Q75b, user bug report, 2026-11-02): with an RPG, an empty tile two away in a line was bright blue and Move was greyed there, so you could fire at it but not walk to it. `cursorActions` (`ui/padTiles.ts`) now offers Move as the walk ("Walk here · N steps") on any tile auto-move can reach, whatever else targets it; Bomb stays beside it. Tests: `test/q75.test.ts`.
47- **The cursor reaches every faded tile while a walk is set** (Q75, user bug report, 2026-11-02): with an auto-move destination set, only the destination was a faded tile and a cursor candidate, so a coin elsewhere (an enemy's drop beside a bomb) looked unreachable. `currentFar` (`main.ts`) now lists all faded tiles always; Move on another sets a new destination. Rules were fine; test: `test/q75.test.ts`.
48- **Moving the mouse no longer hands the board back** (user request, 2026-11-02): with the pad's or the keyboard's cursor showing, only a click, a tap or a key switches to the mouse; a plain mouse move (e.g. to take a screenshot) does not.
49- **A controller can change the menu's switches: the selected item shows its confirm button** (Q74, user bug report, 2026-11-02): in a dialog with a selector (menu, almanac, New run, changes list) a short press of Cross did nothing and nothing said why (the hold rule, Q59). The selected item now carries the confirm button's picture (`.sel-glyph`, `ui/padDialog.ts` `setSel`, with `data-face`, so the hold ring of `ui/holdRing.ts` fills round it); a face button let go before its ring filled calls the new optional `PadTargets.tap` (`ui/gamepad.ts`), which shows the toast "Hold to choose" once per dialog (`showsTapHint` in `ui/padDialogMap.ts`, pure, tested). The almanac's tabs before and after the shown one carry the LB / RB pictures. The 0.5 s rule is unchanged. **Autopilot:** it now waits while every target is cut off by a still-ticking bomb or burning flame (new phase `bombs`, "Autopilot: waiting for the bombs"; before, a coin behind its own bomb was skipped and the level ended without it), waits in that state no longer count towards the stall limit, and the route preview is off while it walks. Tests: `test/autopilot.test.ts`, `test/padDialog.test.ts`, `test/gamepad.test.ts`.
50- **The hold ring is anchored to the picture that began it** (Q72, 2026-11-02): the ring lingered at its old spot for the dialog's 150 ms pop-out, because it was placed only when the pad was polled. It now follows its picture every animation frame (`ui/holdRing.ts`) and hides the same frame the picture is removed, hidden, zero-sized or inside a closing or closed dialog (`ringVisible`); a completed hold's button stays used up until release. Test: `test/holdRing.test.ts`.
51- **Hold to confirm acts when the ring fills, not on release** (Q59 amended, user request, 2026-11-02): waiting for the button to be let go felt late. A face button now acts the moment its ring is full (`stepHold` in `ui/padHold.ts` returns `progress` 1 then `fire`; `ui/gamepad.ts` delivers `press` then), and the ring stays full (green) until the button is let go. The button is then **used up** (`HoldState.done`): it does not fire again, and it starts no new hold in whatever the action opened (a dialog, the demo ending into the game, a new level, the banner) until it has been let go; a second face button meanwhile is still ignored. A context change after completion only clears the ring (`holdEnd`); the used-up state ends on release, unplug, blur or a swapped pad. Holds that have not completed behave as before (early release, a context change, an instant button, blur, unplug, a swap or an error cancel with no action). The demo's hold-to-play starts play at completion, and the same held button then does nothing in the game. New event `release` in `HoldEvent`; `PadTargets.holdEnd` now means "the ring goes". Tests: `test/padHold.test.ts`, the hold-to-confirm block of `test/gamepad.test.ts`.
52- **Virtual controller: white d-pad, outline on top, brighter face buttons; stick demos; time bar on the TV** (user request, 2026-11-02): the d-pad and stick pictures are white at rest (they were dimmed grey) and show a press by their red arm; shoulders and Start light with a glow; the face buttons are dimmer at rest but brightened so PS5's blue and red read on the dark demo (replaced the same day: they are now grey at rest and coloured only while pressed, since a lit one was hard to tell from an idle one). The pictures are drawn under the line drawing (so its lines stay on top) and each face picture is clipped to its drawn circle (`--clip`, from `GLYPH_SCALE`); hold rings stay above. New pad scenes: the stick scene now zooms the demo's view to 2x (`updateCamera`'s `zoom`, `demoZoom` in `main.ts`, reset by `resetView`, `skipTo` and `endDemo`) and the stick pans it in each direction, then pressing it returns to you; **padLook** pushes the stick toward an enemy (`padDemoOrder`, `PAD_STILL_CAPTIONS.padLook`). The scene's progress bar (`#demo-time`) moved from the caption panel to the TV's bottom edge, inside the glass.
53- **The virtual controller is a real line drawing** (Q63, 2026-11-02): the hand-drawn SVG outline is replaced by OpenGameArt's "Controller style 1 / 3 / 5" pictures (CC BY 4.0, `assets/controller-art/`, scaled and trimmed by `tools/make-pad-layouts.py`) for Xbox (and generic), PlayStation and Nintendo, drawn as an image with a light glow so the lines read on the dark demo, and Kenney's pictures sit on the drawn buttons (measured positions; the layout lost `outline` and `lstick`). README Attribution and art provenance updated; the CC BY-SA Xbox photo credit is gone. The positions come from `ui/padLayouts.ts` (generated by `tools/make-pad-layouts.py`) through `ui/padPlaces.ts` (pure, tested); the face buttons follow `faceOf`, so Nintendo's A and B land where they are without CSS special cases. Removed the CSS body and grips and the per-part percentages. Art provenance #16 is data, not art.
54- **Nintendo pads: A confirms, B backs out; the pad demo's presses stay lit longer** (user request, 2026-11-02; amends the position-only mapping): on a Nintendo pad Move/Go and every dialog confirm (primary button, shop Buy, the demo's hold-to-play) are the right button (A), and Wait and every dialog dismiss are the bottom button (B); Bomb (Y) and Charge (X) stay left and top. Xbox, PlayStation and generic pads are unchanged. The family-aware rule is in the pure modules: `faceOf`, `faceActionOf`, `confirmFace`, `cancelFace` in `ui/padMap.ts` (`mapPad` takes the family), `faceGlyph` / `glyphFor` in `ui/padGlyph.ts`, `assignFaces` / `faceAction` in `ui/padDialogMap.ts`; the action bar's `data-face` follows the family, open dialogs are assigned again when it becomes known, and the demo's virtual controller draws A on the right and B at the bottom. `FACE_TO_BUTTON` in `ui/padTiles.ts` became `barButtonFor`. Separately, a pressed button on the virtual controller stays lit for `PAD_LIT_SECONDS` = 0.7 s (`ui/padOverlay.ts`; it was about 0.3 s) in the demo and the clips, with the beats respaced (`PAD_AFTER_SECONDS` = 0.3 s for the cursor to hop and rest after a d-pad press) so presses never overlap. Tests: Nintendo mapping, glyphs and dialog faces.
55- **No automatic fullscreen; the cursor stays on the destination while walking** (Q70, user request, 2026-11-02; supersedes Q57 and the Q60 auto rule): the game no longer goes fullscreen on the first tap, click or key, with or without a controller. Removed: `startFullscreen`, the "Start in fullscreen" setting (its stored value is no longer read), `ui/fullscreenRule.ts` and its test. Kept: the top bar's fullscreen button, the menu's "Fullscreen" switch and its "Press F11" toast. Also fixed: with a controller (or the keyboard cursor), after the first step of an auto-move walk the cursor returned to the player's tile, where only Wait was offered. It now starts each turn on the destination while the walk is on (`cursorStart` in `ui/padTiles.ts`, pure, tested), so Go ("Keep walking") continues it, and on the player again when the walk ends.
56- **Fullscreen only with a controller; a button and a menu switch** (Q60, user request, 2026-11-02; amends Q57): the auto-fullscreen part (`shouldAutoFullscreen` in `ui/fullscreenRule.ts`, `padConnected`, the setting "Start in fullscreen") was superseded by Q70 above and no longer exists; the rest stands. New: a round fullscreen button in the top bar (`#fullscreen-button`, shown only if `document.fullscreenEnabled`, state from `fullscreenchange`; Game Icons `larger` / `smaller`; on a phone's portrait bar all three round buttons shrink to 31 px so the bar does not grow), and a "Fullscreen" switch in the menu's Settings for the controller. A controller press is no browser gesture, so a refusal shows the toast "Press F11, or use the fullscreen button" (the Electron wrapper, Q41, will make it work). No pad button is assigned.
57- **The demo's input button** (Q61, user request, 2026-11-02): a pill under the scene buttons cycling **Input: touch**, **mouse**, **controller: ps5**, **xbox**, **switch**, **generic** (`ui/demoInput.ts`, pure, tested). It overrides the detected input for the demo only (`demoForced` in `main.ts`, not saved): the scene restarts for it; mouse is the touch scenes with Kenney's Cursor Pack arrow (`kenney-cursor/cursor_none.png`) in the finger's place and the hint "Click anywhere to play"; the controllers use the pad's scenes and virtual controller with that family's pictures. The pick stays until the demo ends or a controller is plugged in or unplugged (no click or button press drops it; only holding the confirm button, which ends the demo, leaves it). `Demo.input` joins `Demo.pad`; `syncDemoInput` handles touch/mouse and family switches without changing the scene list. The "Hold {move} to play" hint follows the effective input. Clips keep following the real input.
58- **Hold to confirm on the pad** (Q59, user request, 2026-11-02): a face button now acts only when held until a ring has filled (`HOLD_SECONDS` = 0.5 in `ui/padHold.ts`, pure, tested), and then (amended the same day, see "Hold to confirm acts when the ring fills" above: the moment the ring fills, not on release); releasing early, a swapped pad or a window that loses focus cancels. The ring (`.hold-ring` in `style.css`, a CSS conic gradient, no art; `ui/holdRing.ts` for the page, `PadOverlay.hold` for the demo's controller) fills clockwise from 12 o'clock round the button's picture on the action bar, in dialogs and on the banner. `PadTargets` gains `hold(face, progress)` and `holdEnd()`; `press` for a face button is delivered when the ring fills (`ui/gamepad.ts`; first built as on release); the other buttons (d-pad, shoulders, View, R3, Start) stay instant, and touch, mouse and keyboard are unchanged. Demo: the confirm face button (Cross / A at the bottom; a Nintendo pad's A on the right), held, starts play; other face buttons no longer end it, and the hint reads "Hold {button} to play" whenever the demo is shown for a controller (a detected one, or one picked with the demo's input button). The waking press still only shows the cursor.
59- **Controller demos and clips** (Q58, 2026-11-02): while a pad is in use, the demo shows a virtual controller (`ui/padOverlay.ts`; first CSS shapes with Kenney Input Prompts pictures, since Q63 a line drawing with the pictures on it: d-pad, face buttons, shoulders, right stick, Start) lighting the pressed buttons and a dashed cursor on the board instead of the finger, and the dialogs' clips do the same for the finger kinds (`FINGER_KINDS` in `ui/clip.ts`; a clip switches finger or controller at its next loop, and reduced motion hides the controller like the finger). The pad has its own scene list (`PAD_DEMO_ORDER`, built by `padDemoOrder` in `ui/padDemo.ts`): the cursor, Move, Bomb, Wait, L1, R1, the stick, Start, then the touch demo's gameplay scenes without the touch-only ones (long-press bomb, auto-move, the top bar, "What is that?") and the charge swap (`PAD_LATER` in `sim/demo.ts`). `ui/padDemo.ts` (pure, tested) turns a turn's action into pad presses (`padPlan`, `cursorPath`, `pressPart`, `padHops`). Scenes carry an optional `padCaption` with `{dpad}`, `{move}` ... pictures (`padCaptionHtml`), redrawn if the kind of pad becomes known mid-scene. The two lists keep separate saved places and switch only at the next scene. Almanac Tests tab: a "Demo controller" sample. Ending the demo during the R1 scene no longer leaves "What is that?" on. Art provenance: 36 more Input Prompts files (the controller outline was first noted as hand-made; the Q63 line drawing replaced it).
60- **Autopilot replaces the hoover, sim part** (Q73, user request, 2026-11-02; supersedes Q56 below): the turnless `hoover` action is gone (`canHoover` / `hoover` removed from `sim/turn.ts`, `test/hoover.test.ts` deleted). New pure `sim/autopilot.ts`: `autopilotTargets` (every drop and uncovered gem) and `autopilotPlan` (the next ordinary move toward the cheapest order through them, fewest total turns, exit last; targets on the way count as free; waits for crumbling crates; re-planned every turn with `safeStep`). Tests `test/autopilot.test.ts`; test scenes `testAutopilot` and `testAutopilotCrates`. **SIM_VERSION 42 to 43** (a record holding `hoover` can no longer replay).
720cc9d3 2026-11-03 Pavel Safronov61- **Autopilot, UI part** (Q73, user request, 2026-11-02): `autopilotTick` in `main.ts` replaces `autoFinish`. When the last enemy dies it shows the note `#autopilot` ("Autopilot: cleaning up" / "waiting for the crates" / "waiting for the bombs" / "off to the exit"; top centre, not a popover, `role="status"`, with the Esc cap or the L1 picture and a Stop button), waits `AUTOPILOT_START_SECONDS` (1.0), then plays `autopilotPlan(state, predictDanger(state))` every `AUTOPILOT_STEP_SECONDS` (0.4, was 0.25 until Q89) as `auto` turns, pausing while a dialog or offer is open. Stops: Esc, L1, the Stop button, turning the setting off, or a stall (6 waits in a row, not counting waits while a bomb or flame is on the board, or no safe turn: toast "Autopilot stopped / Your turn"). `boardLocked()` makes the board ignore taps, keys, the action bar (dimmed by `body.autopilot`) and the pad's cursor and buttons while it walks; looking around, dialogs, the menu and the fullscreen button still work; `act()` has a backstop. `cursorWanted` (`ui/padTiles.ts`) takes an `autopilot` flag (tested). The setting is "Autopilot" (input `autopilot`), still stored under the old `autoFinish` key.
92cc4ee3 2026-11-02 Pavel Safronov62- ~~**The level finishes itself** (Q56, user request, 2026-11-01): once the last enemy is gone, the new turnless action `hoover` (`canHoover` / `hoover` in `sim/turn.ts`) gathers the coins, charges and uncovered gems, then `autoFinish` in `main.ts` walks to the exit with auto-move, waiting for crumbling crates. Setting "Finish the level for me" (on by default). Rules version unchanged (a new action; old records replay as before).~~ Superseded by Q73 above.
63- ~~**Fullscreen from the first tap, click or key** (Q57, user request, 2026-11-01): `startFullscreen` in `main.ts`; setting "Start in fullscreen" (on by default).~~ Superseded by Q70 above.
ebcd0a8f 2026-11-02 Pavel Safronov64- **Controller support, stage 1** (Q29, 2026-11-01): the pure core, not yet wired in: `ui/padMap.ts` (gamepad snapshot to intents, with repeat, stick hysteresis, deadzone, controller family) and `ui/spatial.ts` (directional focus), with tests.
aef53511 2026-11-02 Pavel Safronov65- **Controller support, stage 2** (Q29, 2026-11-01): board play with a gamepad, wired in: `ui/gamepad.ts` (reads the first standard pad, routes intents to the game), the demo's scenes can be switched with the d-pad, and a face button, LB or Start ends it. Board play is "tile first" (below): LB puts away "What is that?" or what is left picked and returns the cursor to the player's tile, RB and View are "What is that?".
ebcd0a8f 2026-11-02 Pavel Safronov66- **Controller support, stage 3: dialogs and the banner** (Q29, 2026-11-01): a whole run is playable by pad. A dialog's footer buttons sit on the face buttons with their pictures (primary on Cross, the others on Triangle then Square, the one that leaves on Circle, which closes any dismissable dialog); where they do not fit, or the body has controls, a d-pad selector (`body.pad .pad-sel`, yellow outline) moves over the body's elements and the footer and Cross presses the focused one. Gem offer and shop cards: moving selects (and plays the clip), Cross takes (the shop: Buy). LB/RB switch almanac tabs, the right stick scrolls the body, the death/cleared/victory banner's buttons are on Cross, Triangle, Square, and the seed field is skipped. `ui/padDialogMap.ts` (pure, tested) and `ui/padDialog.ts` (DOM glue, watches the dialog with a MutationObserver so rebuilt bodies keep the selector); `dialog.ts` gains `dismissDialog()` and a `dialogopen` event.
aef53511 2026-11-02 Pavel Safronov67- **Controller board play, tile first** (2026-11-01): after trying the aim / step / cycle models, a cursor tile: the d-pad moves a dashed square between the actionable tiles (all lit blue; `ui/padTiles.ts`, pure), a line over the action bar lists what the tile offers per button with a faded ghost of the result, and the face buttons (Cross Move, Square Bomb, Triangle Charge, Circle Wait on your own tile) do it at once. Buttons that cannot be used there are greyed on the action bar, ones that would cost a life get a red outline and a warning mark (`isDeadly`). LB returns it to the player's tile, RB and View are "What is that?". The cursor is always on while the pad plays the board, resting on the player at the start of each turn (`restingCursor`, `cursorWanted` in `padTiles.ts`; Pavel, 2026-11-01). The left stick does nothing (`LEFT_STICK_ENABLED = false`, code kept); a diagonal d-pad release no longer fires a step. Removed: `padCycle.ts`, the cycle and step aims. `View.lit` and `View.ghost` in `render/board.ts`.
68- **Controller hint for L1 and R1** (2026-11-01): a small legend above the cursor's label shows the shoulder buttons' pictures (L1 / LB / L, R1 / RB / R; `shoulderGlyph` in `ui/padGlyph.ts`, six more Kenney Input Prompts files) with what they do: L1 "Back to you", "Cancel" (a pick or the flag is set) or "Stop asking" ("What is that?" is on), dimmed when there is nothing to undo; R1 "What is that?". Text chosen by `l1Hint` in `ui/padTiles.ts`; the element is rebuilt only when its text changes.
ebcd0a8f 2026-11-02 Pavel Safronov69- **Controller glyphs on the action bar** (Q45, 2026-11-01): while a controller is in use, Move/Go, Bomb, Charge and Wait show the pad's own button (PlayStation Cross, Square, Triangle, Circle in the colour variants; Xbox and other pads A, X, Y, B; Nintendo pads their own letters by position, so the bottom button shows B; Kenney Input Prompts) beside the icon, in place of the keyboard hint, and go back to the hint on a key or a click. The cursor's label shows the same pictures before each line, and a cursor tile where everything possible costs a life is drawn red (`cursorDeadly` in `ui/padTiles.ts`). `ui/padGlyph.ts`; `padFamily` knows 'nintendo'.
70- **Wall Pass renamed Crate Pass** (user request, 2026-11-01): it walks through crates, not walls. Display text only; the internal key stays `wallPass` and the sprite stays `powerup_wall_pass`.
1f0038ac 2026-11-01 Pavel Safronov71- **The in-game menu no longer carries the Kenney credit** (user request, 2026-10-31); it stays in the README.
b8849d36 2026-11-01 Pavel Safronov72- **A demo scene for rubble, and a timeline on every scene** (user request, 2026-10-31): the new `rubble` scene starts with a pillar already cracked and plays until the ceiling falls, then two turns of waiting to see the rubble (`SceneDef.maxSteps` and `tail`; the Acid scene ended when the pillar cracked, which is why the Almanac's Rubble clip never showed any). A scene now records its `moment`. A bar under the demo's caption and under each dialog's clip (`ui/timeline.ts`) fills a turn at a time, with a mark at the moment.
bb3823d2 2026-10-31 Pavel Safronov73- **Two copies of the game** (user request, 2026-10-31): the released one (built from a git tag, `/explodorama/`) and a **next** copy built from `main` (`/explodorama-next/`, deployed with `fw deploy --as explodorama-next`; tab title "EXPLODORAMA! (next)"). Each has its own saves, options, scores and last-played version (`explodorama-next.*` keys), so a rules change on `main` never drops a released run. The released game's menu has a **Try it early** link and its Changes dialog a **Coming next** teaser (read from the next copy's `next.json`); the next copy's Changes dialog lists **Not released yet**. A run finished on the next copy is marked **Early adopter** on its board and counted in one shared key (`explodorama.earlyRuns`) the released copy shows in its menu. Developer mode is separate and works on either.
74- **A bomb two of your actions could handle asks which** (user request, 2026-10-31): with Kick and Bomb Pass, a tap or arrow key on a bomb next to you offers Kick or Walk onto it (the Detonator's Set it off too). Bomb Pass alone now walks onto the bomb on a tap, which was refused before.
75- **A tap on a crate walks to the tile beside it** (2026-10-31); with Run, a crate two tiles away did nothing.
76- **A charge pickup while carrying a Freeze** offers a third choice: use the Freeze, then take the new charge (new action `fireCharge`; a charge that needs aiming can't be used on the spot, so only Freeze).
77- **Only a click or tap ends the demo**; keys no longer do (Ctrl or Shift started the game). New shuffle button, kept across visits (`explodorama.demoShuffle`).
78
7ce1fb51 2026-10-23 Pavel Safronov79### Added
80
1f0038ac 2026-11-01 Pavel Safronov81- **Oil is slippery** (user request, 2026-10-31; `SIM_VERSION` 41): landing on an oil tile after a step or a run, the player slides on in the same direction over every oil tile of the line and stops on the last one (`oilSlide` in `sim/state.ts`), short of a bomb (unless Bomb Pass) or an enemy, and on the open exit. A diagonal step, Slide and Teleport don't start one. What lies on the way is picked up; flame on the way burns the player (as with Slide), and flame where it ends does too. Every enemy but the flying Ghost and Wisp (`FLIES`) slides the same way: planning a step onto oil announces the whole slide as one planned move (`moveTiles` now returns every tile of a move; `stillPossible` re-checks a kept plan against the current oil), and the arrows show it as a doubled arrow. A slide through the player's tile catches them there. New event `oilSlid`, new demo scene `oilSlide` (also the Almanac's Oil clip), texts in the Oil entry and an enemy's info.
5607bea2 2026-10-31 Pavel Safronov82- **Semver releases and an in-game list of changes:** the game's version is 0.1.0 (the base); the menu shows it with the rules version, and tapping it lists every release. A returning player is shown what came after the version they last played, when the opening demo ends.
83
84## [0.1.0] - 2026-10-31
85
86The base: everything below.
87
88### Added
89
e3d8dc49 2026-10-27 Pavel Safronov90- **Deadly moves are marked:** Wait turns red when waiting would cost you a life, and with a button picked, a tile that would is red with a cross. Taps, keys with nothing picked, the long press and auto-move refuse such a move (the tile flashes red); the button then the tile still makes it.
91
6c3fcc31 2026-10-26 Pavel Safronov92- **Demo scenes for the board objects** (hiding in a bush, a bush fire, metal stopping flame, an oil spill, crossing spikes, a barrel going off), and a **Board** tab in the almanac listing crates, pillars, every object and rubble, with clips.
5f066960 2026-10-26 Pavel Safronov93- **Board objects:** bushes (they hide you from chasers, and burn a bush a turn), metal crates (nothing breaks them), oil spills (flame burns a whole spill at once), spikes (up every other turn) and oil barrels (flame bursts one: oil round it and a blast the next turn), each from its own level on. Version 37: runs saved before don't resume.
94- **The Acid charge:** a bomb that cracks pillars; a later blast breaks a cracked one, and 4 turns on the ceiling round it falls as rubble for good, crushing what is under it. Two new ways to lose a life: crushed, and walled in (trapped).
e6bb7c42 2026-10-25 Pavel Safronov95- **TNT**, a power-up worth two Fire +1s, and **a limit of 5 on bombs, blast and fuse**; a power-up with no room left isn't offered, and cards show the limit. Version 34.
96- **Bigger boards for later levels:** from 9 × 11 up to 15 × 21, seen through the same 9 × 13 tiles on every screen, scrolling with you, with arrows at the edge pointing to enemies, bombs, the exit and the gem out of sight. Enemy counts and par grow with the board. Version 32: runs saved before don't resume.
97- **Bigger boards for later levels:** from 9 × 11 up to 15 × 21, seen through the same 9 × 13 tiles on every screen, scrolling with you, with arrows at the edge pointing to enemies, bombs, the exit and the gem out of sight. Enemy counts and par grow with the board. Version 32: runs saved before don't resume.
0bfdc8e6 2026-10-25 Pavel Safronov98- **A demo scene for the charge swap:** carrying a Pierce, the player picks up a Nuke, and the finger takes it in the choice that opens.
d3e4ed26 2026-10-25 Pavel Safronov99- **One charge at a time, used when you choose:** a charge button beside Bomb (or V) puts down a Pierce, Power or Nuke bomb, fires an ICBM, freezes the enemies or places a Decoy; Bomb always places a plain bomb; a Shield is raised with it too and stays up until something hits you, and a Decoy is put up to 3 tiles away in a straight line and lasts until the level ends or something reaches it. The charge button is always there (an empty slot with none). Picking up, choosing or buying a different charge asks: keep yours and sell the new one, or take it and sell yours. Ends the Nuke trap, where a Nuke forced on every bomb made a level impossible. Version 29: runs saved before don't resume.
100- **The balance lab** (for development): bots play thousands of games on the real rules to measure what each power-up does (`npm run balance`, reports in `docs/balance/`).
565a6873 2026-10-25 Pavel Safronov101- **Four new enemies:** the **Sprinter** (rests, then dashes 2 tiles), the **Ghost** (every other turn, chasing you through crates), the **Wisp** (wanders through crates) and the **Hunter** (always chases). A new type now comes every 3 levels, so a run meets all seven. Version 28: runs saved before don't resume.
0b63d158 2026-10-25 Pavel Safronov102- **A frame-rate meter** (`?fps`), and `?gl=0`, `?ratio=1` and `?aa` to find what makes a device slow.
103- **Sounds and vibration:** Kenney's sound effects (and a few made with ZzFX) for bombs, blasts, enemies, pickups, the gem, the exit, hits and a cleared level, timed with the animations; buttons click. Phones that can (Android) vibrate for blasts, hits and pickups. Both can be switched off in the menu. The demo and the clips stay silent.
104- **Coins for every cleared level** (2, and 5 more within par), coins from enemies more often (about 1 a kill), and **cheaper shop prices** (Bomb +1 4, most abilities 6, Heart 12, charges 3–6, a restock 1): the first shop now buys two to four things. Version 27: runs saved before don't resume.
e78b7781 2026-10-25 Pavel Safronov105- **The shop**, after every 3rd level: 4 power-ups and charges, priced by rarity, with a restock that gets dearer. Version 26 (with Diagonal widening Teleport): runs saved before don't resume.
106- **New power-ups: RPG** (fire a bomb as far as it flies), **Proximity alert** (your bombs go off when an enemy is in reach) and **Slide** (slide until a wall, crate or bomb), and a new charge, **ICBM** (3 launches of a bomb that goes off where it lands). With Run, Teleport reaches 4 steps; with Diagonal, its reach is a square. Version 24: runs saved before don't resume.
32dd53cd 2026-10-25 Pavel Safronov107- **The "Ouch!" banner replays your own last turns** before a death. The gem's offer plays a clip of the power-up you look at, and almanac entries open their clip.
108- **Clips in the info dialogs:** most of them play a short scene of what they describe, new every loop, with a finger showing how for the actions and the power-ups you work yourself.
ba8e4ea0 2026-10-27 Pavel Safronov109- **Report a bug** in the menu: an email to the game's bug-report address (no account needed), filled in with the game's version, the device and the run, so it can be replayed.
0b25f1ef 2026-10-24 Pavel Safronov110- **A version number**, at the bottom of the menu and near the top of the README. It is the
111 rules version (`SIM_VERSION`), so it changes exactly when old saved runs stop resuming. The
112 menu also shows the commit the game was built from and links to the source code.
0580e85e 2026-10-24 Pavel Safronov113- **A high-score board** in this browser: every finished run, ranked by how far it got, then
114 coins, with enemies killed, turns, how it ended, the power-ups held and the seed. A global
115 board and a daily dungeon are planned.
116- **Game over** offers the same dungeon again or a new one, and the New run dialog has an
117 optional seed field, to share or replay a dungeon.
00ad7d0a 2026-10-24 Pavel Safronov118- **The board and the turn.** A 9 × 11 board with a stone outer wall, indestructible pillars
119 (their colour changes from level to level) and wooden crates; the whole board fits the screen. Each turn the player picks one action, then enemies step, bombs count down and
7ce1fb51 2026-10-23 Pavel Safronov120 explode, and enemies show their next step.
121- **Bombs** whose fuses count down with the player's moves, chain reactions, and a danger
122 preview that shows what will burn before an action is committed. Flame lingers for one turn.
123- **Lives.** A death restarts the level with the same layout; with no lives left the run ends
0580e85e 2026-10-24 Pavel Safronov124 and shows its seed. The banner says how and where you died.
7ce1fb51 2026-10-23 Pavel Safronov125- **Seeded levels.** Every random choice comes from the seed, and every run is recorded as its
126 seed plus its actions, so it replays exactly.
127- **The exit door**, hidden under a crate and locked until every enemy is dead. Flaming it lets
128 out 3 enemies. A par turn count, with a 5-coin bonus for beating it.
129- **Enemies:** Blob, Seeker and Drifter. Each commits to 3 moves ahead, shown as a fading column
130 of arrows. Coin and charge drops; drops never stack on one tile.
52d68b59 2026-10-24 Pavel Safronov131- **Charges**, dropped by enemies, that work as soon as you pick them up: Pierce, Power and the
132 new Nuke change your next 3 bombs; Shield blocks the next hit; Freeze freezes every enemy for
133 3 turns; Decoy leaves a copy of you.
134 The top bar shows what each still has to give.
135- **Power-ups:** Bomb+, Fire+, Fuse+, Run, Detonator, Wall Pass, Bomb Pass, Flame Pass, Star,
136 Heart, Coin bag, Kick, Throw, Teleport and Diagonal. A death costs only the life: every power-up
137 is kept.
138- **A gem on every level**, hidden under a crate. Taking it offers 5 different power-ups, and
139 you choose one (no turn passes). Common power-ups are offered more often than rare ones, and
140 ones you already hold aren't offered.
00ad7d0a 2026-10-24 Pavel Safronov141- **The 20-level run** with a victory banner at the end.
7ce1fb51 2026-10-23 Pavel Safronov142- **Mid-run saving** after every action, in the browser. URLs with test parameters (`?seed`,
18ff790e 2026-10-24 Pavel Safronov143 `?level`, `?charges`, `?dev`, `?immortal`) never load or overwrite the save.
7ce1fb51 2026-10-23 Pavel Safronov144- **Touch controls:** tap a neighbouring tile to step, press and hold one to bomb it, tap the
145 player to wait.
146- **Auto-move:** tap a far tile to set a flag; Go (or tapping the flag) takes one safe step
147 along the way. Once every enemy is gone, the player walks there alone, one step a second.
148- **A menu** (top right, or Esc) with the level, the seed, New run, the Kenney credit and an
149 almanac of power-ups, charges and enemies.
150- **"What is that?"** — the **?** button (or the ? key), then a tap on anything, explains it;
151 things you can walk to offer **Walk there**.
00ad7d0a 2026-10-24 Pavel Safronov152- **New run modes:** Developer and Immortal.
52d68b59 2026-10-24 Pavel Safronov153- **Pickup dialogs:** the first pickup of each kind of action charge in a run opens a dialog
154 saying what it does.
7ce1fb51 2026-10-23 Pavel Safronov155- **Animation** for the player, enemies, bombs, crates, flame, drops, power-ups, top-bar numbers
156 and dialogs.
157- **Art** from Kenney's New Platformer Pack, UI Pack, UI Pack: RPG Expansion, Game Icons and
158 Board Game Icons (all CC0). Power-ups that improve something get a green modifier badge.
fa3e81a7 2026-10-24 Pavel Safronov159- **A demo before the game:** scenes made up on the spot from the real rules, showing every
160 feature on the board — bombs, watching the enemies' arrows, escapes, chains, lingering flame,
d5e3ad4d 2026-10-24 Pavel Safronov161 the enemy types, drops, the gem, each power-up and each charge, the exit — alternating with the
162 ways to die (into a blast, not far enough, blocked in, a chain, an enemy, and a couple of funny
36c5d6a2 2026-10-24 Pavel Safronov163 ones), each with a caption and an icon, until you tap. Each scene gets to its point 3 to 6
164 turns in, and a finger plays every turn on the real action bar — taps with a ripple, a long
58f1e700 2026-10-24 Pavel Safronov165 press for a bomb, a button then a tile, Go — after five opening scenes on the controls alone. The player wears a "You" tag in the demo, and
e3384c6b 2026-10-24 Pavel Safronov166 each scene's finger starts beside them. The top bar shows in the demo too, with a tour of its
167 items and a scene on using "What is that?" on an enemy. The demo plays on an old CRT TV, made
168 with LittleJS post-processing and a screen overlay.
52d68b59 2026-10-24 Pavel Safronov169- **Installable** as an app (Chrome, Edge, Android, iPhone / iPad), and playable offline once
170 loaded.
7ce1fb51 2026-10-23 Pavel Safronov171- **Deployment** to GitLab Pages on every push to the default branch, after the tests and the
172 build pass.
173
174### Changed
175
05e79f5f 2026-10-27 Pavel Safronov176- **Bushes are tall grass** from Kenney's Foliage Sprites, tinted green and outlined like the rest of the art, in four shapes picked by tile so a clump doesn't repeat one picture. Credited in the menu.
177
e3d8dc49 2026-10-27 Pavel Safronov178- **The Acid bomb is an area weapon, like the Nuke:** it burns every tile within 2 steps, through crates, and cracks every pillar in that area, diagonal ones too (it used to burn a cross and crack only a pillar an arm of it ran into). Version 40: runs saved before don't resume.
179
180- **Tapping yourself no longer waits** (it could kill you by accident); use the Wait button or Space.
181
6c3fcc31 2026-10-26 Pavel Safronov182- **Boxed in costs a life:** with nowhere to step and nowhere to put a bomb, and nothing left on the board that could change it (a Teleport into a gap between crates, rubble falling round you), you lose a life instead of being stuck for good. Version 39: runs saved before don't resume.
5f066960 2026-10-26 Pavel Safronov183- **The danger overlay marks a bomb's tiles from the moment it is placed**, as a red outline until its last two turns, however long the fuse.
184- **Shield and Flame Pass work by themselves while carried:** no button to press. A hit of their kind uses them up (Flame Pass after 3 fire hits) and the charge slot empties. Version 38: runs saved before don't resume.
a313eb7d 2026-10-25 Pavel Safronov185- **Diagonal no longer squeezes** between two blocked tiles: one of the two tiles beside a diagonal step must be open. The squeeze was most of what made Diagonal so strong. Version 36.
fcf44f32 2026-10-25 Pavel Safronov186- **Flame Pass and Teleport are charges now**, not power-ups: Flame Pass, raised with the charge button, takes the next 3 fire hits; Teleport gives 3 jumps from the charge button. Each alone used to win the game.
187- **A death drops the charge you carry** where you fell, to pick up again on the retry.
188- **Board sizes fitted:** up to 13 × 17, so late levels take about as long as early ones; slightly more enemies on late levels. Version 35.
e6bb7c42 2026-10-25 Pavel Safronov189- **The gem's and the shop's cards show what they change:** "Blast 2 → 3", "Bombs 1 → 2", "Lives 3 → 4"…
190- **Auto-move's way** shows as a line of arrows through its blue tiles, one per move, and only the tiles you will land on are lit: with Run, every other one.
191- **Shield and Freeze ask for a confirmation:** the charge button picks them; tap yourself (or press it again) to use them. Version 33.
0bfdc8e6 2026-10-25 Pavel Safronov192- **The demo's title is on top,** above the TV, and the **menu is compact:** Resume and New side by side, then Almanac, Scores, Demo and Bug in one row.
d3e4ed26 2026-10-25 Pavel Safronov193- **Proximity alert:** a bomb now goes off only when an enemy is right next to it, not anywhere in its reach, so a bomb dropped between you and an enemy no longer blows up next to you.
33a0256b 2026-10-24 Pavel Safronov194- The demo plays its scenes in one order, numbered, with ◀ ▶ (and ← →) to go through them and ↺ back to the first; it carries on where it was, after a reload too.
195- The menu can play the demo again (**Watch the demo**), and names the run's modes in one short line.
e3384c6b 2026-10-24 Pavel Safronov196- The game is now called **EXPLODORAMA!**
00ad7d0a 2026-10-24 Pavel Safronov197- One board, 9 × 11 with 20 levels (it was a choice with the original's 31 × 13 and 50 levels),
198 and crates always crumble once the enemies are gone (it was an option). The New run menu has
18ff790e 2026-10-24 Pavel Safronov199 just two modes: Developer and Immortal (nothing kills you, so you can reach the
00ad7d0a 2026-10-24 Pavel Safronov200 end, but an Immortal run earns no achievements).
201- A Developer run's achievements count, marked with a red border; its victory banner is framed
202 in red.
203- The demo's title uses a readable font.
7ce1fb51 2026-10-23 Pavel Safronov204- The placeholder shapes were replaced with Kenney sprites.
52d68b59 2026-10-24 Pavel Safronov205- The action bar is now only Move, Bomb and Wait. Upgrades make Move and Bomb do more instead of
206 adding buttons, and charges have no buttons at all.
7ce1fb51 2026-10-23 Pavel Safronov207- Kick, Throw and Teleport became power-ups kept for the whole run (they were charges).
208- Freeze now holds enemies for this turn and 3 more.
209- The Skates power-up is now called Run.
210- The outer wall is drawn as a bordered stone frame.
52d68b59 2026-10-24 Pavel Safronov211- The exit is a short, one-tile arched doorway instead of a squeezed two-tile door.
212- Run is no longer guaranteed on level 1 or 2; it can be offered by any gem.
213- Auto-move's way is shown as blue tiles instead of a flag and dots, and the Go button keeps
214 the walk icon. Setting the way takes the first step at once.
215- The top bar has a fixed number of rows, so the board no longer moves as things are picked up.
216- The Shield's ring is smaller and moves with the player.
217- Stepping onto the exit walks into the doorway before the jump (it used to happen instantly).
00ad7d0a 2026-10-24 Pavel Safronov218- The player walking into flame is animated (they used to appear on the tile at once). Every
219 move on screen now comes from the change of state, so nothing can skip it.
fa3e81a7 2026-10-24 Pavel Safronov220- An enemy walking into flame finishes its step before it dies (it used to die on the new tile
221 without moving).
0580e85e 2026-10-24 Pavel Safronov222- Saved runs from before the gems can't be resumed (`SIM_VERSION` 22).
39c26813 2026-10-24 Pavel Safronov223- Developer mode now only adds an extra gem next to the player on every level (the level's own
224 gem stays hidden); it no longer gives every ability, extra stats or unlimited charges.
6e94f995 2026-10-24 Pavel Safronov225- Developer mode's extra gem is a **rainbow gem** that turns and glitters, so it can't be taken
e3f29330 2026-10-24 Pavel Safronov226 for the level's own, and it offers **every power-up you don't have yet, and every charge**
227 (Freeze, Decoy and the rest, to test them at once) instead of 5 power-ups (`SIM_VERSION` 23).
6e94f995 2026-10-24 Pavel Safronov228- The board is drawn with **WebGL** again (it was Canvas 2D).
7ce1fb51 2026-10-23 Pavel Safronov229
230### Removed
231
52d68b59 2026-10-24 Pavel Safronov232- The Line charge, and charges as actions with their own buttons and keys.
233- The explanation strip above the action buttons. Nothing covers or resizes the board during
234 play; **?** then a button explains it.
7ce1fb51 2026-10-23 Pavel Safronov235- The Fuse +1 / −1 charges.
236
237### Fixed
238
e6bb7c42 2026-10-25 Pavel Safronov239- With Diagonal, auto-move cuts corners with diagonal steps instead of walking round them.
240- The almanac's tabs fit a phone's width, and entries no longer show through them when scrolled.
241- A swipe on the board, meant to look around, made a move (a teleport, say). Now dragging the board moves the view instead, until your next turn.
242- The shop's coins stay in view while its items scroll.
d3e4ed26 2026-10-25 Pavel Safronov243- A run resumed with a gem's choice or the shop open lost its dialog when the opening demo ended; it opens again now.
ac534e57 2026-10-25 Pavel Safronov244- Dialogs never run off the bottom of a phone's screen: only their middle scrolls, and their buttons always show.
33a0256b 2026-10-24 Pavel Safronov245- Long dialogs (the almanac, the rainbow gem's offer) scroll with a finger again.
e78b7781 2026-10-25 Pavel Safronov246- Every dialog opens scrolled to the top: it used to keep where the last one was scrolled to.
0b63d158 2026-10-25 Pavel Safronov247- The game ran at under 1 frame a second in Chrome on Android: the demo's CRT effect copied every frame, in play too. It is now off outside the demo, and copies on the graphics chip in the demo (LittleJS 1.28.0); and WebGL's antialiasing, which held Chrome on Android to 12 fps, is off.
248- Developer mode is described in one line in the game.
e3384c6b 2026-10-24 Pavel Safronov249- The player is drawn a little higher, so their feet never touch the line between tiles.
250- A top-bar number bumping at the edge of its row (Turn) is no longer cut off.
7ce1fb51 2026-10-23 Pavel Safronov251- Moving off the auto-move path now clears the flag.
52d68b59 2026-10-24 Pavel Safronov252- Enemies let out by flaming the exit or the gem are no longer killed at once by that flame,
253 which lingers a turn; a new explosion still kills them.
254- The last enemy's charge is always one that lasts (Pierce, Power, Nuke or Shield), so it isn't
8da5a7c0 2026-10-24 Pavel Safronov255 wasted; and no Decoy, Freeze or Shield drops while one already lies there or is working.
52d68b59 2026-10-24 Pavel Safronov256- Enemies on the same tile no longer move as one: each plans around the others, so they spread out.
257- A Freeze drop on the board crashed the game (its icon was the wrong size).
28670c3e 2026-10-24 Pavel Safronov258- Drops no longer land on the uncovered exit.
259- Auto-move uses Run and Teleport: each move goes as far toward the target as it can (a
260 neighbour is still a step).
00ad7d0a 2026-10-24 Pavel Safronov261- Once every enemy is gone, auto-move walks twice as fast (two steps a second).
262- The Move button's key is M (like B for Bomb); with Diagonal, Q E Z C step diagonally at once.
28670c3e 2026-10-24 Pavel Safronov263- With Diagonal, tapping a diagonal neighbour steps there (it used to walk round the corner).
264- Throw no longer goes over a pillar or the outer wall (it still goes over crates, bombs and
265 enemies).
52d68b59 2026-10-24 Pavel Safronov266- An error while drawing a frame or playing a turn no longer freezes the game; it is logged and
267 play goes on. Under `npm run dev`, the game's logs and errors, from any device, show in the
268 terminal.
269- The run's mode tags moved to the top bar's third row, so they can't push the level, enemies
270 and coins out of sight.
271- Auto-move no longer walks over the open exit on the way somewhere else (which ended the
272 level early).
7ce1fb51 2026-10-23 Pavel Safronov273- Thin light seams no longer run through the stone outer wall.
52d68b59 2026-10-24 Pavel Safronov274- Top-bar items (hearts, level, enemies and so on) no longer pulse on every update after they
275 have changed once; they pulse only when their value changes.