“Game” — Cooking & Dealing Sim — Phase 1 Design¶
Status: Phase 1 of 5 approved for spec. Display title: “Game” · Internal slug:
cookgame(avoids collision with existingcomponents/game/andlib/game/; single constant, trivially renamed later). Genre: Satirical/fictional 3D crime-management sim. Public library entry. Engine: react-three-fiber + Rapier (declarative), reusing Forest Explorer patterns.
1. Premise & Tone¶
A clearly satirical, fictional tycoon sim in the vein of Steam’s Schedule I: the player runs an underground operation — buy ingredients, mix product for value-boosting “effects,” package it, and sell to neighbourhood NPCs while keeping “heat” down. Tone matches studio precedent (House Always Wins, rmh-capital): comedic and over-the-top, never instructional. No real-world chemistry, quantities, or procedures are modelled — production is abstracted into game-y stations and a data-driven effects engine. All substances/strains are invented.
2. Full-Game Roadmap (context)¶
The complete game is built in 5 stacked chunks; each is its own spec → plan → build cycle.
Phase |
Scope |
Depends on |
|---|---|---|
1 (this doc) |
Foundation + core loop: world, character, interaction, mixing/effects engine, inventory, packaging, selling, soft heat, save |
— |
2 |
Production pipelines: weed grow stations + chemistry-station cook mini-game; multiple bases feed the mixer |
1 |
3 |
Economy & progression: rank/XP, shops, property buy/upgrade, day–night & time cycle, recipe discovery depth |
1, 2 |
4 |
NPC simulation: customer base w/ demand & preferences, phone/deal system, hire employees & dealers (automation) |
1–3 |
5 |
Heat, police & cartel: police AI, busts, wanted escalation, rival factions, risk events |
1–4 |
Phase 1 is a fully playable vertical slice on its own: buy → mix → package → sell → improve recipes.
3. Phase 1 Architecture¶
Mirrors Forest Explorer’s layout so we reuse proven controller/interaction/save code.
lib/cookgame/
types.ts # shared TS types (Product, Additive, Effect, SaveV1, store shapes)
effects.ts # ⭐ PURE effects engine — mix(), value calc, transforms. No R3F. Unit-tested.
content.ts # data tables: BASES, ADDITIVES, EFFECTS, TRANSFORM_RULES, BUYERS
economy.ts # pure: buyer offer pricing, heat application, packaging yield
store.ts # Zustand store: cash, inventory, recipes, heat, player pos; actions
saveSystem.ts # versioned localStorage save/load (pattern copied from forest-explorer)
components/cookgame/
GameShell.tsx # auth gate + canvas mount (studio GameShell pattern)
CookGameGame.tsx # top-level: <Canvas>, scene, HUD, overlays, save wiring
world/
TownScene.tsx # ground, street, buildings (low-poly), boundary walls, lighting
PlayerController.tsx # WASD + mouse + sprint + E (adapted from forest-explorer)
Interactable.tsx # registers a station/NPC interaction zone
InteractionPrompt.tsx # "Press E" floating prompt
stations/
MixingStationOverlay.tsx # product slot + additive slot + Mix → effects/value preview
SupplierShopOverlay.tsx # buy bases & additives with cash
PackagingOverlay.tsx # convert mixed product → sellable units
npc/
BuyerNPC.tsx # static buyer model + interaction → SellOverlay
SellOverlay.tsx # buyer offer, accept/decline, applies heat
ui/
HUD.tsx # cash, heat meter, carried-product summary
RecipeJournal.tsx # discovered combos (journal-overlay pattern)
MenuOverlay.tsx # pause/save/reset
app/routes/cookgame.tsx # route → GameShell
lib/games.ts # add public GameInfo entry (id 'cookgame')
public/images/games/cookgame.webp # placeholder card art
3.1 Boundaries / isolation¶
effects.tsis pure and R3F-free — the crown jewel.mix(product, additive)and value computation are deterministic functions overcontent.tsdata; fully unit-testable with vitest (no DOM env needed — matches the repo’s pure-logic test constraint).economy.tspure too (offer pricing, heat, packaging) — testable in isolation.store.tsis the only stateful hub; React/R3F components are thin views over it.World/UI components depend on the store + pure libs, never on each other’s internals.
4. The Effects Engine (signature mechanic)¶
Data-driven, modelled on Schedule I’s mixing system.
Data shapes (types.ts):
interface Effect { id: string; name: string; multiplier: number; tier: 1|2|3; color: string; }
interface Additive { id: string; name: string; cost: number; baseEffect: EffectId; }
interface Base { id: string; name: string; baseValue: number; }
interface TransformRule { // mixing `additive` into a product carrying `from` → `to`
additive: AdditiveId; from: EffectId; to: EffectId;
}
interface Product { baseId: BaseId; effects: EffectId[]; } // carried/mixed product instance
mix(product, additive) → Product algorithm:
Start from
product.effects.Apply transform rules for this additive: any existing effect
frombecomesto(rules applied to a snapshot so one additive can’t cascade-transform its own outputs in a single mix).Add the additive’s
baseEffectif not already present.De-dupe; cap at 8 effects (excess dropped, lowest tier first).
Return
{ baseId, effects }. Output can be re-fed as input to stack effects across mixes.
Value: value(product) = round(base.baseValue × Π(effect.multiplier for each effect)).
Discovery: the first time a (state → newState) mix yields an effect set not seen before, it’s
recorded in the Recipe Journal. Journal persists in the save.
Phase-1 content budget (enough for real experimentation, small enough to ship/test):
1 base strain, ~8 additives, ~10 effects, ~12 transform rules. Tables live in
content.tsand are trivially expandable in later phases.
5. World, Character, Interaction¶
Map: one bounded block — your property (lab interior with Mixing + Packaging stations), a short street, a Supplier shop, and 2–3 static buyer spots. Low-poly stylized; day-only lighting. Boundary walls keep the player in-bounds.
Controls: third-person — WASD move, mouse-look camera, Shift sprint, E interact. Adapted from forest-explorer
PlayerController(Rapier capsule). Desktop-first; mobile joystick deferred.Interaction:
Interactableregisters a trigger zone + label; when the player is inside,InteractionPromptshows “Press E”; pressing E opens that station/NPC overlay. One active interaction at a time.
6. Core Loop & Economy¶
Supplier shop — spend cash on the base strain and additives (
SupplierShopOverlay).Mixing station — load product + an additive, preview resulting effects + value, confirm (
MixingStationOverlay). Re-feed to stack. New combos → journal.Packaging station — convert a mixed product batch into N sellable units (
economy.tspackaging yield), each carrying the product’s effect set/value.Sell — walk to a buyer;
SellOverlayshows an offer =value × (preference factor) × (heat penalty) × (small variance). Accept → cash gained, heat += sale increment. Decline → no change.Heat — single 0–100 meter; rises per sale, decays over real time while playing. Above a threshold buyers pay less / may decline. No police AI in Phase 1 (Phase 5).
Money is the score. No formal win condition in Phase 1.
7. State & Save¶
Zustand store holds:
cash,inventory(additives owned, product batches, packaged units),discoveredRecipes,heat,playerPosition, plus actions (buy,mix,package,sell,tickHeat). Pure libs do the math; the store just holds state and calls them.Save: versioned localStorage (
cookgame-save-v1), copied from forest-explorersaveSystem(size guard, version check, corrupt-data discard). Autosave on key actions + manual save in menu; load on mount; reset from menu.
8. Integration & Listing¶
lib/games.ts: new publicGameInfo(id: 'cookgame', title “Game”, satirical description, tags like['Simulation','Tycoon','Crime'],authGate: true, placeholderimagePath). The description copy will read clearly as comedic fiction.app/routes/cookgame.tsx: route rendersGameShell.Placeholder card art at
public/images/games/cookgame.webp.
9. Testing & Verification¶
Unit (vitest, pure logic — no DOM):
effects.ts(mixcorrectness, transform ordering, effect cap, value math, determinism) andeconomy.ts(offer pricing, heat penalty/decay, packaging yield). Run via./node_modules/.bin/vitestper repo constraints.Type/build: typecheck + build with
./node_modules/.bin/*wrappers (pnpm wrappers blocked).Manual: load route, full loop buy→mix→package→sell, heat rise/decay, save/reload persistence.
Run the
senior-swe-revieweragent before any PR (studio convention for game work).
10. Out of Scope for Phase 1 (handled by later phases)¶
Grow/cook production pipelines, multiple bases, rank/XP, shops beyond the single supplier, property purchase/upgrade, time-of-day cycle, customer demand simulation, phone/deal system, employees & dealers, police/cartel/busts, mobile controls. The Phase 1 data tables and store are shaped so each later phase extends rather than rewrites.