Ability: Alliances / mutual-defense treaties (durable) #80

Closed
opened 2026-10-17 10:01:19 +02:00 by kamilkrzywda · 0 comments
Owner

Add a new modular LLM ability: alliances — formal mutual-defense pacts between two nations.

Design

TurnResult field alliances (required, default { form: [], break: [] }):

  • AllianceFormOp = { a, b } — two nation refs (id first, then case-insensitive unique name via shared resolveNationRef).
  • AllianceBreakOp = { a, b } — same shape, ends an existing pact.

GameState field alliances: Alliance[] (durable, persists in SQLite):

  • Alliance = { id: al1|al2|..., parties: [a, b] (sorted resolved ids), formedTurn, formedDate } — at most one entry per pair.

Effects (applied in applyTurnResult, in ABILITIES order):

  1. break first: remove matching alliance entry; set a<->b relation to neutral (an active war still overrides via syncWarRelations).
  2. form: create the alliance entry (fresh alN id); set a<->b relation to ally. Self-alliance, duplicates, and breaking a non-existent pact are no-ops.
  3. Because ally is now a formal state behind the relation, wars mutual-defense drag-in already reads the ally relation — no change needed.

Constraints: at most 1-2 per turn, each narrated as a diplomatic event. Unknown/ambiguous/self refs dropped, never thrown.

Payload: always emits alliances (like sea), so the model knows existing pacts.

Durable: yes -> stateFields: [alliances]; db migration automatic (ABILITIES stateFields loop defaults listed fields to [] on legacy rows). New Alliance type in shared/types.ts.

Files to touch

  • shared/protocol.ts — TurnResult.alliances + AllianceFormOp/AllianceBreakOp shapes
  • shared/types.ts — GameState.alliances + Alliance type
  • server/abilities/alliances.ts — new ability module
  • server/abilities/index.ts — import + append to ABILITIES + re-export helpers
  • server/abilities/alliances.test.ts — unit tests
  • Regenerate goldens if system prompt changes (REGEN_GOLDENS=1 npx vitest run server/abilities/registry.test.ts)

Convention

Follow the existing ability pattern exactly (see server/abilities/sea.ts, server/abilities/migration.ts). New abilities are APPENDED last to ABILITIES — never reorder.

Fixes: none pre-filed; this issue is the tracker.

Add a new modular LLM ability: alliances — formal mutual-defense pacts between two nations. ## Design TurnResult field alliances (required, default { form: [], break: [] }): - AllianceFormOp = { a, b } — two nation refs (id first, then case-insensitive unique name via shared resolveNationRef). - AllianceBreakOp = { a, b } — same shape, ends an existing pact. GameState field alliances: Alliance[] (durable, persists in SQLite): - Alliance = { id: al1|al2|..., parties: [a, b] (sorted resolved ids), formedTurn, formedDate } — at most one entry per pair. Effects (applied in applyTurnResult, in ABILITIES order): 1. break first: remove matching alliance entry; set a<->b relation to neutral (an active war still overrides via syncWarRelations). 2. form: create the alliance entry (fresh alN id); set a<->b relation to ally. Self-alliance, duplicates, and breaking a non-existent pact are no-ops. 3. Because ally is now a formal state behind the relation, wars mutual-defense drag-in already reads the ally relation — no change needed. Constraints: at most 1-2 per turn, each narrated as a diplomatic event. Unknown/ambiguous/self refs dropped, never thrown. Payload: always emits alliances (like sea), so the model knows existing pacts. Durable: yes -> stateFields: [alliances]; db migration automatic (ABILITIES stateFields loop defaults listed fields to [] on legacy rows). New Alliance type in shared/types.ts. ## Files to touch - shared/protocol.ts — TurnResult.alliances + AllianceFormOp/AllianceBreakOp shapes - shared/types.ts — GameState.alliances + Alliance type - server/abilities/alliances.ts — new ability module - server/abilities/index.ts — import + append to ABILITIES + re-export helpers - server/abilities/alliances.test.ts — unit tests - Regenerate goldens if system prompt changes (REGEN_GOLDENS=1 npx vitest run server/abilities/registry.test.ts) ## Convention Follow the existing ability pattern exactly (see server/abilities/sea.ts, server/abilities/migration.ts). New abilities are APPENDED last to ABILITIES — never reorder. Fixes: none pre-filed; this issue is the tracker.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OpenCode/History#80