import { content } from "@deadhead/content"; import { describe, expect, it } from "vitest"; import { checkRoute } from "../src/index"; /** * CR-015 §4: reach for base ships on the fixed map, a plain yes or no per leg * (decision 0.5.81 as amended). Replaces CR-012's date-sampled table. */ const NAMES: Record = { earth: "Earth", moon: "Moon", mars: "Mars", "ceres-station": "Ceres", "jupiter-cloud-platform": "Jupiter", }; const ids = Object.keys(NAMES); function reaches(modelId: string, fromId: string, toId: string): boolean { const ship = content.shipModel(modelId)!; return checkRoute(ship, content.location(fromId)!, content.location(toId)!, content.config).ok; } /** [model, from, to] for every leg the table says yes or no to. */ type Leg = [string, string, string]; const both = (model: string, a: string, b: string): Leg[] => [ [model, a, b], [model, b, a], ]; const toJupiterFromAnywhere = (model: string): Leg[] => ids .filter((id) => id !== "jupiter-cloud-platform") .map((from) => [model, from, "jupiter-cloud-platform"]); const yes: Leg[] = [ ...both("courier", "earth", "moon"), ...both("lighter", "earth", "moon"), ...both("clipper", "earth", "moon"), ...both("clipper", "earth", "mars"), ["clipper", "moon", "mars"], ["clipper", "mars", "ceres-station"], // The Freighter does everything the Clipper does, plus Earth↔Ceres and Ceres↔Jupiter. ...both("freighter", "earth", "moon"), ...both("freighter", "earth", "mars"), ["freighter", "moon", "mars"], ["freighter", "mars", "ceres-station"], ...both("freighter", "earth", "ceres-station"), ...both("freighter", "ceres-station", "jupiter-cloud-platform"), ...ids.flatMap((from) => ids.filter((to) => to !== from).map((to): Leg => ["bulk-hauler", from, to]), ), ]; const no: Leg[] = [ ["courier", "earth", "mars"], ["courier", "moon", "mars"], ["lighter", "earth", "mars"], ["lighter", "moon", "mars"], ["clipper", "earth", "ceres-station"], ["clipper", "moon", "ceres-station"], ...toJupiterFromAnywhere("clipper"), ["freighter", "earth", "jupiter-cloud-platform"], ["freighter", "moon", "jupiter-cloud-platform"], ["freighter", "mars", "jupiter-cloud-platform"], ]; const label = ([model, from, to]: Leg) => `${model} ${NAMES[from]}→${NAMES[to]}`; describe("reach table (CR-015 §4)", () => { it.each(yes.map((leg) => [label(leg), leg] as const))("yes: %s", (_name, [m, from, to]) => { expect(reaches(m, from, to)).toBe(true); }); it.each(no.map((leg) => [label(leg), leg] as const))("no: %s", (_name, [m, from, to]) => { expect(reaches(m, from, to)).toBe(false); }); });