deadhead-space-freight-tycoon/packages/sim/test/first-contact-fit.test.ts

73 lines
2.5 KiB
TypeScript

import { content } from "@deadhead/content";
import { describe, expect, it } from "vitest";
import {
boardPeriodIndex,
generateContractBoard,
validateDispatch,
type FleetMember,
} from "../src/index";
/** Fuel enough for any leg in these tests (decision 0.5.94), bought at 10 cr/fu. */
const PLENTY = { fuelFu: 10_000, avgPrice: 10 };
const earth = content.location("earth")!;
const start = Date.parse(content.config.epoch.realStart);
const firstPeriod = boardPeriodIndex(start, content.config);
/** The deal's Clipper with the veteran after Long Haul 2: Mars is in reach at the start. */
const clipper: FleetMember = {
modelId: "clipper",
skills: { "expensive-cargo": 1, "long-haul": 2 },
};
const board = (periodIndex: number, discovered: string[], fleet: FleetMember[]) =>
generateContractBoard(
{ location: earth, discoveredIds: new Set(discovered), periodIndex, worldSeed: 4242, fleet },
content,
);
/** The fleet's Clipper can take it: range, landing, mass, skills, no stranding. */
const clipperCanFly = (contract: ReturnType<typeof board>[number]) =>
validateDispatch(
{
ship: { id: "s", modelId: "clipper", locationId: "earth", inFlight: false, tank: PLENTY },
pilot: {
id: "p",
isAvatar: false,
assignedShipId: "s",
inFlight: false,
skills: clipper.skills,
restEndsAt: null,
},
contract,
tutorial: false,
now: contract.offeredAt,
discoveredIds: new Set(["earth", "moon"]),
},
content,
).ok;
describe("a first contact the fleet can fly (decision 0.5.85)", () => {
it("offers one on every board while a reachable place is undiscovered", () => {
for (let k = 0; k < 24; k++) {
const contracts = board(firstPeriod + k, ["earth", "moon"], [clipper]);
const flyable = contracts.filter((c) => c.firstContact && clipperCanFly(c));
expect(flyable.length, `period ${k}`).toBeGreaterThanOrEqual(1);
// Mars and Venus Cloud City are both a Clipper leg from Earth (CR-016).
expect(flyable.every((c) => ["mars", "venus-cloud-city"].includes(c.destinationId))).toBe(
true,
);
}
});
it("stops once the reachable places are discovered", () => {
for (let k = 0; k < 24; k++) {
const contracts = board(
firstPeriod + k,
["earth", "moon", "mars", "venus-cloud-city"],
[clipper],
);
expect(contracts.filter((c) => c.firstContact && clipperCanFly(c))).toEqual([]);
}
});
});