Skip to content

M49: Crazy Fruits (match-3) — single-source engine, masked DQN (+57% over random), touch+mouse web game - #38

Merged
PieterjanDeClippel merged 22 commits into
masterfrom
m49-crazy-fruits
Jul 24, 2026
Merged

M49: Crazy Fruits (match-3) — single-source engine, masked DQN (+57% over random), touch+mouse web game#38
PieterjanDeClippel merged 22 commits into
masterfrom
m49-crazy-fruits

Conversation

@PieterjanDeClippel

Copy link
Copy Markdown
Member

M49 — Crazy Fruits (match-3) + primitive net

New game + AI in the KidCity (kidcity.be) Crazy Fruits spirit: swap two adjacent fruits to line up 3+, cascades chain, works with mouse and touch. PRD: docs/prd/CRAZY_FRUITS_PRD.md (planned via a 4-agent investigation; the original Flash SWF is unrecoverable, so this ships assumed-standard match-3 rules under the confirmed fruit-stall theme).

What's in it

  • M49.1 Enginecrazyfruits_solver.pg single-source (C# + TS twins): rules, proportional cascade scoring (10·(k+1)/fruit, +20/+50 line bonuses), hard legal-move mask (match-producing swaps only), deadlock reshuffle in-engine (the mask never goes all-false), Schrage-minstd RNG (exact i32 both sides), 672-float observation, scripted random/greedy/expectimax-1 baselines, dueling-net forward, and a stepwise move API for the animating web host. Gate: 16 unit tests + a seeded 1,000-move episode byte-identical C#↔TS (per-move full-grid checksum 78377593).
  • M49.2 Env + campaign + LabCrazyFruitsEnv (masked, stateful, truncation-only) on the M46 DqnScoreCampaign spine; --game crazyfruits (+ --baselines N gate table). Gate: 500 seeded episodes — random 2259.7±49.9, greedy 2387.0±49.3 (CI-separated), expectimax-1 4270.9±98.3. Finding: cascade planning is the skill (+89%); line size is nearly irrelevant (+6%).
  • M49.3 Primitive net+57.2% over random (3552.5±83.3), CI-separated on the 500-episode held-out protocol; +48.8% over greedy. Honest three-run story (one lever per intervention): γ=0.99 failed at +1.9% (bootstrap-noise explosion — the documented match-3 trap), γ=0 alone +7.8%, γ=0 + the PRD's pre-registered per-action feature planes (immediate score + deterministic cascade value; obs 448→672) passed. Ships wwwroot/models/crazyfruits.dqn.ckpt (LFS). Expectimax-1 (4270.9) is the future-training headroom.
  • M49.4 Web game — fully client-side (/crazyfruits): canvas fruit-stall renderer (bunting + vector fruit art), animations driven by the engine's stepwise API, unified Pointer Events (one path covering touchstart/move/end and mousedown/move/up): drag-swap + tap-tap-select, touch-action: none, setPointerCapture.
  • M49.5 Watch AI — tier picker Random / Greedy / Expectimax / Trained net, all running in the browser; crazyfruits-net.ts ckpt parser (byte-level reference: CrazyFruitsNetParityTests).

Verification

  • 32 targeted tests green (engine invariants, mask==brute-force, hand-scored cascades, parity pins, env contract, baseline ordering, campaign resume, net parity, DI registration).
  • Headless node runs of the real browser code: game layer (60 greedy moves land on engine-exact grids; reverts consume nothing) and the full inference path (shipped ckpt → TS parser → generated net; all four tiers play legal 30-move episodes, strength ordering reproduces).
  • ⚠️ Pending: the live in-browser desktop + smartphone pass (M49.4/M49.5 gate leg) — the dev host was down throughout; start dotnet run --project src/RLDemo.Web and visit /crazyfruits to complete it. All headless evidence is recorded in the PRD.

🤖 Generated with Claude Code

PieterjanDeClippel and others added 7 commits July 24, 2026 09:45
4-agent investigation (game provenance, repo integration, conventions/input,
match-3 RL prior art) -> docs/prd/CRAZY_FRUITS_PRD.md + PLAN.md M49.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cade + tests

- crazyfruits_solver.pg: 8x8/6-fruit match-3 rules (swap legality, cascades with
  proportional scoring 10*(k+1) + line bonuses, gravity/refill, deadlock reshuffle),
  Schrage minstd RNG (exact i32 both sides), 448-float observation (6 one-hot planes
  + would-match plane), scripted baselines (random/greedy/expectimax-1) and the
  PgCfDuelingNet forward - all shared C#/TS; pgconfig routes the TS twin to
  ClientApp/src/app/crazy-fruits.
- CrazyFruitsBoard: public facade (state serialization, LoadGrid for directed tests).
- Gate GREEN: 16 tests - init/post-move invariants (stable board, always a legal
  swap), mask == brute force, hand-computed 3/4/5-line + 2-step-cascade scores,
  reshuffle multiset preservation, minstd 10,000th-draw reference (399268537),
  determinism + state round-trip; C#<->TS parity: seeded 1,000-move random episode
  checksummed per-move over action/points/full grid -> identical (78377593, score 70990)
  against the generated TS twin under node type-stripping.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CrazyFruitsEnv: IEnvironment + IActionMaskProvider + IStatefulEnvironment over the
  .pg core; reward = points/30, truncation (never termination) at the 30-move budget,
  full state round-trip, viz labels.
- CrazyFruitsDqnCampaign on the DqnScoreCampaign spine (masked Double+Dueling, the
  Snake recipe re-pointed) + AddCrazyFruitsDqnCampaign() + `--game crazyfruits`
  (`--baselines N` prints the gate table; `--net` adds the trained net to it).
- Gate GREEN: baseline ordering over 500 seeded episodes - random 2259.7+/-49.9,
  greedy 2387.0+/-49.3 (CI-separated), expectimax-1 4270.9+/-98.3 (cascade planning
  is the skill; line size is nearly irrelevant); campaign resume->train->checkpoint->
  resume contract on the real env; one end-to-end 3k-step chunk trained and saved a
  deployable net. 21 CrazyFruits tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… watch scaffolding

- Engine grows a stepwise move API (clearStep / finishMove; applySwap drains the same
  loop) so the animating web host and the one-call training path are the same rules by
  construction - C#<->TS parity checksum re-verified unchanged (78377593).
- crazy-fruits-game.ts: animating host recording swap -> pop -> fall [-> reshuffle]
  timelines from the engine; view-only fall geometry.
- crazy-fruits-render.ts: fruit-stall theme (bunting, strawberry-red wordmark, vector
  fruit art), canvas HUD (score/moves/best drawn on-canvas - loop runs outside zone).
- crazy-fruits.ts/.html/.scss: unified Pointer Events - ONE path for touch
  (touchstart/move/end) and mouse (mousedown/move/up): drag-swap past a 0.35-cell
  threshold + tap-select-tap-swap; setPointerCapture; touch-action: none.
  Watch-AI scaffolding: tier picker (Random/Greedy/Expectimax/net), director driving
  the engine's scripted baselines, net loader (falls back to expectimax until the
  M49.3 ckpt ships); screen wake lock during watch.
