- index.html: WIMVEE GLYTCH match-the-glitch prototype (playable)
- docs/FKTRY_LORE.md: world bible / MODELBEAST asset codex
- fktry/: vite+three+TS scaffold, contracts, main loop, seed data
- fktry/MASTERPLAN.md + CONTRACTS.md + lanes/LANE-{SIM,RENDER,UI,SCREEN,DATA}.md:
round protocol and Round 1 orders for parallel Opus 4.8 executors
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.2 KiB
LANE-SIM — deterministic factory simulation
You are an Opus 4.8 executor on the SIM lane of FKTRY. Read ../MASTERPLAN.md and
../CONTRACTS.md before anything else; the world bible is ../../docs/FKTRY_LORE.md.
Mission: the headless, deterministic heart of the game. Grid, entities, belts, recipes, power, events. If the renderer were deleted, your sim should still be fully playable through unit tests. You are the lane the other four trust with their lives.
Owned paths: src/sim/** (including your tests: src/sim/*.test.ts).
Never touch: contracts, main.ts, other lanes, data JSONs (request changes via NOTES).
Standing rules (all rounds):
- Deterministic: seedable RNG (write your own mulberry32-style helper), no wall-clock, no unseeded Math.random. Same seed + same commands = identical snapshots.
- Every mechanic lands with tests.
npm testgreen before you write NOTES. - Performance target: 1,000 entities + 5,000 belt items at 30 tps without heroics. Prefer flat arrays and index maps over object soup. Don't allocate in the tick loop when avoidable.
- Snapshot may reuse buffers, but its SHAPE must always match
SimSnapshot.
CURRENT ORDERS — Round 1 (goal: milestone M1 "FLOW")
Replace the stub in src/sim/index.ts with a real implementation:
- World + placement. Tile grid (start 64×64, world-centered).
placecommand: validate footprint fits and tiles are free, spawnEntityState, emitplaced.remove(emitremoved, refund nothing yet),rotate,setPaused. Invalid commands are silently dropped (UI will preview validity later). - Belts.
kind:'belt'entities carry up to 2 items each asBeltItem(t: 0..1), moving atbeltSpeedtiles/sec. Items transfer to the belt/machine the belt points into (dir). Items on a belt keep minimum spacing 0.45. Belt→machine: push intoinputBufif the machine's current recipe wants that item and buffer < 2× recipe need; otherwise the item waits (belt backs up — this is core Factorio feel, get it right). Machine→belt: outputs pop onto an adjacent belt facing away, one item per available slot. - Crafting. Machines with recipes: when
inputBufcoversinputs, consume, runticks(progress 0..1), emitcrafted, depositoutputsintooutputBuf. IfoutputBufholds ≥ 4× outputs, machine stalls withjammed:"output full"(emitjammedonce per stall, not per tick). Extractors need no inputs. Machines with multiple recipes usesetRecipe; default torecipes[0]. - Bandwidth (power) v1. Sum powerGen (power kind) vs powerDraw of all entities +
active recipe
bandwidth(note: negative recipe bandwidth GENERATES — quantizer compression pays power, per lore). If draw > gen: global speed multiplier = gen/draw for all progress and belt movement (brownout), emitbrownouton/off edges, setsnapshot.bandwidthaccordingly. No storage/buffer tanks yet. - Shipping.
kind:'shipper'consumes ANY item arriving in its input, incrementsshippedTotal, emitsshipped. Track the single active commission (first in data): fillcommissionProgress, emitcommissionDoneonce satisfied. - Tests (minimum): placement collision; belt line moves an item end to end in the expected tick count; belt back-pressure (full line stops cleanly, no item loss/dupe); demux recipe consumes 2 ore → 1 luma + 1 slurry; brownout halves speed at draw=2×gen; determinism (two sims, same seed+commands, 500 ticks, deep-equal snapshots); shipping increments and fires commissionDone.
Definition of done: with the dev server running, the orchestrator can (via UI or
console __fktryBus.dispatch(...)) place extractor→belts→demuxer→quantizer→
mosh-reactor→shipper and watch shippedTotal.melt climb. All tests green. NOTES
written (decisions, gotchas, what you'd tackle in round 2).
NOTES (append-only log, newest at bottom — template below)
### Round N — YYYY-MM-DD — [your model]
SHIPPED: what actually works now (verified how)
DECISIONS: choices you made inside your mandate
BLOCKED/BROKEN: anything not working, honestly
CONTRACT REQUEST: (if any)
PROPOSAL: (ideas for the orchestrator, optional)
NEXT: what you'd do next round if asked