explodorama / commit
Plan §19: balance lab, bigger boards, hazards, Acid bomb, Gauntlet
PLAN.md | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ decisions.md | 34 +++++++++ 2 files changed, 267 insertions(+) diff --git a/PLAN.md b/PLAN.md index f32bb1b..57a19ce 100644 --- a/PLAN.md +++ b/PLAN.md @@ -466,6 +466,8 @@ the former "Small" board (density 25%, enemies 2 + 1 per 4 levels up to 5, par 2 with no scrolling, and crates always crumbling once the last enemy is gone (§13b). The NES-size notes below (31 × 13, 50 levels, the side-scrolling camera) are kept as the history of the design; the board code for them was removed. +*Proposed 2026-10-24 (user):* bigger boards for later levels, scrolling — see §19.2. It would +undo the one-size choice above. - **Grid 31 × 13** like the NES: hard walls around the border, indestructible pillars at every even (x, y), soft blocks placed by seeded RNG at ~30–40% density, start corner (3 tiles in an L) @@ -1009,3 +1011,234 @@ tools/ compose-icons.sh (composed sprites and the app icons), sc long for an email link (over ~1,900 characters) stays out of the email and goes on the clipboard instead, and the email asks to paste it. + +--- + +## 19. Proposed features (user, 2026-10-24; to discuss, then prioritise) + +Five ideas from the user, worked out into proposals, then settled with the user (decisions marked +in each part). *Agreed 2026-10-24; order: the balance lab (19.1) first.* Nothing here is built yet. + +### 19.1 A balance lab: measuring what an addition does to the game + +**The question:** some power-ups feel overpowered (Flame Pass, Wall Pass, Bomb Pass), but by how +much? And would they be fairer as charges? Today that is judged by feel. + +**Why not search the whole game.** The sim is pure and deterministic (`step()`), so any game can be +played out in Node at full speed, with no browser. But a turn has about 5–20 possible actions +(moves, a bomb on each neighbour, the abilities' targets), and a level takes 40–100 turns: the game +tree has more than 10^50 leaves. Plain DFS or BFS over whole games is out of reach. Search works +well *locally*, over the next few turns, and that is how it is used below. + +**Proposal: bots play thousands of games, and we compare the numbers.** + +- **Bot players** (`tools/balance/`), each a function from a state to an action, using the sim's + own helpers (`predictDanger`, `playerPath`, `safeStep`): + 1. **Careful:** never steps into danger; walks to a crate or an enemy's path, bombs it, walks to + the nearest safe tile; otherwise waits. Cheap, predictable — a cautious beginner. + 2. **Searcher:** a depth-limited search over the next 3–5 turns (beam search: keep the best 50 + states at each depth), scoring states by kills, crates burned, the exit's distance, and + safety (how many safe tiles are reachable). This is where BFS / DFS fits: a few turns ahead, + on the real rules, pruned by the danger overlay. A decent player. + 3. **Reckless** (later): bombs often, escapes late — finds where a power-up rescues a bad player. + + Bots are not humans: a bot gains differently from a power-up than a person does. So the numbers + are for *comparing* (this power-up against that one, before against after), not as truths. +- **Experiments, paired:** the same N seeds (say 500) played twice, once as the baseline and once + with the change — a power-up held from level 1, a charge instead of the power-up, a different + drop rate or price. The same seeds on both sides take out the luck of the boards, so a few + hundred games show even small effects. Each experiment runs on all CPU cores (worker threads). +- **What is measured**, per level and over the run: + - **Survival:** levels cleared before game over; lives lost per level, by cause (blast, chain, + lingering flame, enemy). + - **Pace:** turns per level, the share cleared within par, coins earned. + - **Pressure:** turns spent standing in danger, close calls (out of a blast's reach on the turn + it goes off), turns with only one safe move. + - **Use:** how often the power-up or charge was actually used, and how often it saved a life + (the same seed and turn without it would have died: a counterfactual replay). +- **Structural measures, no bot needed:** on many random boards, from the player's tile, count what + a power-up changes outright. Examples: the share of bomb placements with an escape route + (Flame Pass makes it 100%, which shows why it feels free); tiles reachable in 3 turns (Wall Pass, + Bomb Pass, Run, Teleport); blast reach (Fire +1, Power). Deterministic and quick, a good first + report before the bots exist. +- **The report:** a table per experiment — each power-up's effect on levels survived and lives lost, + with a confidence interval, sorted strongest first — published as an HTML page (an artifact), and + kept in `docs/balance/` so a change can be checked against the last run. +- **Power-up or charge:** the rules get variant switches the lab can turn on (for example + "Flame Pass as a charge of 5 turns", "Wall Pass as 3 uses"), so the same experiment compares + the versions before the game commits to one. + +*Decided (user, 2026-10-24):* **the full version, with bots** (the structural measures come along +as its first report). Still open: which power-ups to measure first — the passes, given 19.5. + +### 19.2 Bigger boards for later levels + +**Today:** every level is 9 × 11, the whole board on screen at once (a choice made 2026-10-23). It +suits the first levels; later ones feel small. *This changes that choice.* + +**First proposal** (*superseded by the decisions below*): boards grow with the level, mostly +taller, since a phone is tall: + +| Levels | Board | On a phone (390 × 844) | +|---|---|---| +| 1–3 | 9 × 11 (as now) | whole board | +| 4–6 | 9 × 13 | whole board, tiles a little smaller | +| 7–10 | 11 × 15 | scrolls up and down | +| 11–15 | 11 × 19 | scrolls | +| 16–20 | 13 × 21 | scrolls both ways a little | + +- **Tile size:** a tile must stay big enough to tap (about 36 CSS px at least). Below that the board + scrolls instead of shrinking: the camera follows the player, eased, kept inside the board (the + NES-style camera, removed 2026-10-23, comes back in a vertical form). A desktop shows more. +- **Off-screen enemies:** a small arrow at the screen's edge for each enemy out of view, and their + count in the top bar as now, so nothing surprises the player from off screen. +- **Everything scales with the area:** enemies (about one per 20 open tiles), crates, par, and the + number of new objects from 19.3. Auto-move matters more on a big board. +- **Generation keeps its guarantees** (every tile reachable once crates are gone, the exit and the + gem under crates, nothing near the start), checked by the existing many-seed tests. + +*Decided (user, 2026-10-24), replacing the table above:* + +- **A fixed view, the same everywhere.** The game shows a window of the board with a set number of + tiles — proposed **9 × 13** (a portrait shape, about the phone's) — on a phone and on a desktop + alike, with bars beside it on a wide screen (as the demo's TV has). *9 × 13 agreed (user, + 2026-10-24).* Everyone sees the same + amount of board, so no screen gives an advantage, and a level plays the same everywhere. +- **Boards bigger in both directions**, growing past the view; the view follows the player, + eased and kept inside the board. +- **Indicators** at the view's edge for what is out of sight: each enemy (an arrow in its colour, + nearer ones bolder), and the exit and the gem once uncovered. Lit bombs and fires near the edge + too, since they can kill. +- **Size by "concentration"** (the user's idea, worked out below), instead of a size table. + +**Concentration: one number that sets how crowded a level is.** Today each level's enemy count is +a table (2, then one more every 4 levels). Instead: + +- A level's **threat** is the sum of its enemies' weights, each type weighted by how dangerous it + is (a Blob 1, a Seeker 1.5, a Hunter 2.5 …; first guesses, then measured by the balance lab: + how often each type kills the bots). +- **Concentration** = threat ÷ open tiles (the floor plus crates: everywhere an enemy could + eventually be). It rises with the level along a curve, for example from 1 per 25 tiles on level + 1 to 1 per 12 by level 20, then more slowly (for endless Gauntlet). +- The board size comes from the level; the enemies come from the size × the concentration. So a + bigger board brings more enemies, but the same crowding — and crowding goes up with the level. + Crates, hazards (19.3) and drops scale with the area the same way, each with its own density. +- **Fitting the curve:** the balance lab plays bots through levels and adjusts the concentration + curve until the bots' chance of clearing each level follows a chosen difficulty curve (say 95% + on level 1, 60% on level 20). Then "harder" means measurably harder. +- **How big a board gets** is then a question of time, not crowding: turns per level grow with the + area. Proposed: grow until a level takes about 3–4 minutes for a bot at a human's pace (roughly + 80–120 turns), which the lab can measure; a first guess is about 15 × 21. Smaller boards stay + for the first levels and as a pause between big ones. + +### 19.3 More on the board: hazards and objects + +**Goal:** more to plan around than crates and pillars. Every object follows the readability rule +(§4): visible from the start, behaving the same every time, in the danger overlay when it can +hurt, explained by "What is that?" and in a new almanac tab, **Board**. New ones arrive a few +levels apart, as enemies do, so each is met on its own first. + +Sprites: mostly from the New Platformer Pack, already used. Spills from the **Splat Pack**: 36 +white splats that can be tinted to any colour (oil, acid, water). *Approved (user, 2026-10-24), +and all the objects below are wanted.* + +| Object | What it does | Flame | Sprite | Proposed | +|---|---|---|---|---| +| **Oil spill** | Floor: anyone can walk on it. | Flame touching any part ignites the **whole connected spill** at once: it burns this turn and lingers next turn like flame, so a spill carries a blast round corners. Then it is gone. | Splat Pack, tinted dark | first | +| **Oil barrel** | Blocks like a crate. | Flame sets it off **next turn** (a 1-turn fuse, shown as a 1): a blast of reach 2, and it spills oil around it (more chains). | none in the packs — an open question; `block_strong_danger` or `block_exclamation` could stand in | first | +| **Bush** | Anyone walks through it. | Burns away, and **fire spreads** to touching bushes one turn later — a slow, visible fire front to outrun or to use. | `bush` | first | +| **Metal crate** | Blocks everything, like a pillar but anywhere. | Not hurt (even Pierce stops). Maybe Kick pushes it one tile (to discuss). | `block_strong_empty` | first | +| **Spikes** | Floor trap, up every other turn (shown, with the turns until it changes). Up, it hurts anyone on it, enemies too; enemies plan around raised spikes. | — | `spikes` / `block_spikes` | first | +| **Acid puddle** | Hurts anyone who ends a turn in it. Enemies avoid it. A bomb in it is a dud. | Flame dries it up. | Splat Pack, tinted green | second | +| **Water** | Not walkable for most; Ghosts and Wisps cross it. A bomb kicked into it fizzles. | Puts out an oil fire that reaches it. | `water` | second | +| **Conveyor** | Each turn it carries whatever is on it (you, bombs, drops, enemies) one tile along. | — | `conveyor` | second | +| **Ice** | Whoever steps on it slides until something stops them, like Slide; kicked bombs too. | Flame melts it to water. | `snow`-coloured tile | later | +| **Cracked floor** | Gives way after something has crossed it once: a pit no one can walk into (enemies that would fall die). | — | a dark tile, to find | later (ties to 19.4) | +| **Spring** | Throws whoever steps on it 2 tiles on, over anything. | — | `spring` | later | + +**Should bushes hide what is in them?** (The user asked for the options, 2026-10-24.) + +| Approach | For | Against | +|---|---|---| +| **A. Hide nothing:** a bush is see-through foliage, only a fire hazard. | Keeps "everything visible" (§4) whole; no surprise deaths. | Bushes add less: only the fire. | +| **B. Hide drops and gems:** treasure in the bushes. | A reason to burn or walk through them; no unfair deaths, since a hidden drop can't hurt. | Crates already hide the gem; similar. | +| **C. Hide enemies:** ambushes. | Tension; scouting matters. | Deaths the player couldn't foresee — the thing turn-based play is meant to avoid (§4). A hidden enemy's arrows would have to vanish too, so plans can't be read. | +| **D. Hide the player:** stealth. Chasers (Seeker's chase, Ghost, Hunter) lose you while you are in a bush and go to where they last saw you. | A new tactic; fair, since you know where you are; uses the enemies' plans. | Needs "last seen" in the enemy rules; enemies that wander aren't affected. | +| **E. Half-hide:** whatever is inside shows faint (as a Ghost in a crate does), arrows and all. | Atmosphere without hiding information. | Only a look; changes nothing in play. | + +*Decided (user, 2026-10-24):* **B + D, with E for enemies.** Bushes hide drops (something to +find) and hide the player from chasers (something to use), while an enemy inside shows faint, +arrows still visible — so nothing that can kill you is ever hidden. + +### 19.4 The Acid bomb: weakening pillars, bringing the roof down + +**Idea:** a bomb that eats into the pillars (the fixed grid of walls), so that enough damage brings +part of the ceiling down — a way to reshape the board, with a risk. + +- **The Acid charge**, like Pierce or Power: acid bombs (green; how many a charge gives, to tune — + the first guess 1). An acid bomb's flame works as usual and also **cracks** each pillar it + touches (a pillar stops flame, so it is the first pillar in each direction). Acid also leaves an + acid puddle (19.3) on its own tile for a few turns. +- **Cracked pillar:** cracked and green-stained. A **second hit** — any later blast that reaches it + — **breaks** it. *Decided (user, 2026-10-24): one acid bomb cracks, a second hit brings it + down.* +- **A broken pillar brings the roof down:** the 8 tiles around it show falling dust and a + countdown of **4 turns** (*user, 2026-10-24*; like a bomb's timer, and in the danger overlay). Then rubble falls: + anything still there is crushed — the player, enemies (a trap to set), drops, bombs — and the + tiles become **rubble: impassable for good** (no blast, Pierce or Wall Pass gets through), so + the board can't be opened up into one big room. The pillar's own tile becomes floor. + *Decided (user, 2026-10-24).* +- **Two new ways to die** (*user, 2026-10-24*): + - **Crushed:** standing under the rubble when it falls. + - **Trapped:** rubble can wall the player in. When the player can never again reach the exit or + every remaining enemy — not even by burning crates, only walls, metal crates and rubble + counting as permanent — the level can't be won, so it costs a life at once, rather than + leaving the player stranded. (An enemy walled off from the player, but reachable by flame, + still counts as reachable; the exact test is to settle when building.) The death banner + names it, and the "Ouch!" replay shows the fall. +- **Floor collapse instead** (an alternative, or later): acid on a floor tile makes it cracked + floor (19.3), which becomes a pit after one crossing. +- The outer wall never breaks. + +Still to settle when building: whether the second hit must be any blast (as written) or another +acid bomb, and how many acid bombs a charge gives. + +### 19.5 Gauntlet mode + +**Idea:** a second way to play. You start with a random loadout and nothing more comes: survive as +many levels as you can, each harder than the last. + +- **Choosing it:** the New run dialog gets a choice of mode — **Classic** (the 20-level run) or + **Gauntlet**. Developer and Immortal stay as options; an Immortal gauntlet would never end, so + Immortal is off for it (or its runs don't count). +- **The loadout:** drawn from the seed, so the same seed gives the same start (and a daily + gauntlet later is easy). To keep it fair, it is drawn to a **budget**, using the shop's prices as + value: for example 3 power-ups and 2 stacks of charges and a stat or two, worth about 40 coins in + all, so no start is far luckier than another. Later: picking it yourself (a draft — choose 1 of 3, + a few times). +- **Nothing more comes:** no gems, no coins and no shop, and enemies drop nothing. The charges + you start with are all you get, so each one is a decision. +- **Hearts:** one life back for every level cleared, up to the starting 3. Hearts are the only + thing that comes back. *Decided (user, 2026-10-24).* +- **Endless** (*decided, user, 2026-10-24*), **harder each level:** more enemies, faster types sooner (then the Reaper, once it + exists), bigger boards (19.2), more hazards (19.3). From the 20 levels of Classic it carries on + past them, the ramp continuing (enemy count, then hazard density). +- **Its own high scores:** a separate board, ranked by levels cleared, then by fewer turns; each + entry shows its loadout and seed. + +- **No passes in a loadout** (*decided, user, 2026-10-24*): Flame Pass, Wall Pass and Bomb Pass + never come in a gauntlet start. + +**The passes in the whole game** (*user, 2026-10-24*): they should either **leave the power-ups** +or **become temporary charges** (for example Flame Pass for 5 turns). Which one is the balance +lab's first experiment (19.1): the passes as they are, as charges of a few lengths, and gone, +compared on the same seeds. + +### 19.6 How these fit together + +- **19.1 first** helps the rest: it can tell whether the passes need nerfing, test a gauntlet + loadout's budget, and tune hazard density. +- **19.2 before 19.3:** more objects need more room. The concentration curve (19.2) is fitted + with the lab's bots, so 19.1 comes first there too. +- **19.4 needs 19.3's** acid puddles and (for the alternative) cracked floor. +- **19.5 uses all of them** for its ramp, but could start with what exists today. diff --git a/decisions.md b/decisions.md index 493901a..eb9e129 100644 --- a/decisions.md +++ b/decisions.md @@ -1814,3 +1814,37 @@ all read: - **Drops** follow the table's words: Sprinter and Wisp mostly a charge, Ghost coins, Hunter both. `SIM_VERSION` 28. Tests in `test/new-enemies.test.ts`. + +### 2026-10-24 — Five proposals written into the plan (PLAN.md §19) + +User request: think through five ideas, propose, and add them to the plan, to prioritise once the +plan is agreed. Written as §19, each with its open questions: a balance lab (bots and paired +experiments on the deterministic sim, since a full DFS/BFS of whole games is beyond reach: about +10^50 leaves; search is used a few turns ahead instead), bigger scrolling boards, hazards and +objects (oil, barrels, bushes, metal crates, spikes, then acid, water, conveyors, ice, cracked +floor, springs), the Acid bomb that corrodes pillars and brings the roof down, and a Gauntlet mode. +Two conflicts with earlier choices are flagged there, not settled: bigger boards undo the one-size +board of 2026-10-23, and bushes that hide things would break "everything visible" (§4). The +Splat Pack, which the user named, would be a new art pack. + +### 2026-10-24 — Answers on the §19 proposals + +The user's answers, recorded in PLAN.md §19: + +1. **Balance lab:** the full version, with bots. +2. **Boards:** a fixed view with the same number of tiles on every screen (bars beside it on a wide + one), boards bigger in both directions, a view that follows the player, and edge indicators. + On the user's question, a "concentration" scheme was proposed: enemies weighted by danger, + divided by open tiles, rising along a curve fitted by the lab's bots to a target difficulty; + board size then set by how long a level takes. The largest size is left to that measurement. +3. **Objects:** all wanted; the Splat Pack is approved. On hiding things in bushes, five approaches + were set out with their pros and cons; recommended: bushes hide drops and the player (from + chasers), and enemies inside show faint — to choose. +4. **Rubble:** crushes what is under it and stays impassable for good. Two new deaths: crushed, + and trapped (the level can no longer be won), which costs a life at once. +5. **Gauntlet:** one life back per cleared level up to 3, endless, and no passes in a loadout. The + passes in the whole game are to leave the power-ups or become temporary charges: the balance + lab's first experiment decides which. +- **Final answers (same day):** bushes B + D + E as recommended; the 9 × 13 view; one acid bomb + cracks a pillar and a second hit brings the roof down 4 turns later. The plan is agreed; the + balance lab comes first.