- Registered: route /crazyfruits + nav link + home card; ARCHITECTURE.md env +
  client-side tables.
- tsc --noEmit clean. Gate note: live desktop+smartphone verification pending the
  user-run host (down at implementation time) - to be evidenced before the PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pisodes)

Three-run story (all 150k moves, masked Double+Dueling DQN, one lever per
intervention per the no-thrash rule):
1. gamma=0.99 (the Snake recipe verbatim): loss exploded 0.62->8.7, eval regressed
   below random mid-run; on the 500-episode gate the keep-best net was +1.9%
   (OVERLAPPING) - the documented match-3 trap: the controllable signal is almost
   entirely immediate, and deep bootstrapping amplifies refill-cascade noise. FAIL.
2. gamma=0 (Q = expected immediate points incl. stochastic cascades): stable loss
   (~0.18), +7.8% CI-SEPARATED, above greedy - real learning, still under +30%. FAIL.
3. gamma=0 + the PRD s6 Risk-1 pre-registered mitigation - observation grows two
   per-action feature planes (immediate score, deterministic cascade value, /100;
   448 -> 672 floats): mean 3552.5 +/- 83.3 = +57.2% over random CI-SEPARATED
   (gate >= +30%), +48.8% over greedy; expectimax-1 (4270.9) remains the scripted
   ceiling = future-training headroom.

