glytch/fktry/lanes/LANE-SIM.md
type-two 1a769e6cbd Baseline: GLYTCH prototype, FKTRY lore codex, scaffold + 5-lane orchestration docs
- 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>
2026-07-17 15:51:12 +10:00

4.2 KiB
Raw Blame History

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 test green 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:

  1. World + placement. Tile grid (start 64×64, world-centered). place command: validate footprint fits and tiles are free, spawn EntityState, emit placed. remove (emit removed, refund nothing yet), rotate, setPaused. Invalid commands are silently dropped (UI will preview validity later).
  2. Belts. kind:'belt' entities carry up to 2 items each as BeltItem (t: 0..1), moving at beltSpeed tiles/sec. Items transfer to the belt/machine the belt points into (dir). Items on a belt keep minimum spacing 0.45. Belt→machine: push into inputBuf if 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.
  3. Crafting. Machines with recipes: when inputBuf covers inputs, consume, run ticks (progress 0..1), emit crafted, deposit outputs into outputBuf. If outputBuf holds ≥ 4× outputs, machine stalls with jammed:"output full" (emit jammed once per stall, not per tick). Extractors need no inputs. Machines with multiple recipes use setRecipe; default to recipes[0].
  4. 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), emit brownout on/off edges, set snapshot.bandwidth accordingly. No storage/buffer tanks yet.
  5. Shipping. kind:'shipper' consumes ANY item arriving in its input, increments shippedTotal, emits shipped. Track the single active commission (first in data): fill commissionProgress, emit commissionDone once satisfied.
  6. 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