deadhead-space-freight-tycoon/packages/engine/test/new-places.test.ts

105 lines
3.8 KiB
TypeScript

import { content } from "@deadhead/content";
import { boardPeriodIndex, generateContractBoard } from "@deadhead/sim";
import { describe, expect, it } from "vitest";
import { fullSave } from "../../schema/test/save-fixture";
import { deliveredTank } from "../src/game/state";
import { encodeSave } from "../src/index";
import {
edit,
getState,
putBoard,
readSave,
setCredits,
signUpOwner,
TEST_NOW,
testContract,
useTestApp,
} from "./support";
const testApp = useTestApp();
const NEW_PLACES = ["venus-cloud-city", "io-sulfur-works", "europa-ice-station"];
describe("Venus, Io and Europa in the engine (Step 16.4)", () => {
it("opens a save from before CR-016 with eight places, the new three undiscovered", async () => {
const { app } = testApp();
const before = fullSave();
const { state } = await app.call("importSave", { code: await encodeSave(before) });
expect(state.locations).toHaveLength(8);
for (const id of NEW_PLACES) {
expect(
state.locations.find((l) => l.id === id),
id,
).toEqual({ id, discovered: false });
}
// Nothing else about what the player knows changed: no save data is needed for them.
const after = await readSave(app);
expect(after.saveVersion).toBe(before.saveVersion);
expect(after.discoveredLocations).toEqual(before.discoveredLocations);
// The import stamps the fixture's migrated last decision (CR-024 §3).
expect(after.company).toEqual({ ...before.company, lastManualDecisionAt: TEST_NOW });
});
it("offers first contacts to Venus on Earth boards over time", () => {
const start = boardPeriodIndex(TEST_NOW, content.config);
const toVenus = Array.from({ length: 200 }, (_, k) =>
generateContractBoard(
{
location: content.location("earth")!,
discoveredIds: new Set(["earth", "moon"]),
periodIndex: start + k,
worldSeed: 4242,
// The deal's Clipper and veteran, after Long Haul training.
fleet: [{ modelId: "clipper", skills: { "expensive-cargo": 1, "long-haul": 2 } }],
},
content,
),
)
.flat()
.filter((c) => c.firstContact && c.destinationId === "venus-cloud-city");
expect(toVenus.length).toBeGreaterThan(0);
});
it("discovers Venus on delivery and opens its board with Venus goods", async () => {
const { app, clock } = testApp();
const owner = await signUpOwner(app);
await setCredits(app, 10_000);
// A Clipper with a full tank: Venus is a Clipper leg from Earth (CR-016 §3).
await edit(app, (save) => {
Object.assign(
save.ships.find((s) => s.id === owner.shipId)!,
{
modelId: "clipper",
...deliveredTank("clipper", "earth"),
},
);
// Every leg out of Venus is ~200M km: Long Haul 1, or its board has nothing
// this fleet can take (CR-019).
save.pilots.find((p) => p.id === owner.avatarId)!.skills = { "long-haul": 1 };
});
const contract = testContract({
destinationId: "venus-cloud-city",
firstContact: true,
payout: 40_000,
});
await putBoard(app, [contract]);
const { dispatch } = await app.call("createDispatch", {
kind: "contract",
contractId: contract.id,
shipId: owner.shipId,
pilotId: owner.avatarId,
});
clock.now = dispatch.arrivalAt;
const state = await getState(app);
expect(state.locations.find((l) => l.id === "venus-cloud-city")!.discovered).toBe(true);
expect(state.summaries[0]!.discoveredLocationId).toBe("venus-cloud-city");
const { contracts } = await app.call("getContractBoard", { locationId: "venus-cloud-city" });
expect(contracts.length).toBeGreaterThan(0);
for (const c of contracts) {
expect(c.originId).toBe("venus-cloud-city");
expect(content.good(c.goodId)!.producedAt, c.goodId).toContain("venus-cloud-city");
}
});
});