Ships wwwroot/models/crazyfruits.dqn.ckpt (LFS, keep-best from run 3, eval 3392.5
at 125k). Observation change verified: 22 tests green (incl. per-action-plane
pins), C#<->TS parity checksum unchanged (78377593).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- CrazyFruitsNetParityTests: byte-level ckpt parse (the line-for-line reference for
  crazyfruits-net.ts) -> PgCfDuelingNet forward matches the SDK DuelingQNet within
  f32 tolerance through real checkpoint bytes; masked netAction returns legal actions.
- Node simulation of the exact browser path (shipped crazyfruits.dqn.ckpt -> TS
  parser -> generated net on the generated engine): all four watch tiers play full
  legal 30-move episodes; strength ordering reproduces (random 2379 / greedy 2520 /
  net 3393 / expectimax 4507 over 20 eps).
- PRD + PLAN M49 updated with all measured gate results; M49.4/M49.5 marked "built,
  live in-browser device check pending" (the user-run dev host was down throughout;
  headless evidence recorded in the PRD).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LIVE Playwright against the running host (desktop 960px mouse + emulated phone
390px with real touch events):
- tap-tap select ring lands on the tapped cell on both form factors; a human
  tap-tap swap cleared a 3-line (score 30, move 1, screenshot-verified)
- mouse drag and CDP touch-drag both fire the gesture; illegal picks revert
  without consuming a move; window.scrollY unchanged through the touch drag
  (touch-action: none holds); zero console/page errors
- watch mode verified live mid-cascade (trained net, score 330 at move 7/30,
  "+30" pop on screen); all four tiers exercised on desktop and mobile

Screenshot-driven UX fix: a failed tap-tap swap now clears the selection like a
successful one (the persistent ring was both a test false-positive and off-feel).
PRD + PLAN M49 marked fully SHIPPED.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@PieterjanDeClippel

Copy link
Copy Markdown
Member Author

Live browser gate completed (host started per the clarified rule — port was free): desktop mouse + emulated smartphone touch both verified with Playwright. Human tap-tap swap cleared a 3-line (score 30 · move 1), drag gestures fire on both input types, illegal swaps revert without consuming a move, window.scrollY stays at 0 through a touch drag (touch-action: none holds), watch mode caught the trained net mid-cascade (+30 pop at move 7/30), all four tiers exercised — zero console errors. One screenshot-driven UX fix landed: failed swaps now clear the selection. PRD/PLAN updated — every M49 gate is green.

PieterjanDeClippel and others added 6 commits July 24, 2026 11:24
Replaces the hand-drawn vector fruits with fruit-cake-art.ts (cached 256px
offscreen renders, blitted scaled - the per-frame cost is a textured quad).
Six visually distinct picks from the 11-tier catalog, no two share a color:
strawberry, grape, dekopon (orange), pear, pineapple, watermelon. Radius bumped
0.36 -> 0.42 cell (the art fills its circle), selection ring to 0.47. C# viz
labels synced to the new fruit identities (labels only - observation unchanged).
Verified live: board + watch-mode cascades render with the new art, no errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…+ PLAN entry

3-agent investigation (canonical Candy Crush mechanics, line-referenced engine
impact, AI/training impact) -> docs/prd/CRAZY_FRUITS_SPECIALS_PRD.md + PLAN M50.

