Files
initiative/specs/005-player-characters/spec.md
T
LukasandClaude Opus 5 c029c0ca8d
CI / check (push) Successful in 2m53s
CI / build-image (push) Successful in 20s
Add the whole party to an encounter from the player menu
Starting an encounter meant searching for each party member by name, one
at a time. The management view now carries an "Add party to encounter"
button that puts all of them on the board in one click and closes, so the
initiative list is what you see next.

Members already in the encounter are skipped. Matching is on
playerCharacterId, not on name — otherwise a second click would hand you
"Thorin 2" via the auto-numbering, and renaming a combatant to match a
mini (the reason the rename feature exists) would break the check. Rows
for those members show a muted swords icon, and the button disables once
nothing is left to add, so the greyed-out state has a visible cause.

The whole batch pushes a single undo entry rather than one per combatant:
undoing a four-person party should not take four keystrokes. That is why
the reducer loops internally instead of the UI dispatching N times, and
why addOneFromPlayerCharacter is now split out of the single-add handler
for both paths to share.

Spec 005 gains story PC-8, FR-020..FR-023, SC-010/SC-011 and the edge
cases around partial parties, renamed combatants and orphaned ones. The
existing "multiple copies of the same PC are allowed" edge case is marked
as still true for individual adds — the party button is the deliberate
exception. Key Entities now documents the combatant/PC link the dedup
relies on, which had never been written down.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 17:58:14 +02:00

20 KiB

Feature Specification: Player Character Management

Feature Branch: 005-player-characters Created: 2026-03-12 Status: Draft Input: User description: "Allow users to create and manage Player characters via the bottom bar. Each player character has a name, AC, max HP, a chosen color, and a preset icon. Player characters persist across sessions and are searchable when adding combatants to an encounter. A dedicated management view lets users edit and delete existing player characters."

User Scenarios & Testing (mandatory)

Creating Player Characters

Story PC-1 — Create a new player character (Priority: P1)

A game master opens a "Create Player" modal from the bottom bar and fills in the character's name, AC, max HP, selects a color from a palette, and picks an icon from a preset grid. On saving, the player character is persisted and available for future encounters.

Why this priority: Creating player characters is the foundational action — nothing else in this feature works without it.

Independent Test: Can be fully tested by creating a player character and verifying it appears in the saved player list.

Acceptance Scenarios:

  1. Given the bottom bar is visible, When the user clicks the "Create Player" icon button, Then a modal opens with fields for Name, AC, Max HP, a color palette, and an icon selection grid.

  2. Given the create player modal is open, When the user fills in Name "Aragorn", AC 16, Max HP 120, selects the color green, and selects the shield icon, Then clicking save creates a player character with those attributes and closes the modal.

  3. Given no player characters exist, When the user creates their first player character, Then it is persisted and appears in the player character list.

  4. Given the create player modal is open, When the user submits with an empty name, Then a validation error is shown and the player character is not created.

  5. Given the create player modal is open, When the user submits with a whitespace-only name, Then a validation error is shown and the player character is not created.

  6. Given the create player modal is open, When the user clicks cancel or closes the modal, Then no player character is created and any entered data is discarded.


Player Character Persistence

Story PC-2 — Player characters survive page reload (Priority: P1)

Player characters are long-lived entities that persist across browser sessions. Unlike encounter combatants which belong to a single encounter, player characters represent recurring party members that the GM reuses across many encounters.

Why this priority: Without persistence, users would need to recreate their party every session, defeating the purpose.

Independent Test: Can be tested by creating a player character, reloading the page, and verifying it still exists.

Acceptance Scenarios:

  1. Given the user has created player characters, When the page is reloaded, Then all player characters are restored with their name, AC, max HP, color, and icon intact.

  2. Given saved player character data is corrupt or malformed, When the page loads, Then the application starts with an empty player character list without crashing.

  3. Given no saved player character data exists, When the page loads, Then the application starts with an empty player character list.


Adding Player Characters to Encounters

Story PC-3 — Search and add player characters as combatants (Priority: P1)

When adding combatants to an encounter, the GM can search for their saved player characters by name. Selecting a player character adds it as a combatant with its saved stats (AC, max HP) pre-filled, along with its color and icon for visual identification.

