Round 4 per lanes/LANE-SIM.md. - research v1: kind:'lab', setResearch, snapshot.research, 'researched'. Gating: any id a tech unlocks is refused until that tech lands; ids no tech names are free forever. Labs take only what the active tech still needs; several labs feed one total; research survives save/load as a RULE, so a restored save can still build what it unlocked - realtech.test.ts: a cold-start research run on DATA's own tree -- ore -> packs -> archaeology lab -> tech -> a refused recipe now accepted. Also the tripwire if the tech bootstrap ever closes over again; it was circular and unenterable at the start of this round - spatial cooling: coolRadius, chebyshev from the footprint, auras sum, total capped at HEAT_COOL_MAX (0.05 -- past that a stack buys nothing but still costs bandwidth and floor). Proven by measuring shed rate - src/sim/constants.ts: 12 constants so DATA imports truth instead of hand-copying numbers that go stale in silence - reference v4: anchor-slab overflow tap, so the demo ships slabs (18 per 20k). Needed TWO melt lanes: with one, melt spills onto the slab lane and the splitter phase-locks with the reactor's push order -- slab to the assembler, melt to the uplink, forever, and no slab ever sold. It passed 20k ticks looking perfect. referenceFactoryTech() derives the techs the layout needs, from the commands - also wired: bandwidth.capacity, EntityState.scrammed, commissionQueue 65 sim tests, 318 across the repo. Melt still tick 1248, zero brownouts over 20k. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58 lines
2.6 KiB
TypeScript
58 lines
2.6 KiB
TypeScript
/**
|
|
* LANE-SIM's tuning constants — the single source of truth.
|
|
*
|
|
* These were private to index.ts until round 4. They're exported because other lanes'
|
|
* tests were hand-copying the numbers and going stale in silence: a copy of 0.7 doesn't
|
|
* fail when the sim moves to 0.65, it just quietly asserts the wrong thing forever.
|
|
* Import these rather than retyping them.
|
|
*
|
|
* Anything DATA can already set per-machine (heatPerTick, coolPerTick, bufferCap,
|
|
* beltSpeed, coolRadius) lives in data/machines.json, not here. These are the sim-wide
|
|
* rules that no machine overrides.
|
|
*/
|
|
|
|
// ------------------------------------------------------------------ belts
|
|
|
|
/** Minimum gap between two items, in belt-tiles. Enforced across the tile seam too. */
|
|
export const BELT_SPACING = 0.45;
|
|
/** Items a single belt tile may hold. */
|
|
export const BELT_CAPACITY = 2;
|
|
/** Items a splitter holds while it waits for an output to open. */
|
|
export const SPLITTER_CAPACITY = 2;
|
|
|
|
// -------------------------------------------------------------- machines
|
|
|
|
/** A machine stalls ('output full') once any output piles to this multiple of its yield. */
|
|
export const OUTPUT_STALL_FACTOR = 4;
|
|
/** A machine accepts an input up to this multiple of the recipe requirement. */
|
|
export const INPUT_BUFFER_FACTOR = 2;
|
|
|
|
// ------------------------------------------------------------------ heat
|
|
//
|
|
// heatPerTick is GROSS (contracts v4): net climb = heatPerTick - coolPerTick, so a
|
|
// machine whose heatPerTick never clears its cooling can never overheat.
|
|
|
|
/** Below this heat, throttling is purely cosmetic. */
|
|
export const HEAT_THROTTLE_START = 0.7;
|
|
/** Speed multiplier at heat 1.0 — the codex's "tick rate visibly halves". */
|
|
export const HEAT_THROTTLE_FLOOR = 0.5;
|
|
/** Heat at which a machine scrams. */
|
|
export const HEAT_SCRAM = 1;
|
|
/** Cool back below this and a scrammed machine restarts. */
|
|
export const HEAT_RESTART = 0.5;
|
|
/** Per-tick cooling when a machine's def doesn't specify `coolPerTick`. */
|
|
export const HEAT_COOL_DEFAULT = 0.004;
|
|
/**
|
|
* Ceiling on a machine's total cooling once auras stack (own rate + every cooler in
|
|
* range). At 0.05 a machine sheds a full 1.0 of heat in 20 ticks (~0.67s), which is
|
|
* already effectively instant — past this, extra coolers would buy nothing but would
|
|
* still cost bandwidth and floor space, and stacking them would look broken rather than
|
|
* generous. See NOTES round 4.
|
|
*/
|
|
export const HEAT_COOL_MAX = 0.05;
|
|
|
|
// ---------------------------------------------------------------- tracing
|
|
|
|
/** Belt graphs bigger than this are treated as unterminated (cheap loop guard). */
|
|
export const MAX_TRACE = 512;
|