Files
initiative/specs/005-set-initiative/data-model.md

2.6 KiB

Data Model: Set Initiative

Entity Changes

Combatant (modified)

Field Type Required Description
id CombatantId (branded string) Yes Unique identifier
name string Yes Display name (non-empty, trimmed)
initiative integer No Initiative value for turn ordering. Unset means "not yet rolled."

Validation rules:

  • initiative must be an integer when set (no floats, NaN, or Infinity)
  • Zero and negative integers are valid
  • Unset (undefined) is valid — combatant has not rolled initiative yet

Encounter (unchanged structure, new ordering behavior)

Field Type Required Description
combatants readonly Combatant[] Yes Ordered list. Now sorted by initiative descending (unset last, stable sort for ties).
activeIndex number Yes Index of the active combatant. Adjusted to follow the active combatant's identity through reorders.
roundNumber number Yes Current round (≥ 1). Unchanged by initiative operations.

Ordering invariant: After any setInitiative call, combatants is sorted such that:

  1. Combatants with initiative come first, ordered highest to lowest
  2. Combatants without initiative come last
  3. Ties within each group preserve relative insertion order (stable sort)

New Domain Event

InitiativeSet

Emitted when a combatant's initiative value is set, changed, or cleared.

Field Type Description
type "InitiativeSet" Event discriminant
combatantId CombatantId The combatant whose initiative changed
previousValue integer or undefined The initiative value before the change
newValue integer or undefined The initiative value after the change

State Transitions

setInitiative(encounter, combatantId, value)

Input: Current encounter, target combatant id, new initiative value (integer or undefined to clear)

Output: Updated encounter with reordered combatants and adjusted activeIndex, plus events

Error conditions:

  • combatant-not-found: No combatant with the given id exists in the encounter
  • invalid-initiative: Value is not an integer (when defined)

Transition logic:

  1. Find target combatant by id → error if not found
  2. Validate value is integer (when defined) → error if invalid
  3. Record the active combatant's id (for preservation)
  4. Update the target combatant's initiative value
  5. Stable-sort combatants: initiative descending, unset last
  6. Find the active combatant's new index in the sorted array
  7. Return new encounter + InitiativeSet event