59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
import type { Location, ShipModel } from "@deadhead/content";
|
|
import { buildContract, standardCargo, type SimContent } from "./board";
|
|
import type { Contract } from "./contract";
|
|
import { createRng, deriveSeed, type Seed } from "./rng";
|
|
|
|
/** The tutorial loaner is the company's Courier. */
|
|
export function loanerModel(content: SimContent): ShipModel {
|
|
const courier = content.shipModels.find((s) => s.archetype === "courier");
|
|
if (!courier) throw new Error("Content has no Courier ship model");
|
|
return courier;
|
|
}
|
|
|
|
export type TutorialLocationId = "earth" | "moon";
|
|
|
|
export interface TutorialBoardInput {
|
|
/** Where the loaner currently is; contracts start here (decision 0.5.3). */
|
|
loanerLocationId: TutorialLocationId;
|
|
periodIndex: number;
|
|
worldSeed: Seed;
|
|
}
|
|
|
|
function location(id: string, content: SimContent): Location {
|
|
const found = content.locations.find((l) => l.id === id);
|
|
if (!found) throw new Error(`Unknown location ${id}`);
|
|
return found;
|
|
}
|
|
|
|
/**
|
|
* The tutorial "company board": Earth↔Moon only, Standard cargo sized to fit
|
|
* the loaner, starting at the loaner's location. Each payout is the tutorial
|
|
* share of the equivalent normal payout, rounded to whole credits.
|
|
*/
|
|
export function generateTutorialBoard(input: TutorialBoardInput, content: SimContent): Contract[] {
|
|
const { loanerLocationId, periodIndex, worldSeed } = input;
|
|
const { config } = content;
|
|
const origin = location(loanerLocationId, content);
|
|
const destination = location(loanerLocationId === "earth" ? "moon" : "earth", content);
|
|
const cargoType = standardCargo(content);
|
|
const maxMass = Math.min(config.contractMassTonnes.max, loanerModel(content).cargoCapacityTonnes);
|
|
const rng = createRng(deriveSeed(worldSeed, `tutorial:${loanerLocationId}:${periodIndex}`));
|
|
|
|
return Array.from({ length: config.tutorialBoardSize }, (_, i) => {
|
|
const contract = buildContract(
|
|
{
|
|
id: `tutorial:${loanerLocationId}:${periodIndex}:${i}`,
|
|
origin,
|
|
destination,
|
|
cargoType,
|
|
tier: 0,
|
|
massTonnes: rng.int(config.contractMassTonnes.min, maxMass),
|
|
firstContact: false,
|
|
periodIndex,
|
|
},
|
|
content,
|
|
);
|
|
return { ...contract, payout: Math.round(contract.payout * config.tutorialPayoutShare) };
|
|
});
|
|
}
|