feat: map spread limit — random 1-4 legs + loop-closing routes (#51, v0.13.0) #53

Merged
kamilkrzywda merged 3 commits from feat/map-spread-limit into master 2026-10-06 14:40:02 +02:00
Owner

#51 — map spread limit (v0.13.0)

Jumping into an undiscovered system now spreads a seeded-random 1–4 legs instead of a fixed 4. Interpretation of the "more circular" part of the issue:

  • Each leg has a 35% chance to close onto the existing chart: instead of minting a new system it becomes a new two-way route to a randomly chosen existing system — loops in the graph make the map more circular and it grows ~2.3x slower on average (~1.7 new systems per discovery instead of 4).
  • A leg that would duplicate an already-existing route mints a new system instead (no wasted legs, no PK violations).
  • Frontier guarantee: at least one new system is always minted per discovery, so the map can never exhaust (invariant the e2e helpers rely on).
  • All randomness is drawn from the existing seeded expansionRng(seed, turn) stream in a fixed order — the same save + turn always reproduces the same chart.

Also fixes a latent bug: ringEdges for 1-2 members emitted a self-loop / duplicate route that would violate the jump_routes primary key (unreachable before, since the count was fixed at 4; n>=3 output is byte-identical, start region unchanged).

Verification

  • Unit: 194/194 (rewritten world.test.ts ringEdges + generateRing suite incl. pinned deterministic values and the frontier guarantee; save.test.ts now asserts 1-4 fresh systems; A/B full-DB byte-identity snapshot test unchanged and passing)
  • E2E (CI-only): new smoke test — jump into undiscovered territory mints 1-4 new systems, each undiscovered and routed to the target, and the graph stays connected (BFS)
  • Typecheck clean

Closes #51

## #51 — map spread limit (v0.13.0) Jumping into an undiscovered system now spreads a **seeded-random 1–4 legs** instead of a fixed 4. Interpretation of the "more circular" part of the issue: - Each leg has a **35% chance to close onto the existing chart**: instead of minting a new system it becomes a new two-way route to a randomly chosen existing system — loops in the graph make the map more circular and it grows ~2.3x slower on average (~1.7 new systems per discovery instead of 4). - A leg that would duplicate an already-existing route mints a new system instead (no wasted legs, no PK violations). - **Frontier guarantee**: at least one new system is always minted per discovery, so the map can never exhaust (invariant the e2e helpers rely on). - All randomness is drawn from the existing seeded `expansionRng(seed, turn)` stream in a fixed order — the same save + turn always reproduces the same chart. Also fixes a latent bug: `ringEdges` for 1-2 members emitted a self-loop / duplicate route that would violate the `jump_routes` primary key (unreachable before, since the count was fixed at 4; n>=3 output is byte-identical, start region unchanged). ### Verification - Unit: 194/194 (rewritten `world.test.ts` ringEdges + generateRing suite incl. pinned deterministic values and the frontier guarantee; `save.test.ts` now asserts 1-4 fresh systems; A/B full-DB byte-identity snapshot test unchanged and passing) - E2E (CI-only): new smoke test — jump into undiscovered territory mints 1-4 new systems, each undiscovered and routed to the target, and the graph stays connected (BFS) - Typecheck clean Closes #51
kamilkrzywda added 3 commits 2026-10-06 14:36:43 +02:00
- ringEdges: n=0 → [], n=1 → [[0,1]], n=2 → [[0,1],[0,2],[1,2]];
  n≥3 wheel is byte-identical to the legacy output.
- generateRing: new params attachCandidates, existingEdgeKeys, anchorId;
  legCount is seeded-random in [EXPAND_MIN, EXPAND_MAX] (1–4);
  each leg may attach a known system (closing a loop) with prob ATTACH_PROB
  instead of minting; frontier guarantee converts the last-drawn attach
  to a mint when all legs attached.
- RingRegion gains attaches: number[] (candidate indices attached).
- Remove the EXPAND_RING constant (replaced by EXPAND_MIN/EXPAND_MAX).
- resolveJumpTask: build existingEdgeKeys from all jump routes (both
  endpoints in the save's system set), pass all systems except the
  target as attachCandidates, insert closing routes for each attach.
- save.test.ts: jump test now expects 1–4 fresh systems (was pinned
  to exactly 4); A/B snapshot test stays green (both paths share the
  same resolveJumpTask code).
- e2e/helpers.ts: update stale comment ('4 fresh neighbours' →
  '1–4 new systems').
- e2e/smoke.spec.ts: new test verifying 1–4 mints, all undiscovered,
  each routed to the target, and BFS connectivity of the full graph.
chore: bump to v0.13.0 — #51 map spread limit + loop-closing routes
CI / build + unit + e2e (pull_request) Successful in 3m15s
d20037762d
kamilkrzywda scheduled this pull request to auto merge when all checks succeed 2026-10-06 14:36:49 +02:00
kamilkrzywda merged commit 311eb5c713 into master 2026-10-06 14:40:02 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OpenCode/SpaceWanderer#53