Wave 2 (closed) + slingshot + spacing pass + Wave 3: bestiary I & Haunted Hollow#38
Merged
Merged
Conversation
The first Kit-touching wave of the content phase, statically verified end to end and ready for the OXT rounds. Kit (the player module + chains): - Drop-through: b2kChain/b2kSmoothGround chains carry the reserved one-way category (bit 2^31, nameable as "oneway"; b2kDefineLayer stops at 2^30 = 31 user layers; b2kSetMask ORs the bit in so custom masks still stand on terrain). DOWN+JUMP on a chain opens a dropMs mask window; the probe ignores one-way ground mid-drop (no phantom re-ground) and the mask restores only once the capsule has CLEARED the deck (one-sided chain contacts judge by centroid - a straddling restore snaps the player back on top), with a 4x hard deadline. The S9.1 ABI question resolved: NO change needed - b2lc_chain_create already honors the pending shape-def filter. - Ladders: b2kPlayerAddLadder zones (flat-array polls, no physics objects, wiped by b2kClear). UP - or DOWN airborne - enters climb: gravity scale parked at 0 (saved/restored), y at climbSpeed (0 = hang), x at half speed; JUMP exits as a normal jump (the press cannot double-spend into the buffer); ground-snap is climb-exempt. - Duck: DOWN grounded brakes to a crouch (no hitbox change this wave); DOWN+JUMP on solid ground is eaten, never a buffered launch. - Hurt-knockback standard: b2kPlayerHurt [fromX] - away-pop riding the jump flag (snap-exempt), hurt state, control back at hurtMs OR first landing after half (whichever is LATER), then an invulnMs mercy window (repeat hurts no-op; b2kPlayerHurtIs() gates hazard checks). An explicit b2kPlayerControl call cancels a knockback in flight. - b2kPlayerAnims grows optional duck/climb/hurt slots (old calls unchanged); new keys dropMs/climbSpeed/hurtPopX/hurtPopY/hurtMs/ invulnMs. Every new tick path idles at one compare; zero added steady-state FFI (the probe reuses the ray's stashed body handle). - Hardening: b2kChain/b2kAddChain set itemDelimiter before parsing (gotcha 5, latent break under a tab delimiter). Harness v10: four new tests (~20 assertions) - drop-through (passes below, chain solid again after), climb (enter/hang/jump-exit/gravity back), duck (brakes, no solid-ground launch), knockback (away-pop, control window, mercy no-op, expiry) - all deterministic at the suite's scale-40 numbers. Platformer: the knockback-vs-respawn split (slime sides, saws, spikes, thwomp undersides, movers knock back via pfOuch + "hits" on the HUD; pits/kill-plane keep the respawn), beige duck/climb anims (the default sheet HAS those frames - design doc corrected), the L2 ladder up to a bonus ledge above the gate (one new coin), drop-through teaching in the help text. The knockback pose is a LOOPING "hurtpose" - a non-looping pose would fire b2kSpriteOnFinish -> the respawn mid-knockback; pfHurtDone also gates on the respawn lock. Micro-game: the same split (sweeper/spikes -> mgOuch; falls respawn), a zero-asset "ladder" verb (drawn rails/rungs) up the taller L2 exit pillar, and OPTIONAL alien skins on menu keys 1-6 when the platformer's remembered Spritesheets folder is present (never prompts; the embedded hero stays the zero-asset default; aliens duck/climb/hurt with real frames from the single aliens.png atlas). Docs: kit-reference (new handlers/keys/states, one-way chain notes, 31-layer cap), kit-guide (new SS21 patterns chapter + duck caveat), CHANGELOG, plan.md decision log, expansion-prep S9 status flips. https://claude.ai/code/session_01WFkLNa8oKsHNqTEHV1Lww4
The seventh example, and the one that shows the PHYSICS CORE carrying a whole game by itself: no player module, no camera, no sprites, and deliberately ZERO contact-event plumbing - every verdict is a poll. - Drag the red ball out of the pocket (tether-clamped pull, live rubber bands, a ballistic aim preview whose dots plot the same x + v*t + a*t^2/2 the world then integrates), release to fire. - Three towers (columns/planks/crates; stone shield on L3) built from level-as-data verbs, laid out exactly touching so the stacks settle asleep; pigs pop on a SPEED POLL - the light body inherits impact momentum, so the poll cannot be outrun by the solver (the doctrine answer to post-impact zero reads), armed after a build-settle grace. - Shot budget per level; 50 a block (polled only inside a post-shot carnage window), 500 a pig, 1000 per leftover shot; out-of-ammo retry rolls the score back; a buzzer-beater pop after the banner still clears the level; win screen with the total. - Hot-path discipline: ammo/bands/aim-dots/pop-rings all POOLED at build (nothing created mid-game but the cannonball), HUD at 4 Hz, idle frame cost is a handful of compares. - Zero assets: colored graphics only (spawned box graphics ROTATE with their bodies - sprites do not, and a toppling tower is all rotation), every sound synthesized. - Registered in tools/sync-embedded-kit.py; README/CLAUDE.md example lists updated; CHANGELOG entry. The static checker's dangling-else gate caught one gotcha-10 in the first draft (fixed block-form). https://claude.ai/code/session_01WFkLNa8oKsHNqTEHV1Lww4
WAVE 2 CLOSED (user-verified, harness v10 all-pass). The wave's one OXT note - "levels are a bit cramped in some areas" - lands as a spacing pass and a new LAYOUT LAW: every interactive beat gets ~100px of clear air; widen the world before squeezing a beat in. - L1 3968px: the cloud steps no longer start at the mound's foot; the pit/second act shift out; decor moves off the bonk row. - L2 3072px: the ladder/ledge is its own beat past the gate (the checkpoint stood INSIDE the ladder tiles, the lever 6px off them); checkpoint 1000, lever 1120, saws 1240/1430, thwomps 1640/1840, wall 2464, stone finale 2688+. - L3 3776px: the bonk-row -> saw -> pit corridor had 0-18px gaps; the saw gets 88/56px of air, the back half shifts +128. - Micro-game L2 1664px: the exit pillar/ladder move past the sweeper's reach. Each beat moved WHOLE (chain + art + cast together); ghost padding and the key/thwomp + checkpoint/slime relationships preserved. WAVE 3 BUILT (statically verified; awaiting the OXT rounds). Design authored in expansion-prep S10; six archetypes + a FOURTH level, all example-side - ZERO Kit changes, so harness v10 stays the baseline (rule 2 is conditional on Kit edits). - Snail: slime-family kind chain snail -> shell -> shellslide <-> shell. Stomp shells it; any touch kicks the shell sliding 520px/s away; the slide is a per-frame velocity assert that reverses off walls (collapsed-vx poll) and bowls over every ground foe it reaches; stomp again to park it; sides knock back. New "kick" tone. - Bat: roosts static under an overhang, drops on approach, then flies as a gravity-scale-0 body (patrol vx + proportional swoop to head height + sine bob). One stomp. - Mimic: a grassBlock dead still in the PURPLE biome (wrong on purpose); wakes within ~90px, lunges in cooldown hops. One stomp. - Piranha burrows: bodiless sprites on a down/rise/bite/sink cycle with the classic mercy (never rises under the hero's feet); unkillable. Scene-drawn mouth holes keep the layering honest. - Ghost: bodiless, drifts through terrain toward the hero ONLY while he faces away (b2kPlayerFacing poll); eye contact freezes it shy. - Faced crushers: pfMakeThwomp pFaced promotes the machine's no-asset fallback art (block_idle/fall/rest moods) to a first-class look; pfTickThwomps already swapped the faces. - L4 "HAUNTED HOLLOW" (3712px, 10 coins): purple biome, mimic field, snail+slime bowling lane, the bat bar, a pit, two burrows, the ghost over the back half, a faced-crusher pair around a new LAVA strip (pfMakeLava: knockback hazard raised above the floor line so wading burns - never a respawn), purple steps, the flag. Win moves to gLevel >= 4; all copy says FOUR. - The spooks sheet (enemies.png, Family C) loads at b2kSheetScale 0.9 per the mixed-grids law and is OPTIONAL: without it the four spook makers skip silently and L4 still completes. Spook facing polarity is statically unverifiable - flagged in the verify list. Docs: expansion-prep S10 + status flips (Wave 2 COMPLETE, baseline v10), plan.md decision rows, CHANGELOG. https://claude.ai/code/session_01WFkLNa8oKsHNqTEHV1Lww4
A fresh-eyes review of everything the waves touched, hunting engine gotchas (single thread, delimiter state, dangling else, sleep semantics) and per-frame waste. Three findings, all in Wave 3 code: 1. The parked SHELL braked itself every frame via b2kSetVelocity - which WAKES the body by design (the pressure-plate lesson), so a parked shell could never sleep and paid solver + 2 FFI calls per frame forever. The kind transitions already write velocity 0; the per-frame brake is gone (the case stays - the default branch would otherwise hand a parked shell patrol velocity). 2. The mimic's 90px wake range gave ~0.3s of telegraph at full sprint before its sides hurt; widened to 110px (~0.4s). 3. The two L4 bats shared one patrol band: two gravity-0 BODIES crossing paths collide while their velocity asserts fight the solver (jitter). Bands split (1490-1650 / 1690-1840) so they never meet. Verified clean by scripted sweeps + mechanical cross-checks: - every item-parsing handler sets itemDelimiter in-handler (zero violations across platformer/micro-game/slingshot own code); - all hot ticks hoist their clock reads (the in-loop "the milliseconds" hits are build-time naming or 1-2 compares in user-verified Wave 1 code); - every b2kSmoothGround chain's SOLID span (ghost rule applied) matches its tile art span exactly on all four levels; slabs flush with tile loops; bounds consistent; - door/lever machinery fully parameterized (no stale coordinates survived the spacing pass); - b2kSpriteFlipH guards same-value (per-frame flip calls are cheap); - sensor dispatch already gates on the hero as visitor (sliding shells cannot collect coins or trip hazards); - b2kFell covers every slime-family row generically (shells and mimics lost to pits clean up their own slots). https://claude.ai/code/session_01WFkLNa8oKsHNqTEHV1Lww4
The institutional memory pass: everything Waves 1-3 (and the audit) taught, written where the next session starts reading. - Gotchas 17-27 appended (existing numbers 1-16 are load-bearing - code comments cite them): velocity writes WAKE bodies (the parked- shell sleep-killer); two velocity-asserting bodies must never share a path; non-looping anims fire OnFinish whoever started them (the looping-hurtpose law); one-sided chains judge by centroid (the straddle-restore trap); 32-bit filter math + the reserved oneway bit; switch-kind default hazards; sprites do not rotate; mixed-grid scaling + .png-suffixed frame names; optional-sheet capability flags; art facing is statically unverifiable; capture `the result` immediately. - New section: the single-threaded performance playbook - the three real costs (interpreter ops, FFI round-trips, property-set redraws) and the eleven rules earned by measured regressions (hero snapshot, hoisted clocks, 4Hz HUD, pool-never-create, redundancy guards, one-compare idle gates, bind-time resolution, sleep preservation, deferred rebuilds, park-before-disable, raw handles in hot paths). - New section: layout & game-design laws - THE LAYOUT LAW (~100px of clear air per beat; widen before squeezing; move beats whole), the chain solid-span==art-span mechanical check, the structural-gate / scenery-first / bounds-before-goto / no-sub-capsule-slot laws, the knockback-vs-respawn split, self-counting totals, ladder zone placement, hazard mercy patterns, versioned chrome + newest-cue sound guards. - Harness note updated: v10, ~113 assertions, and rule 2 made explicit (example-only changes do NOT bump the harness). https://claude.ai/code/session_01WFkLNa8oKsHNqTEHV1Lww4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
One branch, four deliverables, all statically verified (every gate green; embedded Kit in sync; C smoke test passing). Harness stays v10 — Wave 3 touches zero Kit code.
1. Wave 2 — player actions I ✅ user-verified, closed
Drop-through, ladders, duck, the hurt-knockback standard + harness v10 + both games on the knockback-vs-respawn split. Closed 2026-06-13 with v10 all-pass on the user's machine. (Details in the first commit / CHANGELOG.)
2. The slingshot example
Angry-birds-style tower knockdown — the physics core carrying a whole game with zero events and zero assets (drag-to-aim with honest ballistic preview dots, speed-poll pig verdicts, pooled effects, 3 levels + scoring).
3. The spacing pass (the wave's OXT feedback) → a layout law
"Levels are a bit cramped in some areas" — root cause: Wave 2's beats were squeezed into proven layouts. Every level stretched so each interactive beat gets ~100px of clear air, now recorded as a layout law:
Beats moved whole (chain + art + cast together); ghost padding and machine relationships preserved.
4. Wave 3 — bestiary I + L4 "HAUNTED HOLLOW" (awaiting the OXT rounds)
Design authored in expansion-prep §10, then built — all example-side, zero Kit changes (rule 2: no harness bump).
kicktone.b2kPlayerFacingpoll). Bodiless — drifts through terrain.pfMakeThwomp pFacedpromotes the machine's fallback art (block idle/fall/rest moods) to the L4 look.gLevel >= 4; all copy says FOUR. The spooks sheet (enemies.png, scaled 0.9 per the mixed-grids law) is optional — without it the spook makers skip silently and L4 still completes.OXT pass checklist
https://claude.ai/code/session_01WFkLNa8oKsHNqTEHV1Lww4