Key locks: fully deterministic rules (zero RNG - passive bomb clears the most-
frequent type, (r+c)%2 conversion orientations, lowest-run-cell cascade spawns;
striped blast PARALLEL to the match, the "perpendicular" wiki wording is sprite
paint); packed base-16 cell encoding (plain fruit keep 1..6); bounded activation
worklist with the wrapped double-explosion riding the grid as an internal armed
kind (stepwise animation API unchanged); swapIsLegal supersedes swap-must-match
(action space stays 112); obs 672->928 => from-scratch retrain; v1 keeps gamma=0
with the per-action deterministic-value feature extended to price create+fire+
combos (PBRS at gamma=0 is a provable no-op), ONE pre-registered escalation
(gamma=0.5 + 3-step + PBRS) gated by a new expectimax-2 baseline; game-over =
30-move rounds (owner decision - measured zero deadlocks ever, so game-over-on-
deadlock would never fire; 30 keeps round scores comparable to the trained tiers).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Packed base-16 cells (kind*16+type; plain fruit keep 1..6); typewise match scan
  now records runs; creation resolver (bomb > wrapped > striped, blast PARALLEL to
  the match, swap-cell/lowest-cell/intersection spawns); bounded activation worklist
  with chains; wrapped double explosion rides the grid as an internal armed kind
  (stepwise animation API unchanged); stageSwap + swapIsLegal (bomb/special+special
  always legal, action space stays 112); all six combos; passive bomb zaps the
  most-frequent type (zero-RNG lock); per-move creation/fired telemetry.
- Fire-only scoring (owner decision): creations score nothing in-game; the training
  env gains ShapeCreationRewards (+40/+60/+100 to the REWARD only, train env only).
- Planning (immediateScore/deterministicValue) runs REAL clearSteps and restores
  board+context byte-identically (purity test: no RNG, WriteState bytes unchanged).
- Observation 672 -> 928 (+4 kind planes, /300 feature planes); colored specials set
  both planes; bombs colorless.
- Gate GREEN: 42 tests - every creation shape (incl. priority + cascade spawn),
  every activation (wrapped two-step timeline, never-armed-on-stable invariant),
  every combo hand-scored exactly (bomb+bomb 640, striped+wrapped 390, ...), chain
  reactions, invariant sweep, legality brute-force; C#<->TS parity RE-PINNED at
  533753109 via the NOW-COMMITTED tools/cf_parity.mjs (episode exercises creation,
  chains, combos and a mid-episode reshuffle byte-identically).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- RewardScale 30 -> 100 (random means ~86 pts/move with auto-firing specials);
  per-action feature planes /300; ShapeCreationRewards wired to the TRAIN env only
  (--no-shape opts out); stale-width ckpt guard in --baselines.
- New single-source tiers: expectimax-2 (beam-8 two-ply deterministic - the
  baseline that can see create->fire) and specials-greedy (immediate + creation
  weights); per-tier specials created/fired stats in the gate table.
- Gate GREEN (500 seeded episodes): random 2612.2+/-67.5, greedy 3446.0+/-99.6
  (+32% - specials widened the skill gap from M49s +6%), specials-greedy
  3850.4+/-113.8, expectimax-1 5841.2+/-159.8 (+124%), expectimax-2 8368.8+/-177.8
  (+220%). Env validation: random = 31% of expectimax-2 (< 70%). Expectimax-2 gap
  +43.3% over expectimax-1 => the M50.3 escalation trigger is armed. Directed tier
  tests: greedy provably takes the bomb swap; specials-greedy provably builds.
  45 CrazyFruits tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…orm-then-trigger

1. Striped blast is PERPENDICULAR to the creating match (real Candy Crush rule:
   horizontal 4-match -> vertically-striped fruit clearing its COLUMN; paint shows
   the blast). Overrules the research agents parallel reading.
2. Combo blasts centre on the gesture LAST-SELECTED cell: stageSwap(action,
   targetCell); web host passes the second tap / dragged-to cell; AI + baselines
   default deterministically to the action bottom/right cell. Directed test pins
   that the same swap staged toward each end fires the matching column.
