feat: #80 + #81 alliances & space program — 13th & 14th abilities (v0.45.0)
CI / build + unit + e2e (pull_request) Successful in 2m20s

#80: TurnResult.alliances — form/break durable mutual-defense pacts (GameState.alliances; pair relation → ally/neutral, an active war overrides).
#81: TurnResult.space — launch/deorbit satellites (GameState.satellites; +1 stability per active satellite per turn).
Both appended last to the ABILITIES registry (entries 13 & 14, after contested); durable in SQLite via the stateFields loop, mirrored to regionStats, stats re-derived. System + user prompt goldens updated; 738 unit tests passing.
This commit is contained in:
2026-10-17 16:54:28 +00:00
parent 0a6c5aef9c
commit 283f9e0306
26 changed files with 1493 additions and 49 deletions
+29 -1
View File
@@ -3,7 +3,12 @@
// (The single `import type` below erases at compile time, so no runtime
// dependency on protocol.ts is introduced — see the GameState.pendingNationOps
// doc comment.)
import type { NationOp, ContestedRegion } from './protocol';
import type {
Alliance,
NationOp,
ContestedRegion,
Satellite,
} from './protocol';
/** A nation's 0–100 status indices. Every value is clamped to 0–100 by the engine. */
export interface NationStats {
@@ -486,6 +491,29 @@ export interface GameState {
* with this defaulted to `[]` (see server/db.ts) — additive, no data wipe.
*/
contested: ContestedRegion[];
/**
* (v0.45.0, #80) Active alliances / mutual-defense treaties (see {@link
* Alliance}): one entry per pact — which two nations are bound and when the
* pact was formed. Declared/ended by a turn's `alliances.form` /
* `alliances.break` ops (a `form` op also sets the pair's relation to
* `ally` unless an active war overrides it; a `break` op sets it back to
* `neutral` unless an active war still binds them). A pair holds at most one
* pact (re-forming is a no-op). Always `[]` on a fresh game; rows saved
* before v0.45 load with this defaulted to `[]` (see server/db.ts) —
* additive, no data wipe.
*/
alliances: Alliance[];
/**
* (v0.45.0, #81) Active satellites (see {@link Satellite}): one entry per
* satellite in orbit — which nation launched it, over which region, of what
* type, and when. Declared/deorbited by a turn's `space.launch` /
* `space.deorbit` ops (a launch requires `by` to own `regionKey`; each
* active satellite grants its owner +1 stability per committed turn,
* mirrored to its regions and re-derived). Always `[]` on a fresh game;
* rows saved before v0.45 load with this defaulted to `[]` (see
* server/db.ts) — additive, no data wipe.
*/
satellites: Satellite[];
}
/**