Files
initiative/specs/003-remove-combatant/data-model.md

70 lines
2.0 KiB
Markdown

# Data Model: Remove Combatant
**Feature**: 003-remove-combatant
**Date**: 2026-03-03
## Existing Entities (no changes)
### Encounter
| Field | Type | Description |
|-------|------|-------------|
| combatants | readonly Combatant[] | Ordered list of participants |
| activeIndex | number | Index of the combatant whose turn it is |
| roundNumber | number | Current round (≥ 1, never changes on removal) |
### Combatant
| Field | Type | Description |
|-------|------|-------------|
| id | CombatantId (branded string) | Unique identifier |
| name | string | Display name |
## New Event Type
### CombatantRemoved
| Field | Type | Description |
|-------|------|-------------|
| type | "CombatantRemoved" (literal) | Event discriminant |
| combatantId | CombatantId | ID of the removed combatant |
| name | string | Name of the removed combatant |
Added to the `DomainEvent` discriminated union alongside `TurnAdvanced`, `RoundAdvanced`, and `CombatantAdded`.
## New Domain Function
### removeCombatant
| Parameter | Type | Description |
|-----------|------|-------------|
| encounter | Encounter | Current encounter state |
| id | CombatantId | ID of combatant to remove |
**Returns**: `RemoveCombatantSuccess | DomainError`
### RemoveCombatantSuccess
| Field | Type | Description |
|-------|------|-------------|
| encounter | Encounter | Updated encounter after removal |
| events | DomainEvent[] | Exactly one CombatantRemoved event |
### DomainError (existing, reused)
Returned with code `"combatant-not-found"` when ID does not match any combatant.
## State Transition Rules
### activeIndex Adjustment
Given removal of combatant at index `removedIdx` with current `activeIndex`:
| Condition | New activeIndex |
|-----------|----------------|
| removedIdx > activeIndex | activeIndex (unchanged) |
| removedIdx < activeIndex | activeIndex - 1 |
| removedIdx === activeIndex, not last in list | activeIndex (next slides in) |
| removedIdx === activeIndex, last in list | 0 (wrap) |
| Only combatant removed (list becomes empty) | 0 |