63 lines
6.1 KiB
JSON
63 lines
6.1 KiB
JSON
{
|
||
"_comment": "ECONOMY TUNING (the knobs, not the data). goods.json is WHAT exists; this file is HOW it prices and stocks. MODEL v2 — ONE WORLD, ONE GOOD (full version in docs/ECONOMY.md §5): every tradeable good has exactly one ORIGIN system (seeded strict assignment, 'origin-assign' pass in Economy.buildEconomy) — the single world whose shop sells it, cheap, in a DAILY BATCH. Every other system's shop does NOT sell it. The catalog's remainder (goods with no origin, the HUB POOL) is resold by stations/capitals at standard price (distance measured to the nearest hub). SELL price = baseValue × distanceBand(hops to origin) × (1 + demandBonus if the class wants it), CAPPED at the shop's own sale price for the good (no shop may ever be a positive same-shop spread). The banded distance term is the DOMINANT factor in profit; planet type (demand) is a secondary modifier. Prices are fixed per (good, location), a pure function of the seed; the only state is the day's remaining batch (save: economyStock). Credits are the go-between — buying spends them, selling earns them, no barter.",
|
||
"shop": {
|
||
"_comment": "Floor size per settlement KIND (model v2). A WORLD's floor is exactly ONE product — its system's signature good (the strict 1:1 origin assignment; see economy.json → 'stock'). Stations and capitals (hubs) resell from the HUB POOL — wider floors (variety), standard price.",
|
||
"minStock": 1,
|
||
"maxStock": 3,
|
||
"stockByKind": {
|
||
"capital": { "min": 12, "max": 16 },
|
||
"deepSpaceStation": { "min": 10, "max": 16 }
|
||
}
|
||
},
|
||
"pricing": {
|
||
"_comment": "Multipliers are dimensionless and multiply baseValue. ORIGIN sale (the good's home world, batch-limited) = baseValue × (1 − originDiscount) × jitter — the only cheap source in the galaxy. HUB resale (station/capital, hub-pool goods only) = baseValue × hubPriceFactor × jitter — standard, never below origin. SELL price (the shop pays you) = baseValue × distanceBand(min(hops to origin, band)) × (1 + demandBonus if the class wants it) × jitter, CAPPED at the shop's own sale price for that good (anti-loop). `distanceBands` are ascending minHops → factor; the band with the largest minHops ≤ hops wins (no cap — the jump tree's diameter ~17 hops is the natural ceiling). The CURRENT factors are the HALVED-MARGIN curve (f′ = 0.25 + f/2 applied to the original ×1.0 / ×1.8 / ×3.2 / ×5.0 / ×7.0): with the origin buy at ×0.5, profit per unit ≈ (factor − 0.5) × base — ≈ 0.25× / 0.65× / 1.35× / 2.25× / 3.25× of base before the demand bonus — so every band nets exactly half the original margin while distance stays the dominant term. `jitter` is a per-good, per-place seeded wobble (±%) so no two shops feel formulated.",
|
||
"originDiscount": 0.50,
|
||
"hubPriceFactor": 1.00,
|
||
"demandBonus": 0.10,
|
||
"distanceBands": [
|
||
{ "minHops": 0, "factor": 0.75 },
|
||
{ "minHops": 2, "factor": 1.15 },
|
||
{ "minHops": 4, "factor": 1.85 },
|
||
{ "minHops": 7, "factor": 2.75 },
|
||
{ "minHops": 11, "factor": 3.75 }
|
||
],
|
||
"jitter": 0.10
|
||
},
|
||
"stock": {
|
||
"_comment": "THE TIME-GATED BATCH — the only stateful part of the economy (and the only bookkeeping a shop needs). Each ORIGIN world's signature good comes to market as a daily batch of `dailyBatch` units; a DAY is `dayMs` of wall-clock time past `epoch`, so the batch regenerates while the player is away (the local buy→sell loop in the origin system — buy at the world, sell to the same-system station — is a BOUNDED pocket change, never infinite money, while long-haul SELLs stay unlimited: the market is a sink). The sell-back side is NEVER stock-limited. Save state per system: { day, left } — tiny, save-clone-safe (js/economy/Stock.js).",
|
||
"dailyBatch": 6,
|
||
"dayMs": 3600000,
|
||
"epoch": "2026-01-01T00:00:00Z"
|
||
},
|
||
"cargo": {
|
||
"_comment": "The hold is a set of fixed BAYS — one good per bay (unitPerGood=1). `capacitySource` is the UNLOCKED-bay count (ship.stats.cargoHold). `maxSlots` is the fixed grid the shop UI always shows (16 slots) — locked bays are just capacity the ship hasn't unlocked yet. You CARRY goods between shops; that's the whole game loop.",
|
||
"capacitySource": "ship.stats.cargoHold",
|
||
"maxSlots": 16,
|
||
"unitPerGood": 1
|
||
},
|
||
"credits": {
|
||
"_comment": "The trade currency (the go-between). Displayed next to the minerals HUD (upper-right). Player starts at 0 (startingCredits). Earning credits = selling goods + mission/quest credit rewards + the bounded local batch loop. Spending = builds, upgrades, and buying goods. Buying spends credits; selling earns them.",
|
||
"startingCredits": 0,
|
||
"display": { "nextTo": "mineralHud", "anchor": "upper-right" },
|
||
"tradingLockedUntilQuest": 3,
|
||
"earning": ["sellGoods", "questRewards", "localBatchLoop", "miningLaserGems (later)"]
|
||
},
|
||
"restock": {
|
||
"_comment": "Prices + FLOOR are NON-persistent (re-derived from the seed — no per-player sold/bought counters, 'you bought out their stock' bookkeeping lives ONLY in the day's batch: stock.dailyBatch/remaining). A shop's stock and prices are a pure function of (seed, place, economy version) — the batch remainder is the one saved number per origin system.",
|
||
"policy": "deterministic-derivation + daily-batch",
|
||
"stockIsPureFunction": true,
|
||
"note": "Reopening a shop re-derives identical floor & prices; the origin's batch regenerates on the day clock."
|
||
},
|
||
"reputation": {
|
||
"_comment": "DEFERRED (decision #3 — wanted, later). Hook: standing with a place's owner faction nudges prices (good standing = better deal). `maxPriceShift` is the max +/- fraction of price. Wired to js/reputation/Reputation.js standingFor(place). OFF for v1.",
|
||
"enabled": false,
|
||
"maxPriceShift": 0.08
|
||
},
|
||
"faction": {
|
||
"_comment": "DEFERRED (decision #3). Hook: some factions may levy a tariff or patron a good class. `tariffRange` is the +/- fraction. `patronGoods` (a future map of factionId -> [goodId]) lets a faction pay premium for its favored goods. Left empty — populate when factions take an economic role.",
|
||
"tariffRange": 0.05,
|
||
"patronGoods": {}
|
||
},
|
||
"version": 2
|
||
}
|