3. Specials FORM before the step activations run: a fresh special lands on its
   spawn cell first (unmarked - survives untouched), and fires IMMEDIATELY if any
   blast/combo of the same step reaches it. Directed 190-point double-match test:
   a fresh striped triggered by a wrapped box within its own creation step.

47 tests green; parity re-pinned 533753109 -> 801202210 -> 995400597 (score 95550)
via tools/cf_parity.mjs; 500-episode baselines re-measured on the final rules
(random 2598.7 / greedy 3497.9 / specials-greedy 3867.1 / expectimax-1 5931.4 /
expectimax-2 8135.0; env validation 32% < 70%; e2 gap +37.2% keeps the escalation
trigger armed); the in-flight training run was discarded and restarted per change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ts, 30-move rounds

- Square candy wrapper (owner-requested): translucent gold rounded square with
  folded corner tabs behind the fruit + gloss band and double rim in front - the
  fruit stays visible inside. Stripes: thin (0.1r) white bars with dark outlines
  painted ALONG the blast axis (readable on light fruit); colorless sugar-bomb
  sphere with sprinkles.
- Pop step enriched from the engines lastClearedBy/lastCreated: striped beam
  flashes, blast rings, bomb zap glows, creation sparkle-ins.
- stageSwap gesture wiring (combo centre = last-selected cell); six watch tiers
  (+ Specials-greedy, Expectimax-2); 30-move rounds with the round-over screen
  (score / best / measured tier bars / tap to play again); deadlock still
  reshuffles mid-round; home card + copy updated.
- Gate GREEN: tsc clean; headless smoke (60 greedy moves, engine-exact grids,
  specials firing - 8130 pts vs ~4360 pre-specials); LIVE Playwright: watch tiers
  screenshot the square-wrapped pineapple / striped fruit / two bombs, and a real
  30-move human round (164 pixel-diff-probed swaps) ended on the round-over screen,
  tap restarting a fresh round; zero console errors. M50.3 training deferred by
  owner call - runs in background, ckpt + gate table land as a follow-up; the net
  tier falls back to expectimax until then (stale-width guard).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@PieterjanDeClippel

Copy link
Copy Markdown
Member Author

M50 (Candy-Crush specials) is now in this PR — striped / wrapped / sugar bomb + all six combo swaps, single-sourced in the .pg (47 tests, parity re-pinned at 995400597). Three owner rule corrections landed mid-build, each re-verified end-to-end: striped blast ⊥ the creating match, combo blasts centre on the gesture's last-selected cell (stageSwap grew a target-cell parameter), and specials form before the step's activations so a fresh special blasted in the same step fires immediately. Scoring is fire-only (creation earns nothing in-game; the training env adds a creation-shaping reward). Web: square candy wrapper with visible fruit inside, thin outlined stripes along the blast axis, sprinkled bomb sphere, blast/creation effects, six watch tiers, and 30-move rounds with a round-over screen — all live-verified (a real 30-move human round + zero console errors). Baselines on the final rules: random 2598.7 · greedy 3497.9 (+35%) · specials-greedy 3867.1 · expectimax-1 5931.4 (+128%) · expectimax-2 8135.0 (+213%); env validation 32% < 70%. M50.3 retrain is deferred by owner call — it's running in the background and its checkpoint + gate table land as a follow-up commit; until then the site's net tier gracefully falls back to expectimax.

PieterjanDeClippel and others added 9 commits July 24, 2026 13:19
- "Endless mode" toggle (human play): keeps playing past the 30-move round and
  dismisses an already-shown round-over screen, resuming the same board. Any game
  endless touches is permanently exempt from the "best" indicator (bestExempt
  latch per game); rounds + best resume with the next normal game. HUD status
  shows "endless - score wont count for best".
- Striped overlay bars thinned 0.22r -> 0.10r (less than half), per owner.
- Verified: tsc clean; headless semantics smoke (round closes at 30 / endless
  never closes / resume-from-round-over / best frozen once endless touches /
  rounds+best resume when off); live toggle screenshot, zero console errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nctionality tests