Why this priority: This is the core value proposition — reusing pre-configured characters instead of re-entering stats every encounter.

Independent Test: Can be tested by creating a player character, then adding it to an encounter via the combatant search.

Acceptance Scenarios:

  1. Given player characters "Aragorn" and "Legolas" exist, When the user types "Ara" in the combatant search field, Then "Aragorn" appears in the search results alongside bestiary creatures.

  2. Given player character "Aragorn" (AC 16, Max HP 120) exists, When the user selects "Aragorn" from search results, Then a combatant is added to the encounter with name "Aragorn", AC 16, max HP 120, current HP 120, and the player character's color and icon.

  3. Given player character "Gandalf" exists, When the user adds "Gandalf" to two separate encounters (or the same encounter twice), Then each combatant is an independent copy — modifying one combatant's HP does not affect the other or the saved player character.

  4. Given no player characters exist, When the user searches in the combatant search field, Then only bestiary creatures appear in results (no empty "Players" section is shown).


Story PC-8 — Add the whole party to an encounter (Priority: P1)

At the start of a session the GM wants the entire party in the initiative tracker. Instead of searching for each character by name, they open the player character management view and add every saved character to the encounter in one action.

Why this priority: Putting the party on the board is how nearly every encounter starts. Doing it one character at a time is the main friction in the setup flow.

Independent Test: Can be tested by creating several player characters, triggering the add-party action, and verifying every character is present as a combatant.

Acceptance Scenarios:

  1. Given player characters "Aragorn", "Legolas", and "Gimli" exist and none are in the encounter, When the user triggers the add-party action from the management view, Then a combatant is created for each of them, with the same stats, color, and icon an individual add would produce.

  2. Given "Aragorn" is already a combatant in the encounter and "Legolas" is not, When the user triggers the add-party action, Then only "Legolas" is added — "Aragorn" gets no second copy and is not renamed.

  3. Given the user has just added the party, When the user undoes once, Then every combatant created by that action is removed together.

  4. Given every saved player character is already in the encounter, When the user opens the management view, Then the add-party action is unavailable and communicates why.

  5. Given some player characters are already in the encounter, When the user opens the management view, Then those characters are marked as already present and the add-party action remains available for the rest.

  6. Given no player characters exist, When the user opens the management view, Then the empty state is shown without an add-party action.


Displaying Player Characters in Encounters

Story PC-4 — Visual distinction for player character combatants (Priority: P2)

Combatants originating from player characters display their chosen color and icon next to their name in the combatant row, making it easy to visually distinguish PCs from monsters at a glance.

Why this priority: Color and icon display enhances usability but the feature is functional without it.

Independent Test: Can be tested by adding a player character to an encounter and verifying the color and icon render in the combatant row.

Acceptance Scenarios:

  1. Given a combatant was added from a player character with color green and the shield icon, When the combatant row is rendered, Then the player character's icon is displayed next to the name and the color is applied as a visual accent (e.g., colored border, background tint, or icon tint).

  2. Given a combatant was added from the bestiary (not a player character), When the combatant row is rendered, Then no player character icon or color accent is shown.


Managing Player Characters

Story PC-5 — View all saved player characters (Priority: P2)

The GM can access a dedicated management view to see all their saved player characters at a glance, with each character's name, AC, max HP, color, and icon displayed.

Why this priority: Management view is needed for editing and deleting, but basic create/add flow works without it.

Independent Test: Can be tested by creating several player characters and opening the management view to verify all are listed.

Acceptance Scenarios:

  1. Given player characters exist, When the user opens the player character management view, Then all saved player characters are listed showing their name, AC, max HP, color, and icon.

  2. Given no player characters exist, When the user opens the management view, Then an empty state message is shown encouraging the user to create their first player character.


Story PC-6 — Edit an existing player character (Priority: P2)

The GM realizes a player character's stats have changed (e.g., level up) or wants to fix a typo. They open the management view and edit the character's attributes.

Why this priority: Editing is important for ongoing campaigns but the feature delivers value without it initially.

Independent Test: Can be tested by editing a player character's name and stats and verifying the changes persist.

