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

76 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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). Machinebelt: 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
```