# Domain API Contract: Set Initiative ## Function Signature ``` setInitiative(encounter, combatantId, value) → Success | DomainError ``` ### Parameters | Parameter | Type | Description | |-----------|------|-------------| | encounter | Encounter | Current encounter state | | combatantId | CombatantId | Target combatant to update | | value | integer or undefined | New initiative value, or undefined to clear | ### Success Result | Field | Type | Description | |-------|------|-------------| | encounter | Encounter | New encounter with updated combatant and reordered list | | events | DomainEvent[] | Array containing one `InitiativeSet` event | ### Error Codes | Code | Condition | |------|-----------| | `combatant-not-found` | No combatant with the given id exists | | `invalid-initiative` | Value is defined but not an integer | ### Ordering Contract After a successful call, `encounter.combatants` is sorted such that: 1. All combatants with `initiative !== undefined` come before those with `initiative === undefined` 2. Within the "has initiative" group: sorted descending by initiative value 3. Within the "no initiative" group: original relative order preserved 4. Equal initiative values: original relative order preserved (stable sort) ### Active Turn Contract The combatant who was active before the call remains active after: - `encounter.activeIndex` points to the same combatant (by identity) in the new order - This holds even if the active combatant's own initiative changes ### Invariants Preserved - INV-1: Empty encounters remain valid (0 combatants allowed) - INV-2: `activeIndex` remains in bounds after reorder - INV-3: `roundNumber` is never changed by `setInitiative` ## Use Case Signature ``` setInitiativeUseCase(store, combatantId, value) → DomainEvent[] | DomainError ``` Follows the standard use case pattern: get encounter from store, call domain function, save on success, return events or error.