Acceptance Scenarios:

  1. Given player character "Aragorn" exists, When the user edits "Aragorn" to change the name to "Strider" and AC to 18, Then the changes are saved and reflected in the player character list.

  2. Given a player character is being edited, When the user submits with an empty name, Then a validation error is shown and the changes are not saved.

  3. Given a player character is being edited, When the user cancels the edit, Then the original values are preserved.

  4. Given a player character was previously added to an encounter as a combatant, When the player character is edited, Then existing combatants in the current encounter are not affected (they are independent copies).


Story PC-7 — Delete a player character (Priority: P2)

The GM no longer needs a player character and wants to remove it from their saved list.

Why this priority: Deletion keeps the list manageable but is not needed for core functionality.

Independent Test: Can be tested by deleting a player character and verifying it no longer appears in the list or search results.

Acceptance Scenarios:

  1. Given player character "Boromir" exists, When the user deletes "Boromir" with confirmation, Then the player character is removed from the saved list.

  2. Given player character "Boromir" was previously added to the current encounter as a combatant, When the player character is deleted, Then the combatant in the encounter is not affected (it is an independent copy).

  3. Given the delete action is initiated, When the user is asked to confirm, Then the confirmation follows the existing ConfirmButton two-step pattern (as defined in spec 001).


Edge Cases

  • Duplicate player character names: Permitted. Player characters are identified by a unique internal ID, not by name.
  • Adding the same player character to an encounter multiple times: Each addition creates an independent combatant copy. Multiple copies of the same PC in one encounter are allowed. The add-party action is the deliberate exception — it skips characters that are already present (see PC-8).
  • Adding the party when part of it is already present: Only the missing characters are added. Membership is determined by player character identity, not by name.
  • Adding the party after a PC-derived combatant was renamed: The combatant is still recognised as that player character, so the party add does not produce a duplicate.
  • Adding the party after the source player character was deleted: The orphaned combatant matches no saved character; it is left alone and the remaining party members add normally.
  • Editing a player character while it is also a combatant in the active encounter: The active combatant is not affected; only future additions use the updated stats.
  • Deleting a player character while it is a combatant in the active encounter: The combatant remains in the encounter unchanged.
  • Very long player character names: The UI should truncate or ellipsize names that exceed the available space.
  • Browser storage quota exceeded: Player character persistence silently fails; the current in-memory session continues.
  • Corrupt player character data on load: The application discards corrupt data and starts with an empty player character list.
  • Color/icon rendering on different screen sizes: Color and icon must remain visible and distinguishable at all supported viewport sizes.
  • Search ranking: When searching, player characters should appear in a distinct group (e.g., "Players" section) above or alongside bestiary results to make them easy to find.

Requirements (mandatory)

Functional Requirements

FR-001 — Create: Modal via bottom bar

The system MUST provide an icon button in the bottom bar that opens a "Create Player" modal.

FR-002 — Create: Required fields

The create modal MUST include fields for Name (text), AC (number), and Max HP (number).

FR-003 — Create: Color selection

The create modal MUST include a color palette allowing the user to select one color from a predefined set of distinguishable colors.

FR-004 — Create: Icon selection

The create modal MUST include a grid of ~10-20 preset icons (e.g., sword, shield, skull, heart, wand) from which the user selects one.

FR-005 — Create: Name validation

Creating a player character MUST reject empty or whitespace-only names, showing a validation error.

FR-006 — Create: Unique identity

Each player character MUST be assigned a unique internal identifier on creation.

FR-007 — Persistence: Cross-session storage

Player characters MUST be persisted to browser storage and restored on page load.

FR-008 — Persistence: Independent from encounter storage

Player character storage MUST be separate from encounter storage — clearing an encounter does not affect saved player characters.

FR-009 — Persistence: Graceful degradation

The system MUST NOT crash when player character data is missing, corrupt, or storage is unavailable. It MUST fall back to an empty player character list.

Player characters MUST appear in the combatant search results when the user searches for combatants to add to an encounter. Matching is by name substring.

FR-011 — Search: Distinct grouping

Player character results MUST be visually distinguishable from bestiary creature results in the search dropdown.

FR-012 — Add to encounter: Pre-filled stats

When a player character is added to an encounter as a combatant, the combatant MUST be created with the player character's name, AC, max HP, and current HP set to max HP.

FR-013 — Add to encounter: Color and icon association