- StepwiseHostProtocol_IsByteIdenticalTo_ApplySwap: the web pages exact engine
  calls (stageSwap -> clearStep/collapse loop -> finishMove) vs the atomic
  applySwap, 10 seeds x 30 mixed greedy/random moves incl. specials and combos -
  identical grid, score, RNG stream, reshuffles and fired-telemetry every move.
  The browsers game functionality IS the tested engine functionality by
  construction (TS equality separately pinned by the parity checksum).
- tools/cf_host_tests.mjs (committed, `node tools/cf_host_tests.mjs`): the host
  layers own rules - round closes at exactly 30 (not 29), round-over blocks
  moves, endless dismisses the screen and resumes the same board past 30, best
  freezes the moment endless touches a game (incl. games started under endless),
  rounds + best resume when toggled off, illegal swaps never consume a move.
  Runs the real crazy-fruits-game.ts under node type stripping (temp-copy import
  rewrite); no rendering involved.

48 CrazyFruits xunit tests green + both node harnesses (parity, host) green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…er Q)

- PassiveBomb test extended: after the move, the striped that set the bomb off
  AND the bomb itself are off the board.
- New Wrapped_TriggersBomb_AndBothAreRemovedByMoveEnd: a wrapped 3x3 catches a
  bomb; exact step-0 score computed dynamically (match + box + most-frequent-type
  zap); by move end the wrapped (via its armed second explosion), the bomb, and
  any armed shell are gone.
- Lab --baselines: the net row now reports specials created/fired per episode
  (needed for the M50.3 usage gate).

49 CrazyFruits tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fallback)

The gamma=0 run passed the +30% floor decisively (+53.9%, 4000.5 +/- 128.8 on 500
episodes) but missed the 64% gap-share bar (42%) and the 2x-random creation-usage
bar (5.7 vs 7.3/ep) - exactly the hold-for-combo blind spot the PRD pre-registered
the escalation for (expectimax-2 gap +37.2% >> 10% arms the trigger).

- CrazyFruitsDqnOptions : DqnScoreOptions adds NStep (campaign feeds it to the
  trainer; plain options = defaults).
- CrazyFruitsEnv.ShapeSpecialsPotential: potential-based shaping, Phi(s) = sum of
  on-board special option values (40/60/100), reward += gamma*Phi(s2) - Phi(s1) -
  policy-invariant at the matching gamma, prices HOLDING a special without
  rewarding hoarding (provable no-op at gamma=0, hence escalation-only).
- Lab: --nstep, --pbrs (escalation config = --gamma 0.5 --nstep 3 --pbrs; PBRS
  replaces the creation bonus on the train env; eval env stays bare).

49 tests green. Escalation run launched; ONE attempt per the no-thrash stop-loss.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…est counts

PRD/PLAN now carry the full honest M50.3 state ahead of the closing commit:
attempt 1 (gamma=0) 4000.5 +/- 128.8 = +53.9% over random (gate 1 PASS, +14.4%
over greedy) but 42% gap share and 5.7 created/ep miss gates 2/3; the ONE
pre-registered escalation (gamma=0.5 + 3-step + PBRS) is running. PLAN lock text
gains the third correction (form-then-trigger), fire-only scoring and the
endless toggle; test counts synced to 49 + the two committed node harnesses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…to the nearest plain cell

Owner bug report: dragging a striped fruit into a line of 4 neither fired
its blast nor left a new striped elsewhere in the line. placeCreation
overwrote-and-unmarked whatever held the spawn cell, silently deleting the
existing special on all four creation paths (striped swap-cell, wrapped
pivot, bomb match-5, cascade lowest-cell).

Rule (matches real Candy Crush): a spawn cell already holding a special is
never overwritten - that special stays match-marked and fires through the
existing form-then-trigger pass, and the creation relocates to the nearest
plain cell of the shape (outward along both arms from a wrapped pivot; ties
toward the lower flat index). A shape with no plain cell creates nothing -
every special in it simply fires.

