1/**2 * Hand-built v2 TribeView fixtures for script-host tests. Deliberately NOT3 * imported from @tribes/engine (built in parallel) — the shape is pinned by4 * @tribes/protocol alone, so these tests exercise the protocol contract.5 */6import { PROFESSIONS, RESOURCES } from "@tribes/protocol";7import type { Profession, Resource, TribeView } from "@tribes/protocol";89function zeroRecord<K extends string>(keys: readonly K[]): Record<K, number> {10 const out = {} as Record<K, number>;11 for (const k of keys) out[k] = 0;12 return out;13}1415/** Full stores record: zero everywhere except a plausible early-game larder. */16export function makeStores(overrides: Partial<Record<Resource, number>> = {}): Record<Resource, number> {17 return {18 ...zeroRecord(RESOURCES),19 grain: 200,20 fish: 80,21 timber: 120,22 stone: 90,23 ore: 40,24 coin: 80,25 metal: 10,26 bread: 60,27 ale: 50,28 tools: 25,29 weapons: 40,30 ...overrides,31 };32}3334export function makeAllocations(35 overrides: Partial<Record<Profession, number>> = {},36): Record<Profession, number> {37 return { ...zeroRecord(PROFESSIONS), farmer: 200, woodcutter: 80, miner: 40, ...overrides };38}3940/**41 * A realistic single-settlement view: one village with stores and workers,42 * one garrisoned warband, one visible goblin camp, no enemies in sight.43 */44export function makeView(partial: Partial<TribeView> = {}): TribeView {45 const size = 16;46 return {47 tick: 0,48 tribeId: 0,49 mapSize: size,50 terrain: ".".repeat(size * size),51 distant: "?".repeat(size * size),52 claims: ".".repeat(size * size),53 age: 0,54 settlements: [55 {56 id: 1,57 x: 8,58 y: 8,59 tier: 1,60 pop: 1200,61 morale: 800,62 stores: makeStores(),63 storeCap: 2000,64 buildings: { hall: 1, house: 6, farm: 2 },65 buildQueue: [],66 territoryTiles: 40,67 workers: { farmer: 240, woodcutter: 90, miner: 50 },68 capacity: { farmer: 400, woodcutter: 150, miner: 100 },69 herds: 20,70 horses: 4,71 },72 ],73 warbands: [74 {75 id: 30,76 home: 1,77 size: 20,78 kind: "infantry",79 weapons: 20,80 armor: 5,81 veterancy: 100,82 morale: 700,83 x: 8,84 y: 8,85 order: { type: "garrison", target: 1 },86 drilling: 0,87 supply: 40,88 },89 ],90 caravans: [],91 threats: [{ id: 90, kind: "goblin_camp", x: 2, y: 3, strength: 60 }],92 enemySettlements: [],93 enemyWarbands: [],94 offers: [],95 techs: [],96 researching: null,97 knowledge: 0,98 faith: 50,99 craft: { tools: 700, weapons: 200, armor: 100, mill: 800, brew: 100, fodder: 100 },100 decrees: { rations: 1000, slaughter: 0, fodder: 0, ale_ration: 0 },101 allocations: makeAllocations(),102 stances: {},103 aliveTribes: [0, 1],104 events: [],105 ...partial,106 };107}