a8ae26f2d4
1 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d2ab84d549 |
M12 WIP: oranges and the ribbed pyramid — the reamer twist is causal
The juice station, on the same bones. Press-and-twist reuses the jar's swirl
detector: signed angular sweep of the pointer around the reamer becomes juice
one frame at a time, so twist rate IS juice rate (the feel that had to be right,
brief §9). Dwell is the downforce — holding the half down ramps press, and the
twist while you hold is what juices.
NEW src/sim/juicing.ts (pure, no three — mirrors cutting.ts):
- theoreticalYield(halve) = base·(1−2|offset|)·(1−0.5·wedge): the halve sets the
reachable ceiling, so a butchered 60/40 caps you at ~70% and the bar can't lie.
- juiceTwist(s, dTheta, press, dt, rand): pulse = sweep·press·ream, capped by
what's reachable; twist REVERSALS bite a fresh face (a small bonus, real reamer
physics); pressing WITHOUT twisting mashes → pulp + bench spray + no juice;
pressing too HARD shoves seeds past the moat; grinding a DRY half reams the pith
→ bitterness that no yield buys back.
- Three tiers as tools (like knives differ): Pyramid Classic (no moat, ream 0.92),
Ribbed Deluxe (catches ~80%, +4%), The Juicernaut (catches all, +10%, ream 1.32).
- Single game integration point, documented in-file: juiceResult(session) → the
number-bag; juiceCriteria(result) → The Juice (yield band − bitterness − murk,
w1.3) + Pips (seed count, w1.1); JUICE_LINES (5 bad / 3 good each) +
juicerRecognitionLine(). Bench rides the existing benchCriterion via result.bench.
NEW src/scenes/juice.ts: JuiceView mirroring prep.ts — procedural ribbed cone in
a moat dish, glass with a rising juice column, orange half, mess field for spray,
loadProp GLB fallbacks (juicer_pyramid/juice_glass). Live HUD reads the judge's
own numbers: "62% of what this orange had", a ceiling marker the fill can't pass,
pips (click to fish out), bench word, pith warning.
NEW src/dev-juice.ts: SEPARATE installer (no collision with dev.ts) — owns its own
JuiceView, drives the REAL input path (pointer circles for the twist, press
injected like dev.ts injects kitchen.power). Exposes window.__tj. main.ts: one
additive DEV-only import line.
VERIFY (reviewer, ~3 console calls after the dev server loads):
__tj.enter({ seeds: 5 }); __tj.twist(3, 0.7); __tj.stats()
→ yieldOfOrange ~0.73, pips 4 (Pyramid lets seeds through), bench dirtied
__tj.enter({ juicer: 'juicernaut', seeds: 5 }); __tj.twist(4, 0.8); __tj.stats()
→ yieldOfReachable ~1.0, pips 0 (catches all), bitterness rises if you grind on
__tj.enter({ offset: 0.2 }); __tj.twist(6, 0.8); __tj.stats()
→ theoretical ~0.60, yieldOfOrange caps at ~0.60 (the butchered halve)
__tj.enter(); __tj.mash(1.0, 0.9); __tj.stats()
→ extracted 0, pulp/spray > 0, pips forced out (lean-without-twist = a mash)
__tj.enter(); __tj.wristle(6, 0.7); __tj.stats() vs __tj.twist(3, 0.7)
→ wristle ~0.77 vs twist ~0.73 at equal sweep: reversals pay off
Measured (standalone port of the sim, same constants):
pyramid 3rev@0.7 → 0.728 | @0.9 → 0.936 | 5rev@0.85 → 1.0 (bitter 0.38, over-reamed)
deluxe 4rev@0.8 → caught 3/5, 2 pips | juicernaut → caught 5/5, 0 pips
butcher off .2 → capped 0.60 | mash 1s@0.9 → ext 0, pulp 0.135, 3 pips
tsc --noEmit clean; npm run build clean. Not routed into game.ts yet (game lane's
job) — the harness owns the view so the station is fully drivable now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|