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