/** * The prep-bench cast. Everything a knife can be taken to, described by the * numbers the cutting sim actually consumes — shape for the silhouette and the * piece math, skin for the slip check, flesh for juice and layering, and the * station-specific extras (seeds, sting, temperature needs, gratability). * * 1 world unit ≈ 11cm, same convention as the loaf. */ export type IngredientShape = 'sphere' | 'ovoid' | 'block' | 'wedge' | 'bulb' | 'mushroom'; export interface Ingredient { id: string; name: string; shape: IngredientShape; /** Characteristic diameter/length in world units. */ size: number; /** resistance: how hard the skin fights the first bite. slippery: how keenly * it skates when pressed without sawing — the tomato number. */ skin: { resistance: number; slippery: number }; /** moisture > 0.4 juices when cut; layered flesh falls apart when mistreated. */ flesh: { resistance: number; moisture: number; layered?: boolean }; seeds?: { count: number; pocket: 'core' | 'distributed' }; /** Onions. 0..1, scales how fast cutting stings the eyes. */ sting?: number; temp?: { state: 'fridge' | 'bench'; softensInSec?: number; needsSoft?: boolean; needsCold?: boolean }; gratable?: { yield: number; pithDepth?: number }; roastable?: boolean; /** Authored sRGB, same convention as bread crumb/crust. */ colors: { skin: [number, number, number]; flesh: [number, number, number] }; } export type IngredientId = | 'tomato' | 'roast_tomato' | 'orange' | 'onion' | 'garlic' | 'parmesan' | 'brie' | 'cucumber' | 'avocado' | 'button_mushroom' | 'portobello' | 'king_oyster' | 'bell_pepper'; export const INGREDIENTS: Record = { tomato: { id: 'tomato', name: 'tomato', shape: 'sphere', size: 0.6, skin: { resistance: 0.35, slippery: 0.9 }, flesh: { resistance: 0.2, moisture: 0.75 }, seeds: { count: 20, pocket: 'distributed' }, roastable: true, colors: { skin: [0.82, 0.18, 0.12], flesh: [0.9, 0.35, 0.22] }, }, roast_tomato: { id: 'roast_tomato', name: 'roast tomato', shape: 'sphere', size: 0.52, // The skin blisters off in the oven; what's left is a water balloon. skin: { resistance: 0.1, slippery: 0.55 }, flesh: { resistance: 0.08, moisture: 0.95 }, colors: { skin: [0.62, 0.16, 0.1], flesh: [0.75, 0.28, 0.16] }, }, orange: { id: 'orange', name: 'orange', shape: 'ovoid', size: 0.68, skin: { resistance: 0.55, slippery: 0.45 }, flesh: { resistance: 0.3, moisture: 0.85 }, seeds: { count: 5, pocket: 'core' }, gratable: { yield: 1.0, pithDepth: 0.35 }, colors: { skin: [0.95, 0.55, 0.1], flesh: [0.98, 0.68, 0.2] }, }, onion: { id: 'onion', name: 'brown onion', shape: 'sphere', size: 0.62, skin: { resistance: 0.4, slippery: 0.6 }, flesh: { resistance: 0.45, moisture: 0.55, layered: true }, sting: 1.0, colors: { skin: [0.72, 0.5, 0.28], flesh: [0.93, 0.9, 0.82] }, }, garlic: { id: 'garlic', name: 'garlic', shape: 'bulb', size: 0.28, skin: { resistance: 0.25, slippery: 0.35 }, flesh: { resistance: 0.5, moisture: 0.3, layered: true }, sting: 0.15, colors: { skin: [0.9, 0.86, 0.8], flesh: [0.95, 0.92, 0.85] }, }, parmesan: { id: 'parmesan', name: 'parmesan', shape: 'block', size: 0.5, skin: { resistance: 0.8, slippery: 0.15 }, flesh: { resistance: 0.85, moisture: 0.1 }, temp: { state: 'fridge', softensInSec: 90, needsCold: true }, gratable: { yield: 0.9 }, colors: { skin: [0.85, 0.75, 0.5], flesh: [0.93, 0.87, 0.68] }, }, brie: { id: 'brie', name: 'brie', shape: 'wedge', size: 0.45, skin: { resistance: 0.3, slippery: 0.2 }, flesh: { resistance: 0.15, moisture: 0.35 }, // softensInSec tuned for M15: out on the bench at order start, a brie is // spreadable by the time the roast + toast are done (~45s of service). temp: { state: 'fridge', softensInSec: 80, needsSoft: true }, colors: { skin: [0.95, 0.93, 0.88], flesh: [0.97, 0.92, 0.78] }, }, cucumber: { id: 'cucumber', name: 'cucumber', shape: 'ovoid', size: 1.4, skin: { resistance: 0.5, slippery: 0.5 }, flesh: { resistance: 0.25, moisture: 0.8 }, seeds: { count: 14, pocket: 'distributed' }, colors: { skin: [0.2, 0.45, 0.16], flesh: [0.85, 0.94, 0.75] }, }, avocado: { id: 'avocado', name: 'avocado', shape: 'ovoid', size: 0.62, skin: { resistance: 0.7, slippery: 0.3 }, // Ripeness is a lottery: roll flesh resistance per-avocado at spawn. flesh: { resistance: 0.5, moisture: 0.45 }, seeds: { count: 1, pocket: 'core' }, colors: { skin: [0.16, 0.2, 0.1], flesh: [0.78, 0.85, 0.5] }, }, // The mushrooms: dry-slick skin that skates under a pressed blade, soft // flesh once the edge bites. Three varieties, three different fights. button_mushroom: { id: 'button_mushroom', name: 'button mushroom', shape: 'mushroom', size: 0.3, // Tiny and rolls away from the blade — the slip is the whole challenge. skin: { resistance: 0.15, slippery: 0.75 }, flesh: { resistance: 0.15, moisture: 0.35 }, roastable: true, colors: { skin: [0.92, 0.88, 0.8], flesh: [0.97, 0.95, 0.9] }, }, portobello: { id: 'portobello', name: 'portobello', shape: 'mushroom', size: 0.85, skin: { resistance: 0.2, slippery: 0.55 }, // Gills crumble when mistreated, and it weeps dark juice. flesh: { resistance: 0.2, moisture: 0.45, layered: true }, roastable: true, colors: { skin: [0.45, 0.32, 0.22], flesh: [0.82, 0.76, 0.66] }, }, king_oyster: { id: 'king_oyster', name: 'king oyster', shape: 'ovoid', size: 1.0, // Mostly one dense smooth stem — cuts like a slippery little log. skin: { resistance: 0.2, slippery: 0.8 }, flesh: { resistance: 0.35, moisture: 0.3 }, roastable: true, colors: { skin: [0.9, 0.87, 0.78], flesh: [0.96, 0.94, 0.88] }, }, bell_pepper: { id: 'bell_pepper', name: 'bell pepper', shape: 'sphere', size: 0.75, // Waxy gloss skin skates almost like the tomato; inside it's mostly air. // ponytail: hollowness isn't modelled — pieces come out as if solid. // Add a hollow flag to the piece math if rings/strips ever matter. skin: { resistance: 0.45, slippery: 0.65 }, flesh: { resistance: 0.2, moisture: 0.5 }, seeds: { count: 60, pocket: 'core' }, roastable: true, colors: { skin: [0.8, 0.12, 0.1], flesh: [0.88, 0.3, 0.2] }, }, };