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>
32 lines
1.5 KiB
TypeScript
32 lines
1.5 KiB
TypeScript
/**
|
|
* Test/dev helpers for LANE-SIM. Not part of the game loop — nothing in src/main.ts,
|
|
* src/render, src/ui or src/screen imports this, and it tree-shakes out of the bundle.
|
|
*
|
|
* Why it exists: contracts v4 gates every id named by a tech's `unlocks`, and that
|
|
* includes the mosh reactor, the software decoder and the subsampler. So the reference
|
|
* factory — the endgame demo — is no longer buildable from a fresh sim by design. It
|
|
* represents a save where the research has already happened, and this is how a test says
|
|
* so honestly, through the public save/load API rather than a back door into the sim.
|
|
*
|
|
* There is currently no legitimate in-sim path to this state: DATA ships no `kind:'lab'`
|
|
* machine, and every science pack is made on the artifact-bottler, which is itself locked
|
|
* behind a tech costing 10 analog-packs. See NOTES round 4.
|
|
*/
|
|
import type { GameData, Sim } from '../contracts';
|
|
|
|
/**
|
|
* Rewrites a sim's research state to treat `techIds` as completed, via a save/load
|
|
* round-trip. Call it on a fresh sim before enqueueing anything — load() replaces the
|
|
* whole world, so any entities placed first would be discarded.
|
|
*/
|
|
export function grantResearch(sim: Sim, techIds: string[]): void {
|
|
const blob = JSON.parse(sim.save());
|
|
blob.research = { active: null, progress: {}, unlocked: [...techIds] };
|
|
sim.load(JSON.stringify(blob));
|
|
}
|
|
|
|
/** The late-game save: everything DATA's tech tree gates is open. */
|
|
export function grantAllResearch(sim: Sim, data: GameData): void {
|
|
grantResearch(sim, data.tech.map((t) => t.id));
|
|
}
|