diff --git a/apps/server/test/contract-dispatch.test.ts b/apps/server/test/contract-dispatch.test.ts index 69ebc8f..1fc9c39 100644 --- a/apps/server/test/contract-dispatch.test.ts +++ b/apps/server/test/contract-dispatch.test.ts @@ -157,6 +157,10 @@ describe("contract dispatch", () => { const o = await owner(); const contract = testContract({ cargoTypeId: "heavy", + goodId: "machine-parts", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 2, requiredSkill: { skillId: "heavy-cargo", level: 2 }, }); diff --git a/apps/server/test/game.ts b/apps/server/test/game.ts index 456242d..805c73c 100644 --- a/apps/server/test/game.ts +++ b/apps/server/test/game.ts @@ -100,6 +100,10 @@ export function testContract(overrides: Partial = {}): Contract { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 2000, diff --git a/apps/web/src/screens/MapScreen.tsx b/apps/web/src/screens/MapScreen.tsx index aee560c..4a4decc 100644 --- a/apps/web/src/screens/MapScreen.tsx +++ b/apps/web/src/screens/MapScreen.tsx @@ -117,8 +117,8 @@ function LocationPanel({ locationId, onClose }: { locationId: string; onClose: ( : `${formatMillionKm(distanceAt("earth", location.id, now))} from Earth`}

- Produces {location.cargoClassMix.produces.map(cargoName).join(", ") || "nothing"} · demands{" "} - {location.cargoClassMix.demands.map(cargoName).join(", ") || "nothing"} + Produces {location.cargoClassMix.produces.map(cargoName).join(", ") || "nothing"} · + demands {location.cargoClassMix.demands.map(cargoName).join(", ") || "nothing"}

{hasBay ? "Your HQ is here." : "No HQ here."} diff --git a/apps/web/test/board-refresh.test.tsx b/apps/web/test/board-refresh.test.tsx index aee828f..4007759 100644 --- a/apps/web/test/board-refresh.test.tsx +++ b/apps/web/test/board-refresh.test.tsx @@ -45,6 +45,10 @@ const heavyJob: Contract = { originId: "earth", destinationId: "moon", cargoTypeId: "heavy", + goodId: "machine-parts", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 300, payout: 9000, diff --git a/apps/web/test/dispatch-duty.test.tsx b/apps/web/test/dispatch-duty.test.tsx index a35323d..95af04d 100644 --- a/apps/web/test/dispatch-duty.test.tsx +++ b/apps/web/test/dispatch-duty.test.tsx @@ -44,6 +44,10 @@ const moonJob: Contract = { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 900, diff --git a/apps/web/test/dispatch-problems.test.tsx b/apps/web/test/dispatch-problems.test.tsx index 52a4c04..2bff797 100644 --- a/apps/web/test/dispatch-problems.test.tsx +++ b/apps/web/test/dispatch-problems.test.tsx @@ -17,6 +17,10 @@ const job = ( originId: "earth", destinationId: "moon", cargoTypeId: skill ? "high-value" : "standard", + goodId: skill ? "medical-supplies" : "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: skill?.level ?? 0, massTonnes, payout: 1000, diff --git a/apps/web/test/dispatch-sheet.test.tsx b/apps/web/test/dispatch-sheet.test.tsx index d2c3e65..6f644b6 100644 --- a/apps/web/test/dispatch-sheet.test.tsx +++ b/apps/web/test/dispatch-sheet.test.tsx @@ -52,6 +52,10 @@ const marsJob: Contract = { originId: "earth", destinationId: "mars", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 15, payout: 500_000, diff --git a/apps/web/test/location-boards.test.tsx b/apps/web/test/location-boards.test.tsx index 7d08820..8a618a1 100644 --- a/apps/web/test/location-boards.test.tsx +++ b/apps/web/test/location-boards.test.tsx @@ -12,6 +12,10 @@ const contract = (overrides: Partial): Contract => ({ originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 50, payout: 2000, @@ -30,6 +34,10 @@ const boards: Record = { id: "e2", destinationId: "mars", cargoTypeId: "heavy", + goodId: "machine-parts", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 2, requiredSkill: { skillId: "heavy-cargo", level: 2 }, requiredLongHaulLevel: 1, diff --git a/apps/web/test/render.tsx b/apps/web/test/render.tsx index 22500de..c7f9095 100644 --- a/apps/web/test/render.tsx +++ b/apps/web/test/render.tsx @@ -102,6 +102,10 @@ export function sampleTutorialBoard( originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes, payout, diff --git a/apps/web/test/weight-warning.test.tsx b/apps/web/test/weight-warning.test.tsx index dc3fa91..3b22310 100644 --- a/apps/web/test/weight-warning.test.tsx +++ b/apps/web/test/weight-warning.test.tsx @@ -11,6 +11,10 @@ const contract = (id: string, massTonnes: number): Contract => ({ originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes, payout: 1000 + massTonnes, diff --git a/memory-bank/progress.md b/memory-bank/progress.md index bbdbb04..814bbba 100644 --- a/memory-bank/progress.md +++ b/memory-bank/progress.md @@ -203,3 +203,4 @@ Spec: `memory-bank/change-requests/CR-006-boards-that-fit.md`. New decisions rec Spec: `memory-bank/change-requests/CR-007-cargo-goods.md` (supplied as "CR-005 / Phase 10E"; renumbered, see its implementation notes). New decisions recorded as plan §0.5.54–0.5.59. Baseline class mix before the change (1,000 Earth boards, all discovered): Standard 76.79 %, High-Value 23.21 %. - [x] **Step 10G.1 — Content: goods catalog.** `goodSchema` (id, name, `cargoClassId`, `massTonnes {min,max}`, `payMultiplier`, optional `tier` 1–5, `priorityEligible`, optional `priorityName`, `producedAt`, `demandedAt`; min ≤ max refinement) and `data/goods.ts` with all 29 goods from CR-007 §3, plus `goodsProducedAt`/`goodsDemandedAt`. Locations: `produces`/`demands` now derive from the catalog (good ids); the old class lists are kept as `cargoClassMix` (decision 0.5.57) and the sim's class selection and the UI's produces/demands now read them, so nothing visible changes yet; `shippers` added (≥ 1 each). Config: `priorityChance` 0.15, `priorityPayoutMultiplier` 1.5, `priorityReferenceShipModelId` "freighter", `priorityWindowFactor` 1. Bundle: `goods`, `good(id)`. Tests: `goods.test.ts` (schema, references, tiers by class, Standard good everywhere, ≥ 2 Standard goods each way Earth↔Moon, location lists in sync, Priority config), schema tests for Good and the new fields. +- [x] **Step 10G.2 — Sim: contracts carry goods.** `Contract` gains `goodId`, `shipper`, `priority`, `deliveryWindowGameHours` (null unless Priority); the API `contractSchema` mirrors them now (the schema package's type-parity test requires it), so test fixtures across packages gained a good of their class. `contractPayout` = class base × good `payMultiplier` × tierMultiplier^tier × mass × distance × first-contact × Priority bonus. `buildContract` takes a good (the class comes from it) plus shipper and Priority fields; `tierFor` (0.5.55: Standard 0, High-Value/Dangerous the good's tier, Heavy the random roll or up to a fit pilot's level); `routeGoods` (0.5.54 fallback chain). Interim choice until 10G.3: the first route good in catalog order, the origin's first shipper, never Priority; fit jobs only use goods whose tier the pilot meets. `SimContent` gains `goods`. Tests: `contract.test.ts` (tiers from goods, Heavy 1–5, ×2 pay multiplier doubles payout, Priority = bonus × normal). diff --git a/packages/schema/src/entities.ts b/packages/schema/src/entities.ts index fe20412..08a6c1d 100644 --- a/packages/schema/src/entities.ts +++ b/packages/schema/src/entities.ts @@ -85,6 +85,13 @@ export const contractSchema = z.object({ originId: idSchema, destinationId: idSchema, cargoTypeId: idSchema, + /** The named good (CR-007). */ + goodId: idSchema, + /** Flavor: the shipping company (decision 0.5.58). */ + shipper: z.string().min(1), + priority: z.boolean(), + /** Priority only: the longest allowed trip in game hours (decision 0.5.56). */ + deliveryWindowGameHours: z.number().positive().nullable(), tier: z.number().int().min(0), massTonnes: z.number().positive(), payout: credits, diff --git a/packages/schema/test/schemas.test.ts b/packages/schema/test/schemas.test.ts index 18350e2..052ee61 100644 --- a/packages/schema/test/schemas.test.ts +++ b/packages/schema/test/schemas.test.ts @@ -80,6 +80,10 @@ const contract = { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 12, payout: 480, diff --git a/packages/sim/src/board.ts b/packages/sim/src/board.ts index dfb8a64..adef65b 100644 --- a/packages/sim/src/board.ts +++ b/packages/sim/src/board.ts @@ -1,6 +1,7 @@ import type { CargoType, GameConfig, + Good, Location, ScriptedTutorialContract, ShipModel, @@ -17,6 +18,7 @@ import { createRng, deriveSeed, type Rng, type Seed } from "./rng"; export interface SimContent { locations: readonly Location[]; cargoTypes: readonly CargoType[]; + goods: readonly Good[]; skills: readonly Skill[]; shipModels: readonly ShipModel[]; scriptedTutorialContracts: readonly ScriptedTutorialContract[]; @@ -138,54 +140,85 @@ function fitJob( (c.requiredSkillId === null || skillLevel(skills, c.requiredSkillId) >= 1), ); const cargoType = skilled.length > 0 ? rng.pick(skilled) : standardCargo(content); - const tier = - cargoType.requiredSkillId === null - ? 0 - : rng.int(1, skillLevel(skills, cargoType.requiredSkillId)); + // Only goods this pilot may carry: a good's own tier must not exceed their skill. + const good = routeGoods(cargoType, origin, destination, content, (g) => { + const skillId = cargoClassOf(g, content).requiredSkillId; + return skillId === null || skillLevel(skills, skillId) >= (g.tier ?? 1); + })[0]!; + const skillId = cargoClassOf(good, content).requiredSkillId; + const tier = tierFor(rng, good, content, skillId ? skillLevel(skills, skillId) : undefined); const massTonnes = rng.int(band.min, Math.min(band.max, model.cargoCapacityTonnes)); - return { destination, cargoType, tier, massTonnes }; + return { destination, good, tier, massTonnes }; } return null; } -/** Builds one contract from a chosen route, cargo, tier and mass. */ +export function cargoClassOf(good: Good, content: SimContent): CargoType { + const cargoType = content.cargoTypes.find((c) => c.id === good.cargoClassId); + if (!cargoType) throw new Error(`Unknown cargo class ${good.cargoClassId}`); + return cargoType; +} + +/** + * A contract's tier (decision 0.5.55): Standard is 0, High-Value and Dangerous + * take the good's tier, and Heavy rolls 1 to `maxTier` (the skill's maximum, + * or a pilot's level for a fit job). + */ +export function tierFor(rng: Rng, good: Good, content: SimContent, maxTier?: number): number { + const cargoType = cargoClassOf(good, content); + if (cargoType.requiredSkillId === null) return 0; + if (good.tier !== undefined) return good.tier; + return maxTier === undefined ? pickTier(rng, cargoType, content) : rng.int(1, maxTier); +} + +/** Builds one contract from a chosen route, good, tier and mass. */ export function buildContract( args: { id: string; origin: Location; destination: Location; - cargoType: CargoType; + good: Good; tier: number; massTonnes: number; firstContact: boolean; periodIndex: number; + shipper: string; + priority: boolean; + deliveryWindowGameHours: number | null; }, content: SimContent, ): Contract { const { config } = content; + const cargoType = cargoClassOf(args.good, content); const offeredAt = args.periodIndex * boardPeriodMs(config); const distance = routeDistance(args.origin, args.destination, realToGame(offeredAt, config)); return { id: args.id, originId: args.origin.id, destinationId: args.destination.id, - cargoTypeId: args.cargoType.id, + cargoTypeId: cargoType.id, + goodId: args.good.id, + shipper: args.shipper, + priority: args.priority, + deliveryWindowGameHours: args.priority ? args.deliveryWindowGameHours : null, tier: args.tier, massTonnes: args.massTonnes, payout: contractPayout( { - cargoType: args.cargoType, + cargoType, + payMultiplier: args.good.payMultiplier, tier: args.tier, massTonnes: args.massTonnes, distanceMillionKm: distance, firstContact: args.firstContact, + priority: args.priority, }, config, ), requiredSkill: - args.cargoType.requiredSkillId === null + cargoType.requiredSkillId === null ? null - : { skillId: args.cargoType.requiredSkillId, level: args.tier }, + : { skillId: cargoType.requiredSkillId, level: args.tier }, requiredLongHaulLevel: requiredLongHaulLevel(distance, config), offeredAt, expiresAt: offeredAt + boardPeriodMs(config), @@ -193,6 +226,33 @@ export function buildContract( }; } +/** + * The goods a contract of this class can carry on this route (decision 0.5.54): + * that class's goods made at the origin and wanted at the destination; else + * Standard goods on the route; else any Standard good made at the origin. + * `allow` filters out goods a crew can't take (fit jobs). + */ +export function routeGoods( + cargoType: CargoType, + origin: Location, + destination: Location, + content: SimContent, + allow: (good: Good) => boolean = () => true, +): Good[] { + const made = content.goods.filter((g) => g.producedAt.includes(origin.id) && allow(g)); + const onRoute = made.filter((g) => g.demandedAt.includes(destination.id)); + const ofClass = onRoute.filter((g) => g.cargoClassId === cargoType.id); + if (ofClass.length > 0) return ofClass; + const standardId = standardCargo(content).id; + const standardOnRoute = onRoute.filter((g) => g.cargoClassId === standardId); + if (standardOnRoute.length > 0) return standardOnRoute; + const anyStandard = content.goods.filter( + (g) => g.producedAt.includes(origin.id) && g.cargoClassId === standardId, + ); + if (anyStandard.length === 0) throw new Error(`${origin.id} makes no Standard good`); + return anyStandard; +} + function pickCargo(rng: Rng, origin: Location, destination: Location, content: SimContent) { const matching = content.cargoTypes.filter( (c) => @@ -239,7 +299,19 @@ export function generateContractBoard(input: BoardInput, content: SimContent): C const fit = kind === "fit" ? fitJob(rng, band, crews, origin, discovered, offeredAt, content) : null; if (fit) { - return buildContract({ id, origin, ...fit, firstContact: false, periodIndex }, content); + return buildContract( + { + id, + origin, + ...fit, + firstContact: false, + periodIndex, + shipper: origin.shippers[0]!, + priority: false, + deliveryWindowGameHours: null, + }, + content, + ); } const guaranteed = kind !== "open"; const plain = guaranteed && discovered.length > 0; @@ -249,16 +321,20 @@ export function generateContractBoard(input: BoardInput, content: SimContent): C (discovered.length === 0 || rng.next() < config.firstContactChance); const destination = rng.pick(firstContact ? undiscovered : discovered); const cargoType = plain ? standardCargo(content) : pickCargo(rng, origin, destination, content); + const good = routeGoods(cargoType, origin, destination, content)[0]!; return buildContract( { id, origin, destination, - cargoType, - tier: pickTier(rng, cargoType, content), + good, + tier: tierFor(rng, good, content), massTonnes: rng.int(band.min, band.max), firstContact, periodIndex, + shipper: origin.shippers[0]!, + priority: false, + deliveryWindowGameHours: null, }, content, ); diff --git a/packages/sim/src/contract.ts b/packages/sim/src/contract.ts index f8c316e..03e946c 100644 --- a/packages/sim/src/contract.ts +++ b/packages/sim/src/contract.ts @@ -5,8 +5,20 @@ export interface Contract { id: string; originId: string; destinationId: string; + /** The cargo class (decision 0.5.6). */ cargoTypeId: string; - /** 0 for Standard; 1–5 otherwise, and equal to the required cargo-skill level (decision 0.5.6). */ + /** The named good (CR-007, decision 0.5.54); its class is `cargoTypeId`. */ + goodId: string; + /** Flavor: the company shipping it, from the origin's list (decision 0.5.58). */ + shipper: string; + /** A Priority contract must arrive within its delivery window (decision 0.5.56). */ + priority: boolean; + /** Priority only: the longest trip allowed, in game hours; null otherwise. */ + deliveryWindowGameHours: number | null; + /** + * 0 for Standard; 1–5 otherwise, and equal to the required cargo-skill level + * (decision 0.5.6). High-Value and Dangerous take it from the good (0.5.55). + */ tier: number; massTonnes: number; /** Credits, fixed at offer time (decision 0.5.11). */ @@ -24,24 +36,30 @@ export interface Contract { export interface PayoutInput { cargoType: CargoType; + /** The good's pay multiplier (CR-007). */ + payMultiplier: number; tier: number; massTonnes: number; /** Route distance at offer time. */ distanceMillionKm: number; firstContact: boolean; + priority: boolean; } /** - * Payout in whole credits: base pay per tonne per million km × tierMultiplier^tier - * × mass × distance, × the first-contact multiplier when flagged. + * Payout in whole credits: class base pay per tonne per million km × the good's + * pay multiplier × tierMultiplier^tier × mass × distance, × the first-contact + * multiplier and the Priority bonus when flagged (CR-007). */ export function contractPayout(input: PayoutInput, config: GameConfig): number { - const { cargoType, tier, massTonnes, distanceMillionKm, firstContact } = input; + const { cargoType, payMultiplier, tier, massTonnes, distanceMillionKm, firstContact } = input; const pay = cargoType.basePayPerTonnePerMillionKm * + payMultiplier * cargoType.tierPayMultiplier ** tier * massTonnes * distanceMillionKm * - (firstContact ? config.firstContactPayoutMultiplier : 1); + (firstContact ? config.firstContactPayoutMultiplier : 1) * + (input.priority ? config.priorityPayoutMultiplier : 1); return Math.round(pay); } diff --git a/packages/sim/src/tutorial.ts b/packages/sim/src/tutorial.ts index 0292813..dac6835 100644 --- a/packages/sim/src/tutorial.ts +++ b/packages/sim/src/tutorial.ts @@ -1,5 +1,5 @@ import type { Location, ShipModel } from "@deadhead/content"; -import { buildContract, standardCargo, type SimContent } from "./board"; +import { buildContract, routeGoods, standardCargo, type SimContent } from "./board"; import type { Contract } from "./contract"; /** The tutorial loaner: the content's company ship (decision 0.5.29). */ @@ -48,16 +48,20 @@ export function generateTutorialBoard(input: TutorialBoardInput, content: SimCon ? content.cargoTypes.find((c) => c.id === special.cargoTypeId) : standardCargo(content); if (!cargoType) throw new Error(`Unknown cargo ${special?.cargoTypeId}`); + const good = routeGoods(cargoType, origin, destination, content)[0]!; const contract = buildContract( { id: `tutorial:${loanerLocationId}:${run}:${periodIndex}:${i}`, origin, destination, - cargoType, + good, tier: 0, massTonnes, firstContact: false, periodIndex, + shipper: origin.shippers[0]!, + priority: false, + deliveryWindowGameHours: null, }, content, ); diff --git a/packages/sim/test/contract.test.ts b/packages/sim/test/contract.test.ts index 93f61fa..97d4250 100644 --- a/packages/sim/test/contract.test.ts +++ b/packages/sim/test/contract.test.ts @@ -1,6 +1,7 @@ import { content } from "@deadhead/content"; import { describe, expect, it } from "vitest"; -import { contractPayout, type PayoutInput } from "../src/index"; +import { tierFor } from "../src/board"; +import { contractPayout, createRng, type PayoutInput } from "../src/index"; const config = content.config; const standard = content.cargoType("standard")!; @@ -8,10 +9,12 @@ const dangerous = content.cargoType("dangerous")!; const base: PayoutInput = { cargoType: standard, + payMultiplier: 1, tier: 0, massTonnes: 10, distanceMillionKm: 100, firstContact: false, + priority: false, }; describe("contract payout", () => { @@ -50,3 +53,35 @@ describe("contract payout", () => { ); }); }); + +describe("contracts carry goods (CR-007)", () => { + const rng = createRng(42); + + it("takes the tier of a High-Value or Dangerous contract from its good", () => { + for (const good of content.goods.filter( + (g) => g.cargoClassId === "high-value" || g.cargoClassId === "dangerous", + )) { + expect(tierFor(rng, good, content)).toBe(good.tier); + } + }); + + it("keeps the random 1–5 tier for Heavy goods and tier 0 for Standard", () => { + const parts = content.good("machine-parts")!; + const seen = new Set(); + for (let i = 0; i < 200; i++) seen.add(tierFor(rng, parts, content)); + expect([...seen].sort()).toEqual([1, 2, 3, 4, 5]); + expect(tierFor(rng, content.good("mail")!, content)).toBe(0); + }); + + it("doubles the payout when the good's pay multiplier doubles", () => { + expect(contractPayout({ ...base, payMultiplier: 2 }, config)).toBe( + 2 * contractPayout(base, config), + ); + }); + + it("pays a Priority contract exactly the bonus times an identical normal one", () => { + expect(contractPayout({ ...base, priority: true }, config)).toBe( + contractPayout(base, config) * config.priorityPayoutMultiplier, + ); + }); +}); diff --git a/packages/sim/test/dispatch.test.ts b/packages/sim/test/dispatch.test.ts index b2ee54f..47c2250 100644 --- a/packages/sim/test/dispatch.test.ts +++ b/packages/sim/test/dispatch.test.ts @@ -27,6 +27,10 @@ const contract: Contract = { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 2000, @@ -99,6 +103,10 @@ describe("dispatch validation", () => { const heavy = { ...contract, cargoTypeId: "heavy", + goodId: "machine-parts", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 1, requiredSkill: { skillId: "heavy-cargo", level: 1 }, }; diff --git a/packages/sim/test/duty-dispatch.test.ts b/packages/sim/test/duty-dispatch.test.ts index 0058c2a..a0e2b46 100644 --- a/packages/sim/test/duty-dispatch.test.ts +++ b/packages/sim/test/duty-dispatch.test.ts @@ -24,6 +24,10 @@ const contract: Contract = { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 2000, diff --git a/packages/sim/test/loan.test.ts b/packages/sim/test/loan.test.ts index d5c1625..1a26b78 100644 --- a/packages/sim/test/loan.test.ts +++ b/packages/sim/test/loan.test.ts @@ -44,6 +44,10 @@ describe("resolution with a loan", () => { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 2000, diff --git a/packages/sim/test/pilot.test.ts b/packages/sim/test/pilot.test.ts index a8d440f..799af89 100644 --- a/packages/sim/test/pilot.test.ts +++ b/packages/sim/test/pilot.test.ts @@ -6,6 +6,10 @@ const shortStandard: Contract = { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 1000, @@ -18,6 +22,10 @@ const shortStandard: Contract = { const heavyTier2: Contract = { ...shortStandard, cargoTypeId: "heavy", + goodId: "machine-parts", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 2, requiredSkill: { skillId: "heavy-cargo", level: 2 }, }; diff --git a/packages/sim/test/record.test.ts b/packages/sim/test/record.test.ts index d5092ba..bebca8b 100644 --- a/packages/sim/test/record.test.ts +++ b/packages/sim/test/record.test.ts @@ -14,6 +14,10 @@ const contract: Contract = { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 2000, diff --git a/packages/sim/test/resolution.test.ts b/packages/sim/test/resolution.test.ts index 78ade26..5fe8583 100644 --- a/packages/sim/test/resolution.test.ts +++ b/packages/sim/test/resolution.test.ts @@ -16,6 +16,10 @@ const contract: Contract = { originId: "earth", destinationId: "moon", cargoTypeId: "standard", + goodId: "consumer-goods", + shipper: "Pacific Orbital Logistics", + priority: false, + deliveryWindowGameHours: null, tier: 0, massTonnes: 10, payout: 2000, diff --git a/packages/sim/test/tutorial.test.ts b/packages/sim/test/tutorial.test.ts index b710684..ca95d29 100644 --- a/packages/sim/test/tutorial.test.ts +++ b/packages/sim/test/tutorial.test.ts @@ -29,15 +29,17 @@ function distanceOf(contract: Contract): number { ); } -/** The normal (non-tutorial) payout for the same Standard cargo and route. */ +/** The normal (non-tutorial) payout for the same Standard good and route. */ function normalPayout(contract: Contract): number { return contractPayout( { cargoType: content.cargoType("standard")!, + payMultiplier: content.good(contract.goodId)!.payMultiplier, tier: 0, massTonnes: contract.massTonnes, distanceMillionKm: distanceOf(contract), firstContact: false, + priority: false, }, config, );