Move territory from whole-country (ISO_A3) to individual sub-region id granularity (PR 3 of #16): - new server/regions.ts (turf-free): loadRegions (boot), expandTerritory (game creation), migrateTerritoryToRegions (legacy games on db.load), regionNamesFor / regionLabel (LLM prompt), graceful ISO_A3 fallback - game creation expands each preset nation's ISO_A3 list to its sub-region ids; pre-v0.19 saved games migrate transparently on read (idempotent) - LLM contract: territoryChanges gain/lose sub-region ids (one region at a time; gain moves out of the prior owner; lost-without-gainer = unowned); user prompt carries a top-level regions reference table ({id: 'name (parent)'} over the state's territory ids) - WorldMap: choropleth fill per sub-region (countries can split between nations), ownership via properties.regionId through the shared mapFeatureOwner, flash lights exactly the changed features (featuresByRegionIds) - deterministic stub: one region-level move per non-empty round (player annexes the lexicographically-first region of the first other nation) - tests: new server/regions.test.ts (real geo + fallback + seams); map/engine tests re-pinned to region ids; scripts/regions.test.ts stays green Measured full wwii-1939 user prompt (411 regions): ~24.7k chars / ~6.2k tokens — far under the 80k frontier limit, so the full regions table is always sent (no frontier-limited mode needed). Part of #16
21 lines
995 B
TypeScript
21 lines
995 B
TypeScript
// Build the choropleth payload from a GameState: every **sub-region id** in a
|
|
// nation's territory maps to its owning nation plus that nation's stable color
|
|
// (see shared.nationColor). The client merges this onto public/regions.geo.json
|
|
// and calls source.setData(). The map is keyed by whatever ids sit in
|
|
// `nation.territory` — sub-region ids (e.g. `FR-57`) as of v0.19 — so it needs
|
|
// no change to move from country to sub-region granularity; a sub-region in no
|
|
// nation's territory is simply absent (unowned, rendered grey by the map).
|
|
import { nationColor, type RegionMap } from '../shared/protocol';
|
|
import type { GameState } from '../shared/types';
|
|
|
|
export function buildRegionMap(state: GameState): RegionMap {
|
|
const map: RegionMap = {};
|
|
for (const [id, nation] of Object.entries(state.nations)) {
|
|
const color = nationColor(id);
|
|
for (const regionId of nation.territory) {
|
|
map[regionId] = { color, owner: nation.name, ownerId: id };
|
|
}
|
|
}
|
|
return map;
|
|
}
|