import { content, type Location } from "@deadhead/content"; import { describe, expect, it } from "vitest"; import { checkRoute, effectiveStats, validateDispatch, validateReposition, wouldStrand, type Contract, type PilotState, type RepositionProposal, type ShipState, type SimContent, } from "../src/index"; const loc = (id: string) => content.location(id)!; const now = Date.parse("2100-01-01T00:30:00Z"); const pilot: PilotState = { id: "p1", isAvatar: false, assignedShipId: "s1", inFlight: false, skills: {}, restEndsAt: null, }; /** * Fixture: a short-legged ship and a heavy Moon (factor 0.5), so the ship can * reach the Moon from Earth but can't climb back out. "moon-station" shares the * Moon's position, so it is always in reach from there. */ const heavyMoon: Location = { ...loc("moon"), launchRangeFactor: 0.5 }; const station: Location = { ...heavyMoon, id: "moon-station", name: "Moon Station" }; const fixture: SimContent = { ...content, locations: [...content.locations.filter((l) => l.id !== "moon"), heavyMoon, station], shipModels: [ ...content.shipModels, { ...content.shipModel("courier")!, id: "hopper", fuelRangeMillionKm: 0.45 }, ], }; const hopper: ShipState = { id: "s1", modelId: "hopper", locationId: "earth", inFlight: false }; const proposal: RepositionProposal = { ship: hopper, pilot, destinationId: "moon", discoveredIds: new Set(["earth", "moon"]), credits: 100_000, now, }; const contract: Contract = { id: "c1", originId: "earth", destinationId: "moon", cargoTypeId: "standard", goodId: "consumer-goods", shipper: "Pacific Orbital Logistics", priority: false, deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 2000, requiredSkill: null, requiredLongHaulLevel: 0, offeredAt: Date.parse("2100-01-01T00:00:00Z"), expiresAt: Date.parse("2100-01-01T01:00:00Z"), firstContact: false, }; describe("no-strand rule (Step 10L.3, decision 0.5.79)", () => { it("rejects a deadhead that would leave the ship unable to fly anywhere", () => { expect(validateReposition(proposal, fixture)).toEqual({ ok: false, reason: "would-strand" }); }); it("passes the same trip once a reachable location is discovered", () => { const discoveredIds = new Set(["earth", "moon", "moon-station"]); expect(validateReposition({ ...proposal, discoveredIds }, fixture)).toEqual({ ok: true }); }); it("applies to contract dispatches too", () => { const base = { ship: hopper, pilot, contract, tutorial: false, credits: 100_000, now }; expect( validateDispatch({ ...base, discoveredIds: new Set(["earth", "moon"]) }, fixture), ).toEqual({ ok: false, reason: "would-strand" }); expect( validateDispatch( { ...base, discoveredIds: new Set(["earth", "moon", "moon-station"]) }, fixture, ), ).toEqual({ ok: true }); }); it("never blocks a base ship on a leg it can fly between the five locations (fixed map)", () => { const ids = content.locations.map((l) => l.id); for (const base of content.shipModels) { const model = effectiveStats(base, {}, content); for (const from of ids) { for (const to of ids) { if (from === to || !checkRoute(model, loc(from), loc(to)).ok) continue; expect(wouldStrand(model, loc(to), undefined, content), `${model.id} ${from}→${to}`).toBe( false, ); } } } }); });