Files
initiative/specs/016-combatant-ac/data-model.md

2.3 KiB

Data Model: Combatant Armor Class Display

Feature: 016-combatant-ac | Date: 2026-03-06

Entity Changes

Combatant (modified)

Field Type Required Validation Notes
id CombatantId (branded string) Yes Non-empty Existing — unchanged
name string Yes Non-empty after trim Existing — unchanged
initiative number | undefined No Integer Existing — unchanged
maxHp number | undefined No Integer >= 1 Existing — unchanged
currentHp number | undefined No Integer >= 0, <= maxHp Existing — unchanged
ac number | undefined No Integer >= 0 NEW — Armor Class

Key Differences from Other Optional Fields

  • Unlike maxHp/currentHp, AC has no paired or derived field — it is a single standalone value.
  • Unlike initiative, AC does not affect combatant sort order.
  • AC validation is >= 0 (not >= 1 like maxHp), because AC 0 is valid in tabletop RPGs.

Domain Events

AcSet (new)

Field Type Description
type "AcSet" Event discriminant
combatantId CombatantId Target combatant
previousAc number | undefined AC before the change
newAc number | undefined AC after the change

State Transitions

setAc(encounter, combatantId, ac)

Input: Encounter, CombatantId, ac: number | undefined

Validation:

  • Combatant must exist in encounter (error: "combatant-not-found")
  • If ac is defined: must be a non-negative integer (error: "invalid-ac")

Behavior:

  • Replaces the combatant's ac field with the new value (or undefined to clear)
  • No side effects on other fields (unlike setHp which initializes currentHp)
  • No reordering (unlike setInitiative which re-sorts)

Output: { encounter: Encounter, events: [AcSet] } or DomainError

Persistence Format

localStorage JSON (unchanged key: "initiative:encounter")

Combatant objects are serialized as plain JSON. The ac field is included when defined, omitted when undefined (standard JSON behavior).

Rehydration validation: typeof entry.ac === "number" && Number.isInteger(entry.ac) && entry.ac >= 0 — invalid values are silently discarded as undefined.