Implement the 005-set-initiative feature that adds initiative values to combatants with automatic descending sort and active turn preservation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-04 17:26:41 +01:00
parent a9df826fef
commit fea2bfe39d
17 changed files with 1107 additions and 1 deletions

View File

@@ -0,0 +1,116 @@
# Feature Specification: Set Initiative
**Feature Branch**: `005-set-initiative`
**Created**: 2026-03-04
**Status**: Draft
**Input**: User description: "Allow setting an initiative value for combatants; when initiative is set or changed, the encounter automatically orders combatants so the highest initiative acts first."
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Set Initiative for a Combatant (Priority: P1)
As a game master running an encounter, I want to assign an initiative value to a combatant so that the encounter's turn order reflects each combatant's rolled initiative.
**Why this priority**: Initiative values are the core of this feature — without them, automatic ordering cannot happen.
**Independent Test**: Can be fully tested by setting an initiative value on a combatant and verifying the value is stored and the combatant list is reordered accordingly.
**Acceptance Scenarios**:
1. **Given** an encounter with combatant "Goblin" (no initiative set), **When** the user sets initiative to 15 for "Goblin", **Then** "Goblin" has initiative value 15.
2. **Given** an encounter with combatant "Goblin" (initiative 15), **When** the user changes initiative to 8, **Then** "Goblin" has initiative value 8.
3. **Given** an encounter with combatant "Goblin" (no initiative set), **When** the user attempts to set a non-integer initiative value, **Then** the system rejects the input and the combatant's initiative remains unset.
4. **Given** an encounter with combatant "Goblin" (initiative 15), **When** the user clears "Goblin"'s initiative, **Then** "Goblin"'s initiative is unset and "Goblin" moves to the end of the turn order.
---
### User Story 2 - Automatic Ordering by Initiative (Priority: P1)
As a game master, I want the encounter to automatically sort combatants from highest to lowest initiative so I don't have to manually reorder them.
**Why this priority**: Automatic ordering is the primary value of initiative — it directly determines turn order.
**Independent Test**: Can be fully tested by setting initiative values on multiple combatants and verifying the combatant list is sorted highest-first.
**Acceptance Scenarios**:
1. **Given** combatants A (initiative 20), B (initiative 5), C (initiative 15), **When** all initiatives are set, **Then** the combatant order is A (20), C (15), B (5).
2. **Given** combatants in order A (20), C (15), B (5), **When** B's initiative is changed to 25, **Then** the order becomes B (25), A (20), C (15).
3. **Given** combatants A (initiative 10) and B (initiative 10) with the same value, **Then** their relative order is preserved (stable sort — the combatant who was added or set first stays ahead).
---
### User Story 3 - Combatants Without Initiative (Priority: P2)
As a game master, I want combatants who haven't had their initiative set yet to appear at the end of the turn order so that the encounter remains usable while I'm still entering initiative values.
**Why this priority**: This supports the practical workflow of entering initiatives one at a time as players roll.
**Independent Test**: Can be fully tested by having a mix of combatants with and without initiative values and verifying ordering.
**Acceptance Scenarios**:
1. **Given** combatants A (initiative 15), B (no initiative), C (initiative 10), **Then** the order is A (15), C (10), B (no initiative).
2. **Given** combatants A (no initiative) and B (no initiative), **Then** their relative order is preserved from when they were added.
3. **Given** combatant A (no initiative), **When** initiative is set to 12, **Then** A moves to its correct sorted position among combatants that have initiative values.
---
### User Story 4 - Active Turn Preservation During Reorder (Priority: P2)
As a game master mid-encounter, I want the active combatant's turn to be preserved when initiative changes cause a reorder so that I don't lose track of whose turn it is.
**Why this priority**: Changing initiative mid-encounter (e.g., due to a delayed action or correction) must not disrupt the current turn.
**Independent Test**: Can be fully tested by setting the active combatant, changing another combatant's initiative, and verifying the active turn still points to the same combatant.
**Acceptance Scenarios**:
1. **Given** it is combatant B's turn (activeIndex points to B), **When** combatant A's initiative is changed causing a reorder, **Then** the active turn still points to combatant B.
2. **Given** it is combatant A's turn, **When** combatant A's own initiative is changed causing a reorder, **Then** the active turn still points to combatant A.
---
### Edge Cases
- What happens when a combatant is added without initiative during an ongoing encounter? They appear at the end of the order.
- What happens when all combatants have the same initiative value? Their relative order is preserved (insertion order).
- What happens when initiative is set to zero? Zero is a valid initiative value and is treated normally in sorting.
- What happens when initiative is set to a negative number? Negative values are valid initiative values (some game systems use them).
- What happens when initiative is removed/cleared from a combatant? The combatant moves to the end of the order (treated as unset).
## Requirements *(mandatory)*
### Functional Requirements
- **FR-001**: System MUST allow setting an integer initiative value for any combatant in an encounter.
- **FR-002**: System MUST allow changing an existing initiative value for a combatant.
- **FR-003**: System MUST allow clearing a combatant's initiative value (returning it to unset).
- **FR-004**: System MUST automatically reorder combatants from highest to lowest initiative whenever an initiative value is set, changed, or cleared.
- **FR-005**: System MUST place combatants without an initiative value after all combatants that have initiative values.
- **FR-006**: System MUST use a stable sort so that combatants with equal initiative (or multiple combatants without initiative) retain their relative order.
- **FR-007**: System MUST preserve the active combatant's turn when reordering occurs — the active turn tracks the combatant identity, not the position.
- **FR-008**: System MUST reject non-integer initiative values and return an error.
- **FR-009**: System MUST accept zero and negative integers as valid initiative values.
- **FR-010**: System MUST emit a domain event when a combatant's initiative is set or changed.
### Key Entities
- **Combatant**: Gains an optional initiative property (integer or unset). When set, determines the combatant's position in the encounter's turn order.
- **Encounter**: Combatant ordering becomes initiative-driven. The `activeIndex` must track the active combatant's identity through reorders.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: Users can set initiative for any combatant in a single action.
- **SC-002**: After setting or changing any initiative value, the encounter's combatant order immediately reflects the correct descending initiative sort.
- **SC-003**: The active combatant's turn is never lost or shifted to a different combatant due to an initiative-driven reorder.
- **SC-004**: Combatants without initiative are always displayed after combatants with initiative values.
## Assumptions
- Initiative values are integers (no decimals). This matches common tabletop RPG conventions.
- There is no initiative "roll" or randomization in the domain — the user provides the final initiative value. Dice rolling is outside scope.
- Tiebreaking for equal initiative values uses stable sort (preserves existing relative order). MVP baseline does not include secondary tiebreakers (e.g., Dexterity modifier).
- Clearing initiative is supported to allow corrections (e.g., a combatant hasn't rolled yet).