diff --git a/memory-bank/progress.md b/memory-bank/progress.md index 6302af9..70fb1d1 100644 --- a/memory-bank/progress.md +++ b/memory-bank/progress.md @@ -217,3 +217,4 @@ Spec: `memory-bank/change-requests/CR-007-cargo-goods.md` (supplied as "CR-005 / ## Phase 10H — Boards That Feel Fresh (CR-008) Spec: `memory-bank/change-requests/CR-008-fresh-boards.md`. New decisions recorded as plan §0.5.60–0.5.62. +- [x] **Step 10H.1 — Content: pay variance and new goods.** Config `contractPayVariance` 0.15. Five Standard goods (decision 0.5.61): Water Recyclers, Spare Parts (Priority-eligible) and Lunar Base Supplies Earth → Moon; Crew Personal Effects and Recycled Alloys Moon → Earth (locations' goods lists update from the catalog). Earth → Moon now has 6 Standard goods, Moon → Earth 4. All existing tests still pass (tutorial masses unchanged: goods on both routes still hold 5/12/20 t). Test: `goods.test.ts` (route variety, variance is a fraction). diff --git a/packages/content/src/data/config.ts b/packages/content/src/data/config.ts index 4f97239..9c479bf 100644 --- a/packages/content/src/data/config.ts +++ b/packages/content/src/data/config.ts @@ -32,6 +32,8 @@ export const gameConfig: GameConfig = { restGameHours: 10, firstContactChance: 0.1, firstContactPayoutMultiplier: 2, + // Each board contract pays its own market rate, ±15% (CR-008). + contractPayVariance: 0.15, // Priority contracts (CR-007): 15% of eligible goods, ×1.5 pay, a window as // long as a Freighter's trip. priorityChance: 0.15, diff --git a/packages/content/src/data/goods.ts b/packages/content/src/data/goods.ts index 76a66ec..665e13c 100644 --- a/packages/content/src/data/goods.ts +++ b/packages/content/src/data/goods.ts @@ -94,6 +94,58 @@ export const goods: Good[] = [ demandedAt: [EARTH, MARS, CERES], }, + // More early Standard goods (CR-008, decision 0.5.61). + { + id: "water-recyclers", + name: "Water Recyclers", + cargoClassId: "standard", + massTonnes: { min: 3, max: 18 }, + payMultiplier: 1.1, + priorityEligible: false, + producedAt: [EARTH], + demandedAt: [MOON, MARS, CERES], + }, + { + id: "spare-parts", + name: "Spare Parts", + cargoClassId: "standard", + massTonnes: { min: 1, max: 12 }, + payMultiplier: 1.05, + priorityEligible: true, + producedAt: [EARTH, MARS], + demandedAt: [MOON, CERES, JUPITER], + }, + { + id: "lunar-base-supplies", + name: "Lunar Base Supplies", + cargoClassId: "standard", + massTonnes: { min: 2, max: 20 }, + payMultiplier: 1, + priorityEligible: false, + producedAt: [EARTH], + demandedAt: [MOON], + }, + { + id: "crew-effects", + name: "Crew Personal Effects", + cargoClassId: "standard", + massTonnes: { min: 0.5, max: 5 }, + payMultiplier: 1.2, + priorityEligible: false, + producedAt: [MOON, MARS, CERES], + demandedAt: [EARTH], + }, + { + id: "recycled-alloys", + name: "Recycled Alloys", + cargoClassId: "standard", + massTonnes: { min: 5, max: 30 }, + payMultiplier: 0.95, + priorityEligible: false, + producedAt: [MOON], + demandedAt: [EARTH, MARS], + }, + // High-Value: Expensive Cargo skill; tier from the good. { id: "medical-supplies", diff --git a/packages/content/src/schemas.ts b/packages/content/src/schemas.ts index a74ea80..a8a3c04 100644 --- a/packages/content/src/schemas.ts +++ b/packages/content/src/schemas.ts @@ -173,6 +173,8 @@ export const gameConfigSchema = z restGameHours: z.number().positive(), firstContactChance: fraction, firstContactPayoutMultiplier: z.number().positive(), + /** Each board contract's pay rate varies within ± this share of 1 (decision 0.5.60). */ + contractPayVariance: fraction, /** Share of Priority-eligible contracts that become Priority (decision 0.5.56). */ priorityChance: fraction, /** Payout multiplier for a Priority contract. */ diff --git a/packages/content/test/goods.test.ts b/packages/content/test/goods.test.ts index 11944a6..6fecc44 100644 --- a/packages/content/test/goods.test.ts +++ b/packages/content/test/goods.test.ts @@ -56,6 +56,13 @@ describe("goods catalog (CR-007)", () => { expect(standardOn("moon", "earth").length).toBeGreaterThanOrEqual(2); }); + it("offers variety on the early route: ≥ 5 Standard goods Earth→Moon, ≥ 4 back (CR-008)", () => { + expect(standardOn("earth", "moon").length).toBeGreaterThanOrEqual(5); + expect(standardOn("moon", "earth").length).toBeGreaterThanOrEqual(4); + expect(gameConfig.contractPayVariance).toBeGreaterThan(0); + expect(gameConfig.contractPayVariance).toBeLessThan(1); + }); + it("keeps each location's produces and demands in sync with the catalog", () => { for (const location of locations) { expect(location.produces).toEqual(goodsProducedAt(location.id)); diff --git a/packages/content/test/schemas.test.ts b/packages/content/test/schemas.test.ts index df619fa..79e1c5a 100644 --- a/packages/content/test/schemas.test.ts +++ b/packages/content/test/schemas.test.ts @@ -83,6 +83,7 @@ const validGameConfig = { restGameHours: 60, firstContactChance: 0.1, firstContactPayoutMultiplier: 2, + contractPayVariance: 0.15, priorityChance: 0.15, priorityPayoutMultiplier: 1.5, priorityReferenceShipModelId: "freighter",