- 8 directed tests (reported drag exact-scored at 180; wrapped variant +
  armed refire; plain-spawn regression guard; all-special run, zero
  creations; equidistant tie-break; bomb relocation with priority intact;
  wrapped-pivot; cascade relocation) - suite 57/57 green
- Parity re-pinned 563660409 (C# = TS via tools/cf_parity.mjs); host
  harness green
- Baselines re-measured on fixed rules (M50.3 bars updated): random 2613.9
  greedy 3499.2 - e1 5974.6 - e2 8139.1; validation 32%; e2 gap +36.2%
  keeps the escalation armed; the in-flight escalation run was restarted
  on the fixed rules

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The page now carries a tribute paragraph: Crazy Fruits came from KidCity.be,
the Belgian Flash-era children's portal; both are gone today.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…er keeps the promised special

Owner report round 2: a wrapped dragged into a line of 4 still never left a
new striped standing. Two-agent audit showed M50.5 was functionally correct
(the dragged wrapped fired and the striped WAS created, all 13 geometries)
- but the wrapped's own 3x3 always covers the nearest-plain relocation
cell, so the relocated striped chain-fired in the same step and the armed
second explosion re-covered it a step later. A dragged striped only spared
it when the blast axis missed - exactly why striped drags looked fixed.

Rule: a creation displaced off its preferred spawn cell is shielded from
blasts (beams, boxes, armed refires, bomb zaps, combo areas) for the rest
of the move - the fired special cannot consume its own replacement.
Matches in later cascade steps still consume it normally, and creations
placed on their preferred plain cell keep the form-then-trigger chain rule
(the 190-point test is untouched).

- shielded[] list, set only on relocation, skipped by markCell (the single
  blast-marking entry point), cleared by stageSwap - never outlives a move
- collision tests updated to shield semantics: striped drag exact-scores
  100 with the fresh striped surviving; wrapped drag 90 surviving BOTH
  explosions; wrapped-pivot 80 keeping an unarmed wrapped - 57/57 green
- parity re-pinned 481681208 (score 95950, up from 86340: surviving
  specials fire later - the shield is score-positive), C# = TS verified;
  host harness green
- the completed cf7train run (trained without the shield) is void;
  training restarts from scratch on the final rules

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…an and lost

Final-rules gate eval (500 eps, seeds 5000+e; bars: >=3392.0 / >=4747.8
gap-share / created >=7.3 & fired >=5.6):

- SHIPPED cf5train (gamma=0 + creation-shaping): 4040.4 +- 128.9 = +54.9%
  over random, CI-separated (gate 1 PASS, +15.1% over greedy); gap share
  43% (gate 2 MISS); created 5.81 (MISS) / fired 5.75 (pass). The net
  transfers unchanged across the rule fixes because its per-action feature
  planes are computed by the live engine at inference.
- The ONE pre-registered escalation (gamma=0.5 + 3-step + PBRS) got its
  clean from-scratch run on the final rules (cf8train, 400k): 3408.2 =
  +30.6%, gap share 24%, created 4.66 - worse on every gate. Bootstrapping
  loses to gamma=0 on match-3 refill noise even with PBRS; the M49 lesson
  reconfirmed. Two earlier escalation runs were voided by the in-flight
  rule fixes (cf6train killed at 210k; cf7train trained without the shield,
  only +33.4% under final rules).
- Stop-loss invoked per protocol: best net ships, gates 2/3(created) are
  reported missed, no further training. Hold-for-combo (the +36% e2 gap)
  stays unclaimed by reactive nets; the recorded future lever is
  search-guided play, not another reward schedule.

Round-over screen gains the net's challenge bar (~4 000). PRD/PLAN updated
with the full verdict and final-rules baselines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@PieterjanDeClippel
PieterjanDeClippel merged commit 2a74dfa into master Jul 24, 2026
2 checks passed
@PieterjanDeClippel
PieterjanDeClippel deleted the m49-crazy-fruits branch July 24, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant