diff --git a/BUILD-RECORD.md b/BUILD-RECORD.md index 318ad1d..ca658df 100644 --- a/BUILD-RECORD.md +++ b/BUILD-RECORD.md @@ -1,13 +1,12 @@ -# BUILD RECORD — RC-0D193E "Build Angry Birds, Report Process" +# BUILD RECORD — "Build Angry Birds, Report Process" -- **RC:** RC-0D193E (tier: scout, owner: rc-ops, assigned: Hermie(s)) - **Worker:** Hermie (HANDS worker, Hermes Agent v0.19.1, default profile) - **Date:** 2026-08-28 (UTC) -- **Artifact root:** `/root/rc-0d193e-isle-slingers/` (this git repository) +- **Artifact root:** this git repository - **Result:** shipped — playable browser game + this build record. Test suites: **sim 15/15 PASS + page 7/7 PASS** (see §5; post-shipment fixes: bug #11 boot crash, bugs #12-13 physics+camera, bugs #14-15 - release+direction — all found by the Commander's playtest). + release+direction — all found in playtest). --- @@ -256,7 +255,7 @@ audio → UI → tests. Bugs found by the headless harness and fixed in order: order against a DOM stub built from the real `index.html` ids and plays a full click session headlessly. 12. **Inverted box-pair separation — forts self-destructed (found - post-shipment, Commander's playtest: "objects glitching like crazy, + post-shipment, playtest feedback: "objects glitching like crazy, bouncing around on their own", "unbreakable objects", "can't kill a pig").** `resolveBoxPair` pushed *resting* blocks **toward** each other: with `s = a.x < c.x ? -1 : 1`, `a.x -= s*ox*0.5; c.x += @@ -292,7 +291,7 @@ audio → UI → tests. Bugs found by the headless harness and fixed in order: Arms added: fort rest (test 14) — RED on the original solver ("L1: structure still moving at idle (max 76.5 px/s)"), GREEN after. -13. **Camera never showed sling and target together (Commander: "cannot +13. **Camera never showed sling and target together (playtest: "cannot see the entire playing field and have to guess where to sling the birds", sling "not visible anywhere").** Two framings, neither sufficient: aiming → camera at (480, 740), a 1280 px view showing @@ -312,7 +311,7 @@ audio → UI → tests. Bugs found by the headless harness and fixed in order: `e.y - r` while the level data and the integrity test treat `e.y` as the center — every mogg dropped 24-38 px on load, one more "objects moving on their own" moment.) -14. **Sling never lets go (Commander round 2: "sling never actually lets +14. **Sling never lets go (playtest round 2: "sling never actually lets go of bird when the bird is shot out").** Purely visual: `drawSling` drew the taut rubber bands toward the active bird whenever the bird existed — including while it was *flying* — so the @@ -321,7 +320,7 @@ audio → UI → tests. Bugs found by the headless harness and fixed in order: `bird.state === 'aiming'` (pouch or mid-drag); in flight the bands hang relaxed (the pre-existing else-branch). Arm 17 (page harness, `lineTo` recording) is RED on 2d9c8f47, GREEN after. -15. **Birds only launched backwards (Commander round 2: "Sling shot +15. **Birds only launched backwards (playtest round 2: "Sling shot only shoots backwards and not in the direction of the target").** Root cause in `main.js toWorld()`: the screen→world inverse was `(sx - VW/2) + cam.x` — it added the camera center but never divided @@ -350,7 +349,7 @@ audio → UI → tests. Bugs found by the headless harness and fixed in order: Process notes: - The headless harness caught **11 bugs pre- and post-shipment on its - own** (10 in dev + the page boot); the Commander's playtest then found + own** (10 in dev + the page boot); playtest then found **4 more** (#12-15) that the harness *could* have caught — the missing invariants were "the world is at rest", "the view shows the play", "the input maps where the player sees", and "the sling lets go". @@ -372,7 +371,7 @@ Process notes: ``` # play (any static server, or just open the file): -cd /root/rc-0d193e-isle-slingers +cd isle-slingers # repo root, after cloning python3 -m http.server 8000 # then open http://localhost:8000/ # or open index.html directly in a browser @@ -404,10 +403,10 @@ designs are original. The game is named **Isle Slingers**. ## 10. Commit -See the repository commit SHA recorded in the RC completion payload. +See the repository commit SHA for this build. Working tree at commit time contains exactly the files listed in §3. -## 11. Addendum — RC-375D84 S-2 modularization (2026-09-28) +## 11. Addendum — modularization pass (2026-09-28) The flat `js/{core,levels,audio,renderer,main}.js` files described in §3 no longer exist. The tree was restructured (behavior-neutral, proven by a diff --git a/MODULES.md b/MODULES.md index 4acaf4c..642d971 100644 --- a/MODULES.md +++ b/MODULES.md @@ -1,6 +1,6 @@ # Isle Slingers — MODULES.md (master module list) -RC-375D84 S-2. Folders = modules, subfolders = submodules. Every module and +the modularization pass. Folders = modules, subfolders = submodules. Every module and submodule carries an `agents.md` describing its surface and invariants. Load contract (order is load-bearing) is in `architecture.md` and encoded in `index.html` + `test/page.test.mjs`. @@ -35,7 +35,7 @@ Load contract (order is load-bearing) is in `architecture.md` and encoded in | helpers | wood, ice, stone, mogg, grum, king, SLING | — | | data/level-N | one level object each (returns it) | wood/ice/stone/mogg/grum/king, SLING | -## Physics notes (S-3/S-4/S-5, RC-375D84 — landed 2026-09-29) +## Physics notes (S-3/S-4/S-5, the physics + modularization update — landed 2026-09-29) - **topple** (S-3): blocks carry a rotational DOF (`ang`, `angVel`, `pivoting`). A resting block whose COM is past its support span pivots about the support-edge corner (full continuous rotation, Q1) and either lands on the diff --git a/architecture.md b/architecture.md index 945c195..ff58abf 100644 --- a/architecture.md +++ b/architecture.md @@ -1,7 +1,7 @@ # Isle Slingers — Architecture Original architecture for a fully offline, canvas-rendered slingshot game. -No frameworks, no build step, no external assets. As of RC-375D84 (S-2) the +No frameworks, no build step, no external assets. As of the physics + modularization update (S-2) the JavaScript is a **modularized tree**: folders are modules, subfolders are submodules, and every module/submodule carries its own `agents.md`. @@ -52,7 +52,7 @@ app/index.js : the page — input, screens, main loop The simulation is a deterministic impulse-ish engine: bodies integrate under gravity at fixed 1/120 s, contacts resolve positionally, and damage routes -through two funnels (`damageBlock`, `damageEnemy`). What each RC-375D84 step +through two funnels (`damageBlock`, `damageEnemy`). What each physics-pass step added, and where it lives: - **Boards tip and topple (S-3, Q1 = full continuous rotation).** Blocks carry @@ -145,9 +145,9 @@ same surface (every new spec was watched RED on the pre-change tree first). ## Conventions for agents working in this tree 1. Change a physics rule -> edit the one submodule that owns it (see each - `agents.md`); re-run `npm test` (27/27) and the golden-step hash - (`/opt/data/s2_golden.mjs` against `/opt/data/core.orig.js`) when touching - anything that predates RC-375D84 behavior. + `agents.md`); re-run `npm test` (47/47) and re-check the golden differential + against the pre-modularization core when touching anything that predates + this modularization/physics pass. 2. Never re-introduce a flat file for a unit that has a submodule folder. 3. Keep `index.html` script order in lockstep with `test/page.test.mjs`'s `FILES` list — both encode the load contract. diff --git a/index.html b/index.html index d587ffa..aa87bff 100644 --- a/index.html +++ b/index.html @@ -77,7 +77,7 @@ - diff --git a/js/app/agents.md b/js/app/agents.md index f1bbb8b..80d2f69 100644 --- a/js/app/agents.md +++ b/js/app/agents.md @@ -1,5 +1,5 @@ # js/app/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Self-contained module — the page. Owns DOM, input, screens and the main loop. diff --git a/js/audio/agents.md b/js/audio/agents.md index fdc4063..91ac50c 100644 --- a/js/audio/agents.md +++ b/js/audio/agents.md @@ -1,5 +1,5 @@ # js/audio/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Self-contained module. Exports `ISLE_AUDIO = { AudioEngine }`. diff --git a/js/levels/agents.md b/js/levels/agents.md index 71c0da2..01bc55e 100644 --- a/js/levels/agents.md +++ b/js/levels/agents.md @@ -1,5 +1,5 @@ # js/levels/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. The levels **module** (aggregator). Shared scope `L`. diff --git a/js/levels/data/agents.md b/js/levels/data/agents.md index 6d0bc2a..bd05003 100644 --- a/js/levels/data/agents.md +++ b/js/levels/data/agents.md @@ -1,5 +1,5 @@ # js/levels/data/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Level definitions, one file per level (`level-1.js`..`level-5.js`). diff --git a/js/levels/data/level-1.js b/js/levels/data/level-1.js index 28703f6..8382707 100644 --- a/js/levels/data/level-1.js +++ b/js/levels/data/level-1.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- levels/data/level-1.js (submodule: level-1) - * RC-375D84 S-2: level 1 definition, split from the original js/levels.js. + * Modularization pass: level 1 definition, split from the original js/levels.js. * Installer: returns the level object built from the shared helpers scope L. */ (function (root, factory) { diff --git a/js/levels/data/level-2.js b/js/levels/data/level-2.js index 8d5a936..21fc5f8 100644 --- a/js/levels/data/level-2.js +++ b/js/levels/data/level-2.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- levels/data/level-2.js (submodule: level-2) - * RC-375D84 S-2: level 2 definition, split from the original js/levels.js. + * Modularization pass: level 2 definition, split from the original js/levels.js. * Installer: returns the level object built from the shared helpers scope L. */ (function (root, factory) { diff --git a/js/levels/data/level-3.js b/js/levels/data/level-3.js index 9c1bc6e..8078074 100644 --- a/js/levels/data/level-3.js +++ b/js/levels/data/level-3.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- levels/data/level-3.js (submodule: level-3) - * RC-375D84 S-2: level 3 definition, split from the original js/levels.js. + * Modularization pass: level 3 definition, split from the original js/levels.js. * Installer: returns the level object built from the shared helpers scope L. */ (function (root, factory) { diff --git a/js/levels/data/level-4.js b/js/levels/data/level-4.js index 44164bf..0997728 100644 --- a/js/levels/data/level-4.js +++ b/js/levels/data/level-4.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- levels/data/level-4.js (submodule: level-4) - * RC-375D84 S-2: level 4 definition, split from the original js/levels.js. + * Modularization pass: level 4 definition, split from the original js/levels.js. * Installer: returns the level object built from the shared helpers scope L. */ (function (root, factory) { diff --git a/js/levels/data/level-5.js b/js/levels/data/level-5.js index 36875e3..427eb5c 100644 --- a/js/levels/data/level-5.js +++ b/js/levels/data/level-5.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- levels/data/level-5.js (submodule: level-5) - * RC-375D84 S-2: level 5 definition, split from the original js/levels.js. + * Modularization pass: level 5 definition, split from the original js/levels.js. * Installer: returns the level object built from the shared helpers scope L. */ (function (root, factory) { diff --git a/js/levels/helpers/agents.md b/js/levels/helpers/agents.md index 0f2e7b9..d2acbcb 100644 --- a/js/levels/helpers/agents.md +++ b/js/levels/helpers/agents.md @@ -1,5 +1,5 @@ # js/levels/helpers/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `L`: wood, ice, stone (block factories, return center-based records), mogg, grum, king (enemy factories) and the SLING anchor {x:260,y:745}. diff --git a/js/levels/helpers/index.js b/js/levels/helpers/index.js index f858c20..f2ea3bb 100644 --- a/js/levels/helpers/index.js +++ b/js/levels/helpers/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- levels/helpers/index.js (submodule: helpers) - * RC-375D84 S-2: block/enemy constructor helpers + SLING anchor, split from + * Modularization pass: block/enemy constructor helpers + SLING anchor, split from * the original js/levels.js. Installs into the shared levels scope `L`; * js/levels/index.js loads it first, then the level-N data submodules. */ diff --git a/js/levels/index.js b/js/levels/index.js index d4c02a4..a5ac868 100644 --- a/js/levels/index.js +++ b/js/levels/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- levels/index.js (module: levels -- aggregator / public API) - * RC-375D84 S-2 modularization. The original js/levels.js monolith is now: + * Modularization pass. The original js/levels.js monolith is now: * levels/helpers/ - block/enemy constructors + SLING anchor (shared scope L) * levels/data/level-N.js - one level definition each (uses the shared scope) * This aggregator loads the parts in order, builds the LEVELS array, and diff --git a/js/physics/abilities/agents.md b/js/physics/abilities/agents.md index 7703ea4..9762ca4 100644 --- a/js/physics/abilities/agents.md +++ b/js/physics/abilities/agents.md @@ -1,5 +1,5 @@ # js/physics/abilities/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: launch, triggerAbility. diff --git a/js/physics/abilities/index.js b/js/physics/abilities/index.js index f00562b..94101f8 100644 --- a/js/physics/abilities/index.js +++ b/js/physics/abilities/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/abilities/index.js (submodule: abilities) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that diff --git a/js/physics/agents.md b/js/physics/agents.md index f58ba10..e6f8806 100644 --- a/js/physics/agents.md +++ b/js/physics/agents.md @@ -1,5 +1,5 @@ # js/physics/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. The physics **module** (aggregator). Deterministic, DOM-free. @@ -17,7 +17,7 @@ The physics **module** (aggregator). Deterministic, DOM-free. (`activeBird`, `trajectory`, `aimVector`, `starsFor`, `birdsRemaining`). - Invariants: fixed-timestep consumer (tests run 1/120 s); no `Math.random()` in gameplay paths (determinism is a test arm); no DOM access. -- New physics behavior lands in the owning submodule, NOT here. RC-375D84 +- New physics behavior lands in the owning submodule, NOT here. The physics pass S-3..S-5 (landed 2026-09-29): topple/ owns board tip-over (Q1 full continuous rotation), collision/ owns velocity-aware crush + mass-weighted stacks (S-4), step/ owns the landed-bird state and its integration (S-5). diff --git a/js/physics/aim/agents.md b/js/physics/aim/agents.md index 98fb089..28776ed 100644 --- a/js/physics/aim/agents.md +++ b/js/physics/aim/agents.md @@ -1,5 +1,5 @@ # js/physics/aim/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: aimVector, trajectory. diff --git a/js/physics/aim/index.js b/js/physics/aim/index.js index 40832fa..b255d40 100644 --- a/js/physics/aim/index.js +++ b/js/physics/aim/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/aim/index.js (submodule: aim) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that diff --git a/js/physics/camera/agents.md b/js/physics/camera/agents.md index afefcbe..a616dd1 100644 --- a/js/physics/camera/agents.md +++ b/js/physics/camera/agents.md @@ -1,5 +1,5 @@ # js/physics/camera/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: updatePopups, updateCameraTarget, decayCamera. diff --git a/js/physics/camera/index.js b/js/physics/camera/index.js index 43fb929..09c0dbe 100644 --- a/js/physics/camera/index.js +++ b/js/physics/camera/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/camera/index.js (submodule: camera) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that diff --git a/js/physics/collision/agents.md b/js/physics/collision/agents.md index 22afb19..91a4134 100644 --- a/js/physics/collision/agents.md +++ b/js/physics/collision/agents.md @@ -1,5 +1,5 @@ # js/physics/collision/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: crushCircleVsBox, collideBirdWorld, collideBirdBlocks, collideBirdEnemies, REST_VEL_CLAMP, resolveBoxPair. @@ -7,7 +7,7 @@ collideBirdEnemies, REST_VEL_CLAMP, resolveBoxPair. - Contact resolution for circles (birds, enemies) vs axis-aligned blocks and block-block pairs. `resolveBoxPair` is the box-box rest/impulse resolver; `crushCircleVsBox` is the fast-falling-onto-structure damage path. -- RC-375D84 S-4 (landed 2026-09-29): `crushCircleVsBox` is velocity-direction- +- Added 2026-09-29: `crushCircleVsBox` is velocity-direction- aware (the box must be the body plowing into the enemy, `boxAlong > 30`; a resting box never crushes), carries a per-enemy crush cooldown (0.12 s — one landing = one crush instance) and an inelastic velocity transfer so boxes do diff --git a/js/physics/collision/index.js b/js/physics/collision/index.js index ad64210..a6ed022 100644 --- a/js/physics/collision/index.js +++ b/js/physics/collision/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/collision/index.js (submodule: collision) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that @@ -32,7 +32,7 @@ ent.vy -= ny * rel * 1.4; if (isEnemy) { // crush damage: a fast box hurts what it lands on. - // S-4 (RC-375D84): the direction gate is velocity-aware -- the BOX + // Added in the physics pass: the direction gate is velocity-aware -- the BOX // must be the body moving into the enemy (boxAlong > 30). The old gate // (ny < -0.3, enemy above the box) only let SIDE plows crush: a block // dropped STRAIGHT DOWN onto an enemy never registered ("falling @@ -145,7 +145,7 @@ // per-target hit cooldown so one pass-through = one damage instance if (g.time - (e.lastHit || -9) > 0.12) { var speed = Math.hypot(b.vx, b.vy); - // retuned 2026-09-28 (RC-0D193E, Commander bug #3): the old curve + // retuned 2026-09-28 (playtest finding): the old curve // gave ~0.9 dmg to a soft wren lob — a mogg (hp1) could not be // killed without a perfect full-power hit. Bumped so a decent // medium shot connects; the king (hp3) still survives one @@ -186,7 +186,7 @@ var relv2 = (c.vy - a.vy) * n2; if (relv2 < -P.REST_VEL_CLAMP) { // real impact: inelastic common velocity. - // S-4 (RC-375D84): mass-WEIGHTED (was a plain (a.vy+c.vy)/2), so a + // Added in the physics pass: mass-WEIGHTED (was a plain (a.vy+c.vy)/2), so a // heavy block landing on a light plank transfers its real momentum // through the stack (chain-crush). A 22.6-mass stone at v over a // 7.2-mass plank now drives the plank to ~0.76v instead of 0.5v. diff --git a/js/physics/constants/agents.md b/js/physics/constants/agents.md index 30baf80..3118ac6 100644 --- a/js/physics/constants/agents.md +++ b/js/physics/constants/agents.md @@ -1,5 +1,5 @@ # js/physics/constants/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: WORLD, VIEW, MATERIALS, BIRD_TYPES, ENEMY_TYPES, GRAVITY, LAUNCH_POWER, MAX_PULL, MIN_PULL, AIR_DRAG, BIRD_BOUNCE, BIRD_GROUND_FRICTION, diff --git a/js/physics/constants/index.js b/js/physics/constants/index.js index a619a81..3e30711 100644 --- a/js/physics/constants/index.js +++ b/js/physics/constants/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/constants/index.js (submodule: constants) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that @@ -19,7 +19,7 @@ P.MATERIALS = { wood: { hp: 1300, density: 1.0, restitution: 0.18, dmgFactor: 0.9, score: 500, maxVel: 520 }, ice: { hp: 480, density: 0.7, restitution: 0.05, dmgFactor: 1.6, score: 800, maxVel: 560 }, - // stone: retuned 2026-09-28 (RC-0D193E, Commander bug #3 "blocks and pig + // stone: retuned 2026-09-28 (playtest finding: "blocks and pig // bad guys too hard to kill"): at hp 3400 with dmgFactor 0.35 a 70x70 // cube took ~11 full-power direct hits — stone walls were functionally // unbreakable, so every enemy behind one was unkillable. Now ~2-3 hits. diff --git a/js/physics/damage/agents.md b/js/physics/damage/agents.md index 9778ed2..92f0d5b 100644 --- a/js/physics/damage/agents.md +++ b/js/physics/damage/agents.md @@ -1,5 +1,5 @@ # js/physics/damage/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: damageBlock, damageEnemy. @@ -9,6 +9,6 @@ Installs into `P`: damageBlock, damageEnemy. here. - The balance spec (`test/balance.test.mjs`) asserts per-material break budgets and enemy kill budgets under full-power direct hits — that spec is the - contract for everything that deals damage. S-4 (RC-375D84, falling-object + contract for everything that deals damage. Falling-object impact damage) routes through these two functions so it inherits the spec. - Consumes: MATERIALS, ENEMY_TYPES. diff --git a/js/physics/damage/index.js b/js/physics/damage/index.js index be0ba70..94675b5 100644 --- a/js/physics/damage/index.js +++ b/js/physics/damage/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/damage/index.js (submodule: damage) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that diff --git a/js/physics/index.js b/js/physics/index.js index fab21b0..b7f1513 100644 --- a/js/physics/index.js +++ b/js/physics/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/index.js (module: physics -- aggregator / public API) - * RC-375D84 S-2 modularization. This is the THIN AGGREGATOR for the physics + * Modularization pass. This is the THIN AGGREGATOR for the physics * module. The original js/core.js monolith is now split into submodules * (physics/constants, -/state, -/aim, -/abilities, -/damage, -/step, * -/collision, -/rules, -/camera); each installs its units into ONE shared diff --git a/js/physics/rules/agents.md b/js/physics/rules/agents.md index 51d7996..7a66242 100644 --- a/js/physics/rules/agents.md +++ b/js/physics/rules/agents.md @@ -1,10 +1,10 @@ # js/physics/rules/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: checkEndStates, birdsRemaining, starsFor. - Win/lose arbitration (called from step): all enemies dead -> won, no bird - left in play with enemies alive -> lost. S-5 (RC-375D84, landed 2026-09-29): + left in play with enemies alive -> lost. S-5 (added 2026-09-29): a LANDED bird counts as a bird still in play — do not declare `lost` while one is out in the world (it can still fall, smash and kill). `starsFor(g)` maps score to the level's three star thresholds. diff --git a/js/physics/rules/index.js b/js/physics/rules/index.js index 8c5652a..d074922 100644 --- a/js/physics/rules/index.js +++ b/js/physics/rules/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/rules/index.js (submodule: rules) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that diff --git a/js/physics/state/agents.md b/js/physics/state/agents.md index c1caa9d..67f7e55 100644 --- a/js/physics/state/agents.md +++ b/js/physics/state/agents.md @@ -1,5 +1,5 @@ # js/physics/state/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: createGame, makeBird, activeBird. @@ -8,7 +8,7 @@ Installs into `P`: createGame, makeBird, activeBird. scorePopups, hadEnemies, camera, status, activeBird, launched, wonAt, lostAt, stats`) is consumed by render, app and every test — extending is OK, silently dropping a key is not. -- Block/enemy/bird records are plain objects. S-3/S-5 (RC-375D84, landed) +- Block/enemy/bird records are plain objects. S-3/S-5 (added) extended them additively: blocks carry `ang`, `angVel`, `pivoting` (topple DOF) and birds gain the `landed` state (a live body under gravity while another bird is in play; see step/topple). Keep further extensions diff --git a/js/physics/state/index.js b/js/physics/state/index.js index 69d49a2..4102510 100644 --- a/js/physics/state/index.js +++ b/js/physics/state/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/state/index.js (submodule: state) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that diff --git a/js/physics/step/agents.md b/js/physics/step/agents.md index edb5aef..c3f4daa 100644 --- a/js/physics/step/agents.md +++ b/js/physics/step/agents.md @@ -1,5 +1,5 @@ # js/physics/step/ — agents.md -RC-375D84 S-2. Module map: `MODULES.md`; runtime model: `architecture.md`. +Part of the modularization pass. Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: step, stepPhysics, spendBird. **The physics hub.** @@ -10,7 +10,7 @@ Installs into `P`: step, stepPhysics, spendBird. **The physics hub.** BEFORE nothing — but all of its callees must exist in `P` by the time `step` runs (they do, because install order is load order). Keep it that way. - `spendBird` retires a bird that is GONE (aged out / off the island). S-5 - (RC-375D84, landed 2026-09-29) split the settle branch: a bird that settles + (added 2026-09-29) split the settle branch: a bird that settles while ANOTHER bird is in play becomes `landed` — a live body integrated every frame in `stepPhysics` (real gravity, no lifetime timer) that falls when its support breaks, chain-damages boards, and can kill enemies. The LAST diff --git a/js/physics/step/index.js b/js/physics/step/index.js index bc09f2f..ff57409 100644 --- a/js/physics/step/index.js +++ b/js/physics/step/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/step/index.js (submodule: step) - * RC-375D84 S-2 modularization (behavior-neutral split of the original + * Modularization pass (behavior-neutral split of the original * js/core.js monolith). Installs its units into ONE shared physics scope `P` * that every physics submodule sees -- the same single-scope semantics the * monolith had. Must load before js/physics/index.js (the aggregator that @@ -61,7 +61,7 @@ // gone for good (off the island or aged out) -> spent, next bird loads P.spendBird(g, b); } else if (b.settleTimer > P.SETTLE_TIME) { - // S-5 (RC-375D84, Q2): the "another bird is already active" window. + // Landed-bird gravity behavior: the "another bird is already active" window. // A bird that settles while MORE birds are in play (queued or active) // is NOT a corpse: it becomes a LANDED body -- real continuous // gravity, no lifetime timer. It falls if its support breaks, diff --git a/js/physics/topple/agents.md b/js/physics/topple/agents.md index bdd7872..540aabf 100644 --- a/js/physics/topple/agents.md +++ b/js/physics/topple/agents.md @@ -1,5 +1,5 @@ # js/physics/topple/ — agents.md -RC-375D84 S-3 (2026-09-29). Module map: `MODULES.md`; runtime model: `architecture.md`. +Added in the physics pass (2026-09-29). Module map: `MODULES.md`; runtime model: `architecture.md`. Installs into `P`: toppleBlocks, blockSupportSpan, beginTopple, integrateTopple, landTopple, topplePathDamage, settleBack, supportStillAlive. diff --git a/js/physics/topple/index.js b/js/physics/topple/index.js index 147fe3a..466ee93 100644 --- a/js/physics/topple/index.js +++ b/js/physics/topple/index.js @@ -1,5 +1,5 @@ /* ISLE SLINGERS -- physics/topple/index.js (submodule: topple) - * RC-375D84 S-3. Boards tip and topple end-over-end (Commander Q1: FULL + * Board tip/topple physics. Boards tip and topple end-over-end (design call: FULL * CONTINUOUS ROTATION). A resting block whose centre of mass lies OUTSIDE the * x-span of whatever supports it (ground, or the top face of a block below) * begins pivoting about the support-edge corner on the side the COM leans to. diff --git a/js/render/agents.md b/js/render/agents.md index c6dc387..9333cb8 100644 --- a/js/render/agents.md +++ b/js/render/agents.md @@ -8,7 +8,7 @@ Self-contained module. Exports `ISLE_RENDERER = { Renderer, VIEW_W, VIEW_H }`. scenery, popups). It never mutates `state`. - VIEW_W/VIEW_H (1280x720) mirror physics constants VIEW — keep them in sync; the camera lives in state (set by physics/camera), render only applies it. -- S-3/S-5 (RC-375D84, landed): `drawBlock` rotates about the block COM when +- S-3/S-5 (added): `drawBlock` rotates about the block COM when `bl.ang` is set (no-op at `ang=0`, so un-tipped blocks draw identically to the pre-S-3 output), and `drawBird` renders `landed` birds as live bodies alongside the `spent` corpses. The DOM-stub test only checks that drawing diff --git a/package.json b/package.json index 3d03c45..f34eba7 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "isle-slingers", "version": "3.0.0", "private": true, - "description": "Isle Slingers — an original browser slingshot physics game (RC-0D193E). No dependencies; opens directly in a browser.", + "description": "Isle Slingers — an original browser slingshot physics game. No dependencies; opens directly in a browser.", "scripts": { "test": "node test/sim.test.mjs && node test/page.test.mjs && node test/balance.test.mjs && node test/topple.test.mjs && node test/knifeedge.test.mjs && node test/fallingkill.test.mjs && node test/landedbird.test.mjs", "start": "python3 -m http.server 8000"