Build Brief 1: the puppet, the food, the samurai
Sandoniette (サンドニエット) — 2D shadow-puppet kitchen. Marionette chef on honest string physics, comical food with mass, the samurai as the toastsim judge wearing armor, SHUBATTO string-cut fail state. Milestones M0-M6 with harness-verified exit bars; steals toastsim's discipline (dev harness, pieceCV, judge line banks, verify-or-it-didn't-happen), not its code. Assets: MODELBEAST flux 2D only, shadow-theatre style token, seeds 301+. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
commit
0eb48b87e6
202
OPUS-BUILD-BRIEF.md
Normal file
202
OPUS-BUILD-BRIEF.md
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
# サンドニエット SANDONIETTE — Build Brief 1: The Puppet, The Food, The Samurai
|
||||||
|
|
||||||
|
*"SHUBATTO! SANDO-NI-ETTE!!!" — read this file and execute it. It is written to
|
||||||
|
work cold: a fresh session with no other context should be able to build this
|
||||||
|
game from here. Sibling project: `~/Documents/toastsim` — do NOT touch it, but
|
||||||
|
DO steal its discipline (this brief tells you exactly what to steal).*
|
||||||
|
|
||||||
|
## 0. What this game is
|
||||||
|
|
||||||
|
A 2D shadow-puppet kitchen. You are a **silhouette marionette chef** operated
|
||||||
|
by strings — and only by strings. You cut comical food, stack it into
|
||||||
|
sandwiches, carry the dish across the stage, and serve it to your one
|
||||||
|
customer: a giant, permanently unimpressed **samurai**, glaring down at the
|
||||||
|
kitchen like a health inspector from hell. Do badly — drop things, mangle the
|
||||||
|
cut, stack a leaning tower, serve late — and his katana unsheathes a little
|
||||||
|
more. At maximum: **SHUBATTO** — one lightning slash, your strings are cut,
|
||||||
|
and the chef collapses into a floppy ragdoll amid flying ingredients. Restart.
|
||||||
|
|
||||||
|
The comedy IS the physics: puppeteer lag, pendulum swing, food with mass.
|
||||||
|
The difficulty is "cunty hard but fair" — Loot Cycle Inc. tension, not
|
||||||
|
Sekiro. Every failure must be readable as YOUR wobble, never RNG.
|
||||||
|
|
||||||
|
Fictional inspiration stack (for taste, not code): Loot Cycle Inc. (physics
|
||||||
|
triage under a ticking fail-state), Ratatouille (tiny chef, big kitchen),
|
||||||
|
1997 bargain-bin PS1 import energy (Pepsi Man voice, broken-Engrish UI).
|
||||||
|
|
||||||
|
## 1. The design law (inherited from TOASTSIM, adapted)
|
||||||
|
|
||||||
|
1. **One game, not minigames in a trench coat.** Cut, carry, stack, serve are
|
||||||
|
all the same verb — *move a pendulum with intent* — scored by the same
|
||||||
|
judge. A new mechanic must ride the string sim or improve it for everyone.
|
||||||
|
2. **The judge is the voice.** The samurai is toastsim's judge generalized:
|
||||||
|
named criteria with bands, a line bank with 8+ lines per criterion, the
|
||||||
|
scorecard as the emotional payoff. He speaks subtitled Japanese barks with
|
||||||
|
deadpan Engrish translations — *"SANDO... ga... yugande iru."* ("The
|
||||||
|
sandwich. It leans.")
|
||||||
|
3. **Physics is the comedian, the sim is honest.** No canned animations for
|
||||||
|
gameplay outcomes — if the tower falls, it falls because the center of
|
||||||
|
mass left the base. Comedy from real consequences, always.
|
||||||
|
4. **Nothing ships unverified.** The dev harness drives REAL input
|
||||||
|
deterministically and every milestone commits with measured numbers.
|
||||||
|
This is toastsim's single most valuable organ. Transplant it first.
|
||||||
|
5. **Failure must be readable.** The player must be able to say what they did
|
||||||
|
wrong from the wreckage alone. If a fail reads as random, it's a bug in
|
||||||
|
the DESIGN even when the code is correct.
|
||||||
|
|
||||||
|
## 2. Tech decisions (made — don't relitigate)
|
||||||
|
|
||||||
|
- **Vite + TypeScript + Phaser 3 (Matter physics build)**. One engine
|
||||||
|
dependency; Matter gives joints/constraints for the marionette and food.
|
||||||
|
Same repo shape as toastsim: `src/sim/` pure logic, `src/scenes/`
|
||||||
|
presentation, `src/dev.ts` harness, `npm run typecheck` must stay clean.
|
||||||
|
- **The strings are Verlet-ish chains of small Matter bodies + pin
|
||||||
|
constraints** (stiffness < 1 so they stretch visibly under abuse). If
|
||||||
|
Matter's constraint jitter fights back, fall back to pure-math Verlet
|
||||||
|
ropes rendered as polylines with only the ENDS as Matter bodies —
|
||||||
|
pre-authorized judgment call.
|
||||||
|
- **Silhouettes that carry physics are procedural polygons** (flat black
|
||||||
|
vector shapes with visible pin-joints, like Balinese/Japanese shadow
|
||||||
|
puppets). Generated art is for backdrops, food faces, the samurai, title —
|
||||||
|
never for collision shapes. (Toastsim law: silhouettes are gameplay.)
|
||||||
|
- **Determinism**: fixed-dt stepping (`app.step(dt)` equivalent — Phaser's
|
||||||
|
`update` driven manually in harness mode), seeded RNG only. No `Date.now()`
|
||||||
|
in sim code.
|
||||||
|
|
||||||
|
## 3. The bones to build (in order; each is a pure module + a scene + harness verbs)
|
||||||
|
|
||||||
|
### 3.1 `sim/marionette.ts` — the puppet
|
||||||
|
Classic marionette rig: a **control bar** (the player's proxy) + strings to
|
||||||
|
head, two hands, two knees. Mouse position = bar position; mouse tilt comes
|
||||||
|
from horizontal velocity; hold LMB = lower the bar (crouch/reach), release =
|
||||||
|
lift; RMB or Space = the GRIP (both hands clamp). That's the whole control
|
||||||
|
surface — depth comes from the pendulum, not the input map.
|
||||||
|
- Puppet body: 9 segments (head, torso ×2, upper/lower arms, thighs/shins as
|
||||||
|
single limbs to start), pin joints with angular limits.
|
||||||
|
- **The lag is the game**: strings transmit force with ~0.15s of felt delay
|
||||||
|
(stiffness/damping tuned, not a literal buffer). Walk = rhythmic bar sway
|
||||||
|
that gets the legs swinging. It must feel like Getting Over It's honesty
|
||||||
|
with Octodad's dignity.
|
||||||
|
- Harness: `__s.bar(x,y)`, `__s.sway(freq, amp, secs)`, `__s.grip(on)`,
|
||||||
|
`__s.pose()` → joint angles, `__s.settle()` → frames-to-rest.
|
||||||
|
- **Exit bar (M1)**: pendulum settle time measured; a scripted sway walks the
|
||||||
|
puppet 6 stage-units without face-planting; grip picks a box off the floor
|
||||||
|
10/10 times in harness. Feel: dangle a hand over a table edge — it should
|
||||||
|
make you smile before any food exists.
|
||||||
|
|
||||||
|
### 3.2 `sim/food.ts` + cutting
|
||||||
|
Food = 2D convex-ish polygon bodies with mass, friction, a `face` sprite,
|
||||||
|
and toastsim-style material params: `skin.resistance`, `flesh.moisture`
|
||||||
|
(wet food SPLATS — a 2D mess decal + slippery floor patch), `wobble`
|
||||||
|
(jelly-class food jiggles as soft constraint clusters).
|
||||||
|
- **The cut**: cleaver in gripped hand; a cut commits when blade-edge speed ×
|
||||||
|
angle-through-food crosses threshold (a slow push SQUASHES — moisture
|
||||||
|
splats, no cut). Pieces are real bodies with the parent's face split
|
||||||
|
across them. Cut quality = blade angle + speed + follow-through, scored as
|
||||||
|
**clean / ragged / crime** (crime = squashed).
|
||||||
|
- Harness: `__s.spawnFood(id, x)`, `__s.swing(from, to, secs)`,
|
||||||
|
`__s.cutStats()` → pieces, area CV (toastsim's pieceCV, straight port of
|
||||||
|
the idea), splat mass.
|
||||||
|
- **Exit bar (M2)**: a practiced harness swing produces 2 clean pieces with
|
||||||
|
area CV < 0.1; a slow push produces 0 pieces + splat > 0; a wild fast
|
||||||
|
swing sends a piece flying offstage (and that's CORRECT).
|
||||||
|
|
||||||
|
### 3.3 `sim/stack.ts` — the sando
|
||||||
|
Sandwich = ordered layers stacked by carrying pieces onto a plate zone.
|
||||||
|
Stability is honest Matter stacking, but SCORED: center-of-mass drift per
|
||||||
|
layer, overhang, lean angle. The order ticket names the target
|
||||||
|
(bread-filling-bread minimum; later: the katsu sando, the "tower" specials).
|
||||||
|
- Harness: `__s.stack()` → layers, lean°, COM drift; `__s.nudge(force)` for
|
||||||
|
the earthquake test.
|
||||||
|
- **Exit bar (M3)**: 3-layer sando stands; lean° reported; nudge test
|
||||||
|
topples a bad stack and not a good one; toppled food splats/rolls.
|
||||||
|
|
||||||
|
### 3.4 `sim/samurai.ts` — the judge + the fail state
|
||||||
|
The anger meter is toastsim's judge wearing armor. **Anger events**: drop
|
||||||
|
(+small), splat (+medium), crime-cut (+medium), served-wrong (+large),
|
||||||
|
served-late (+ramps), offstage food (+large). **Cooldown**: a clean serve
|
||||||
|
sheathes a little. Meter states = katana unsheath stages (0/25/50/75%:
|
||||||
|
eyebrow → hand-on-hilt → 10cm of blade → full glare, screen vignettes).
|
||||||
|
- **THE STRING CUT**: at 100% — freeze 300ms, slash line across the screen,
|
||||||
|
ALL string constraints deleted in one frame, ragdoll collapse, ingredients
|
||||||
|
launched with the impulse of the slash, gong. Score card over the wreckage.
|
||||||
|
It must be fast, unfair-FEELING but earned, and funny every single time.
|
||||||
|
- Serve = dish carried into the counter zone + a bow (hold still 0.5s — the
|
||||||
|
dwell commit, straight from toastsim).
|
||||||
|
- Scorecard groups: **THE CUT / THE SANDO / THE SERVICE / THE FLOOR** (the
|
||||||
|
floor = mess+drops; the bench criterion reborn). 8+ lines each, bilingual
|
||||||
|
bark + Engrish subtitle. Grade S–D; S = "…umai." and a single approving nod.
|
||||||
|
- **Exit bar (M4)**: full loop playable — order in, cut, stack, carry, serve,
|
||||||
|
scored; harness plays a clean run (B or better) and a disaster run (strings
|
||||||
|
cut) deterministically; numbers in the commit message.
|
||||||
|
|
||||||
|
### 3.5 Orders, days, escalation (M5)
|
||||||
|
Ticket rail like toastsim's days: Day 1 = one open sando. Escalate
|
||||||
|
ingredient count, wetness (tomato before you've earned it is cruelty),
|
||||||
|
required cuts, and the samurai's patience ramp. **One new pressure per day,
|
||||||
|
never two.** Day N bar: each day introduces its thing and is beatable by the
|
||||||
|
harness with a scripted-but-honest run.
|
||||||
|
|
||||||
|
### 3.6 The juice (M6)
|
||||||
|
Title screen: giant brush-stroke 「サンドニエット」, the voice line (text
|
||||||
|
crawl + gong if no audio yet: **SHUBATTO!! SANDONIETTE!!!**), attract-mode
|
||||||
|
ragdoll. Shamisen sting + slash whoosh + wet splats (Web Audio, synthesized
|
||||||
|
or CC0 — no paid assets). Unlockable strings as difficulty modifiers —
|
||||||
|
**rubber** (bouncy, +lag +comedy), **chain** (heavy, slow, precise), **silk**
|
||||||
|
(tighter, for cowards) — pre-authorized to defer if M5 lands better without.
|
||||||
|
|
||||||
|
## 4. Assets — MODELBEAST, 2D ONLY (this game needs no meshes)
|
||||||
|
|
||||||
|
Steal `scripts/gen-assets.sh` from toastsim as the template, keep only the
|
||||||
|
flux path (`run_flux` + `run_cutout`). **Machine facts current as of
|
||||||
|
2026-07-17** (verified the hard way): client lives at `~/MODELBEAST` (NOT
|
||||||
|
~/Documents), token is `MB_TOKEN` in `~/Documents/backnforth/.env`, export
|
||||||
|
`MB_HOST=http://100.89.131.57:8777` (m3ultra queue). Node m4's venvs are
|
||||||
|
dead — every stage retries up to 10× with 60s pauses until a healthy node
|
||||||
|
takes the job; keep that loop until told m4pro is healed.
|
||||||
|
|
||||||
|
Style token (fix it, reuse it everywhere):
|
||||||
|
`"japanese shadow puppet theatre, flat black silhouette with cut-out
|
||||||
|
details, warm washi paper backdrop, edo period, high contrast, hand-crafted
|
||||||
|
paper texture"`.
|
||||||
|
|
||||||
|
Batch 1 (fixed seeds, start at 301): washi/shoji stage backdrop, wooden
|
||||||
|
stage floor boards, the samurai in 5 anger states (SAME seed, expression
|
||||||
|
phrase varies — the toastsim judge-portrait trick), title brushwork art,
|
||||||
|
paper order tickets, food FACES (bread, tomato, cheese, katsu, egg —
|
||||||
|
comical, slightly alarmed), splat decals, the katana slash frame.
|
||||||
|
Fire asset jobs FIRST, build procedural while they render, `loadProp`-style
|
||||||
|
catch-fallbacks so the game never blocks on art.
|
||||||
|
|
||||||
|
## 5. What to steal from toastsim, literally
|
||||||
|
|
||||||
|
Open these files and port the PATTERN (not the code — different engine):
|
||||||
|
- `src/dev.ts` — the harness: real input driven deterministically, helpers
|
||||||
|
returning stats objects, `window.__s` installer. THE most important file.
|
||||||
|
- `src/sim/cutting.ts` — pieceCV and the cvWord ladder; material params.
|
||||||
|
- `src/game/judging.ts` + `lines.ts` — criteria bands, weighted groups, the
|
||||||
|
line bank shape and its voice discipline.
|
||||||
|
- `OPUS-BUILD-BRIEF-2.md §0` — the verify discipline and "known traps" habit:
|
||||||
|
keep a STATUS section at the top of THIS file updated as you go, so any
|
||||||
|
session can pick up cold.
|
||||||
|
|
||||||
|
## 6. Milestone order and the bar
|
||||||
|
|
||||||
|
M0 bootstrap (vite+ts+phaser+harness skeleton, typecheck green, a Matter box
|
||||||
|
drops onto the stage floor) → M1 puppet → M2 cutting → M3 stacking → M4
|
||||||
|
samurai + full loop → M5 days → M6 juice. One commit per milestone, message
|
||||||
|
= what you measured. Screenshots when visuals change. If a feel is wrong,
|
||||||
|
fixing feel beats advancing — the three feels that must be RIGHT: **the
|
||||||
|
dangle** (M1), **the clean chop** (M2), **the string cut** (M4).
|
||||||
|
|
||||||
|
Pre-authorized judgment calls: all tuning constants; Verlet fallback (§2);
|
||||||
|
segment count on the puppet; deferring string unlockables; cutting a food
|
||||||
|
type that won't behave. Do NOT add: paid/cloud dependencies, accounts,
|
||||||
|
telemetry, or 3D. Do not touch `~/Documents/toastsim` or `~/MODELBEAST`
|
||||||
|
except through `mb`.
|
||||||
|
|
||||||
|
The bet: toastsim proved the bones (harness, honest sim, judge voice, free
|
||||||
|
assets) make a game feel handmade and alive. Sandoniette bets the same bones
|
||||||
|
survive transplant into slapstick — that "verified physics comedy" is a
|
||||||
|
genre, and we can build it in milestones without ever shipping an unfunny
|
||||||
|
fall or an unfair death.
|
||||||
Loading…
Reference in New Issue
Block a user