# Research: Set Initiative ## R-001: Stable Sort for Initiative Ordering **Decision**: Use JavaScript's built-in `Array.prototype.sort()` which is guaranteed stable (ES2019+). Combatants with equal initiative retain their relative order from the original array. **Rationale**: All modern browsers and Node.js engines implement stable sort. No external library needed. The existing codebase already relies on insertion-order preservation in array operations. **Alternatives considered**: - Custom merge sort implementation — unnecessary since native sort is stable. - Separate "sort key" field — over-engineering for the current requirement. ## R-002: Active Turn Preservation Through Reorder **Decision**: After sorting, find the new index of the combatant who was active before the sort (by `CombatantId` identity). Update `activeIndex` to point to that combatant's new position. **Rationale**: The existing `removeCombatant` function already demonstrates the pattern of adjusting `activeIndex` to track a specific combatant through array mutations. This approach is simpler than alternatives since we can look up the active combatant's id before sorting, then find its new index after sorting. **Alternatives considered**: - Store active combatant as `activeCombatantId` instead of `activeIndex` — would require changing the `Encounter` type and all downstream consumers. Too broad for this feature. - Compute a position delta — fragile and error-prone with stable sort edge cases. ## R-003: Initiative as Optional Property on Combatant **Decision**: Add `readonly initiative?: number` to the `Combatant` interface. `undefined` means "not yet set." **Rationale**: Matches the spec requirement for combatants without initiative (FR-005). Using `undefined` (optional property) rather than `null` aligns with TypeScript conventions and the existing codebase style (no `null` usage in domain types). **Alternatives considered**: - Separate `InitiativeMap` keyed by `CombatantId` — breaks co-location, complicates sorting, doesn't match the existing pattern where combatant data lives on the `Combatant` type. - `number | null` — adds a second "empty" representation alongside `undefined`; the codebase has no precedent for `null` in domain types. ## R-004: Clearing Initiative **Decision**: Clearing initiative means setting it to `undefined`. The `setInitiative` function accepts `number | undefined` as the value parameter. When `undefined`, the combatant moves to the end of the order (per FR-003, FR-005). **Rationale**: Reuses the same function for set, change, and clear operations. Keeps the API surface minimal. **Alternatives considered**: - Separate `clearInitiative` function — unnecessary given the value can simply be `undefined`. ## R-005: Integer Validation **Decision**: Validate that the initiative value is a safe integer using `Number.isInteger()`. Reject `NaN`, `Infinity`, and floating-point values. Accept zero and negative integers (per FR-009). **Rationale**: `Number.isInteger()` handles all edge cases: returns false for `NaN`, `Infinity`, `-Infinity`, and non-integer numbers. Allows the full range of safe integers. **Alternatives considered**: - Branded `Initiative` type — adds type complexity without significant safety benefit since validation happens at the domain boundary.