When a combatant is created from a player character, the combatant MUST carry the player character's color and icon for display purposes.

FR-014 — Add to encounter: Independent copy

Combatants created from player characters MUST be independent copies. Changes to the combatant's stats during an encounter do not modify the saved player character, and vice versa.

FR-015 — Display: Color and icon in combatant row

Combatant rows for player-character-originating combatants MUST display the chosen icon and color accent.

FR-016 — Management: View all player characters

The system MUST provide a view listing all saved player characters with their name, AC, max HP, color, and icon.

FR-017 — Management: Edit player character

The system MUST allow editing a player character's name, AC, max HP, color, and icon. Edits MUST be persisted.

FR-018 — Management: Delete player character

The system MUST allow deleting a player character with two-step confirmation (ConfirmButton pattern from spec 001).

FR-019 — Management: Delete does not affect active combatants

Deleting a player character MUST NOT remove or modify any combatants currently in an encounter.

FR-020 — Add to encounter: Add the whole party

The management view MUST provide an action that adds all saved player characters to the current encounter in a single interaction.

FR-021 — Add to encounter: Party add skips present members

Adding the party MUST skip player characters that already have a combatant in the current encounter. Membership MUST be determined by player character identity, not by combatant name.

FR-022 — Add to encounter: Party add is one undo step

Adding the party MUST be reversible as a single undo step, regardless of how many combatants it created.

FR-023 — Management: Indicate encounter membership

The management view MUST indicate which saved player characters are already in the current encounter, and MUST disable the add-party action when none remain to be added.

Key Entities

  • PlayerCharacter: A persistent, reusable character template with a unique PlayerCharacterId (branded string), required name, ac (number), maxHp (number), color (string from predefined set), icon (string identifier from preset icon set), and optional level (integer 1-20, added by spec 008 for encounter difficulty calculation).
  • PlayerCharacterStore (port): Interface for loading, saving, and deleting player characters. Implemented as a browser storage adapter.
  • Combatant → PlayerCharacter link: A combatant created from a player character retains that character's PlayerCharacterId. The link drives display (color, icon) and encounter-membership detection (FR-021). It does not make the combatant a live view of the character — the combatant remains an independent copy (FR-014).

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: Users can create a player character with name, AC, max HP, color, and icon in under 30 seconds.
  • SC-002: Player characters persist across page reloads with all attributes intact.
  • SC-003: Player characters appear in combatant search results and can be added to an encounter in a single selection.
  • SC-004: Combatants created from player characters display their color and icon in the initiative tracker.
  • SC-005: Users can edit any attribute of a saved player character and see the change persisted immediately.
  • SC-006: Deleting a player character requires two deliberate user interactions (ConfirmButton pattern) and does not affect active encounter combatants.
  • SC-007: All player character domain operations (create, edit, delete) are pure functions with no I/O, consistent with the project's deterministic domain core.
  • SC-008: The player character domain module has zero imports from application, adapter, or UI layers.
  • SC-009: Corrupt or missing player character data never causes a crash — the application gracefully falls back to an empty player character list.
  • SC-010: Users can put their entire party into an encounter with one interaction, and reverse it with one undo — no matter how large the party is.
  • SC-011: Repeating the add-party action never produces duplicate or auto-renamed copies of a player character already in the encounter.

Assumptions

  • Player character IDs are generated by the caller (application layer), keeping domain functions pure.
  • The predefined color palette contains 8-12 visually distinct colors suitable for both light and dark backgrounds.
  • The preset icon set uses Lucide React icons already available in the project, requiring no additional icon dependencies.
  • Player characters are stored in a separate localStorage key from encounter data.
  • Name validation trims whitespace; a name that is empty after trimming is invalid.
  • Duplicate player character names are permitted — characters are distinguished by their unique ID.
  • MVP baseline does not include importing/exporting player characters.
  • MVP baseline does not include player-character-specific fields beyond name, AC, max HP, color, and icon (e.g., no class, level, or ability scores).
  • MVP baseline does not include reordering player characters in the management view.
  • The management view is accessible from the bottom bar or a dedicated UI affordance, separate from the encounter view.
  • When a player character is added to an encounter, a snapshot of its current stats is copied — future edits to the player character do not retroactively update existing combatants.