Files
Battle-for-Tismo/docs/simple_economy/01-decoupling-hard-economy.md
T
adrien d5305da449 Gave the world a simple economy: one pool per nation and a global market
The simple economy is now the default and the old simulation is frozen as the hard model, selectable per game. A nation keeps one resource pool available in every region, fed by public production works rather than private per-region stores, and construction and training begin at once, paced by the region's spare power instead of gathering materials over days.

Money is euro only: a per-inhabitant daily tax funds a treasury spent in a global market, where buy and sell lots trade against the world stock and move its price. The hard economy keeps its per-nation currencies, central banks and exchange rates.

Simple games skip the price-settling warmup and economic migration; the snapshot carries the economy model, the market and the pool figures the client draws. Added the matching test suites and the design briefs under docs/simple_economy.
2026-09-25 14:58:49 +02:00

4.2 KiB

01 — Decouple the economy model (freeze "hard economy")

Depends on: nothing. Do this first; every other prompt assumes it.

Goal

Introduce an explicit, per-game economy model so the current model can be kept untouched as the hard economy while a new simple economy becomes the default. Nothing about the current simulation should change when the hard model is selected.

Current behaviour

  • There is one implicit model. GameState.configure(civilisations, seed) in shared/game_state.js builds the world and the rich resource economy.
  • The server passes setup through GameServer.configureGame(setup) (server/game_server.js), which also runs the warmup. setups are assembled in server/server.js from CLI flags.
  • testing is the only mode flag and is shipped in the snapshot.

Target behaviour

  • Add economyModel to GameState, defaulting to "simple", accepting "simple" or "hard". Reject/coerce anything else to "simple".
  • GameState.configure(civs, seed, options) takes { economyModel } (keep the existing two-argument call working; options optional). Set this.economyModel before building the world, because world/scenario seeding differs per model.
  • Ship economyModel in the snapshot alongside testing so joiners know which UI to render (shared/game_state/serialization.js).
  • Server CLI: add --economy simple|hard (env ECONOMY), default simple, parsed in server/server.js and forwarded in the configureGame setup object. Keep --warmup working for hard; see 04-warmup.md.
  • Add a model-specific override mechanism. Recommended: a new shared/game_state/simple_economy.js exporting simpleEconomyMethods. In configure(), when the model is simple, Object.assign(this, simpleEconomyMethods) so the instance shadows the prototype methods it needs to replace. The hard model needs no override module — it is the existing mixins unchanged.
    • Instance-level assignment is safe because the model is fixed for the life of a game and the client does not run a live GameState.
    • Name each override after the method it replaces so the diff is obvious.
  • Add a helper isSimpleEconomy() (or this.economyModel === "simple") and use it at every branch rather than scattering string comparisons.

Files

  • shared/game_state.js — constructor field, configure() options, override assignment, isSimpleEconomy().
  • shared/game_state/simple_economy.js — new, the override mixin (empty at first; later prompts add methods).
  • shared/game_state/serialization.js — ship economyModel.
  • server/server.js — CLI flag and help text.
  • server/game_server.js — pass economyModel into configure, keep the warmup path intact.
  • shared/data/economy.js (or a new shared/data/simple_economy.js) — constants for the simple model, namespaced so they cannot collide with ECONOMY, MONEY and RESOURCE_*.
  • client/js/game_screen.js / client/js/net.js — store the flag from the snapshot for the view (no visible change yet).
  • tests/economy_model_test.js — new.

Acceptance criteria

  • new GameState() defaults to "simple".
  • A game configured with { economyModel: "hard" } behaves byte-for-byte like today: the existing suites (resources_test.js, money_test.js, industry_test.js, construction_site_test.js, taxes_test.js, ...) still pass unchanged for the hard model.
  • A game configured with { economyModel: "simple" } is constructible and runs its daily ticks without throwing, even before the other modules land. To keep it runnable, the initial simpleEconomyMethods may be empty.
  • The snapshot carries economyModel; the server default is "simple".
  • node server/server.js --economy hard still runs the hard game.

Notes / decisions

  • Decide whether hard is selectable only by CLI/admin or also by a lobby option. Default recommendation: CLI/launch option only.
  • Do not rename existing symbols (resources.js, money.js, taxes.js) — they are the hard model. "Hard economy" is a label, not a new directory.
  • If a branch is needed inside an existing method, prefer an early if (this.isSimpleEconomy()) return this._simpleX(...) delegating to the override module over editing the hard path in place.