demo-dnd: Product Brief¶
Status: approved (W-003).
Target app: apps/demo-dnd. Refs: concept §8.
1. Vision¶
Player leads a fixed party (Fighter, Rogue, Wizard) through one turn-based, D&D-style skirmish on a grid against a pack of monsters, moving and acting with each hero and watching initiative, dice, crits, and poison play out in a 2–5 minute fight.
2. Audience and purpose¶
- Audience: developers learning ECS / flecs concepts on koota. The demo must still be a fun 2–5 minute fight on its own.
- Teaches: traits and tags, pairs with data (
HasEffect(Poisoned)with a duration), observers,Added/Removedchange detection, systems ordered in turn phases (ecs-schedule), monster templates as prefabs (ecs-prefab), and live world inspection (ecs-devtools).
3. Core loop¶
- User sees the grid, the initiative order, and whose turn it is.
- On a hero's turn, player moves the hero on the grid, then picks an action and a target in reach.
- The action resolves with visible dice (advantage, crits); damage and Poisoned apply.
- Monsters take their turns automatically, closing in on the weakest hero.
- Poisoned ticks down at turn boundaries; defeated combatants leave the order.
- Repeat until one side is defeated, then restart.
4. ECS showcase¶
| flecs concept | Shown by | Package |
|---|---|---|
| Entities, components, tags | Combatants with Health, ArmorClass, Initiative, Position; Hero / Monster / Defeated tags (DND-F01, DND-F02) |
koota |
| Queries | Monster AI finds the living hero with the lowest HP (DND-F04) | koota |
| Pipeline phases, ordered systems, manual stepping | Turn pipeline: start of turn → move → act → resolve → end of turn, stepped per turn (DND-F02, DND-F05) | ecs-schedule |
Prefabs and IsA |
Monsters spawned from templates (DND-F01); template variants (DND-F09) | ecs-prefab |
| Pairs with data | HasEffect(Poisoned) with remaining duration (DND-F05) |
koota |
| Observers | Combat log entries and defeat handling on trait add/remove (DND-F02, DND-F03) | koota |
Added / Removed queries |
UI highlights new effects and newly defeated combatants (DND-F02, DND-F05) | koota |
| Explorer-style inspection | Live entity/trait panel (DND-F10) | ecs-devtools |
| Serialization | Save and resume a fight (DND-F08) | ecs-serialize |
5. Backlog¶
| ID | Feature | Milestone | Work |
|---|---|---|---|
| DND-F01 | User sees Fighter, Rogue, and Wizard vs. 3–4 template monsters (e.g. Goblin, Orc) on a grid, and player can move the active hero up to its speed | M1 | |
| DND-F02 | User sees the initiative order and the active combatant; turns advance round after round, defeated combatants drop out, and the user sees victory or defeat and can restart | M1 | |
| DND-F03 | Player can make the active hero attack a monster in reach (melee: adjacent; Wizard: ranged) and sees the d20 + bonus vs. AC roll, advantage, crits, and damage in a combat log; attacks against a Poisoned target roll with advantage | M1 | |
| DND-F04 | Monsters take their turn automatically: move toward and attack the living hero with the lowest HP | M1 | |
| DND-F05 | Player can use the Rogue's poison ability to apply Poisoned (damage per turn for N turns) and sees it tick and expire; while Poisoned, attacks against the target have advantage | M1 | |
| – | |||
| DND-F07 | Player can control the whole fight from the keyboard with on-screen key hints | M2 | |
| DND-F08 | Player can save a fight in progress and resume it after reload | M2 | |
| DND-F09 | User meets monster variants that build on a base template (e.g. Goblin Boss from Goblin) | M2 | |
| DND-F10 | User can open a devtools panel listing entities, traits, and effects live | M1 | |
| DND-F11 | Player can pick the party and the encounter from a list in content data | M2 | |
| – | |||
| DND-F13 | Player can cast spells with multiple effects and areas | later | |
| DND-F14 | Player can fight with terrain, cover, and opportunity attacks on the grid | later |
M1 order: DND-F01, DND-F02, DND-F03, DND-F04, DND-F05, DND-F10.
Notes:
- Every core-loop action in M1, including grid movement, must already be keyboard-reachable (demo rule); DND-F07 adds hints and polish.
- Dependency/risk (DND-F10): needs an ecs-devtools v0 implementation. Only its spec (W-006) is on the board, and concept §6 has ecs-devtools build on ecs-serialize. DND-F10 is last in M1 so the core loop is playable without it; the v0 scope should be an entity/trait list that does not need ecs-serialize.
6. Non-functional targets¶
- Performance: under 50 combatant entities on a grid of at most 12×12; UI stays at 60 FPS with the devtools panel open; a full turn resolves in under one frame of logic.
- Accessibility: all actions, including grid movement and targeting, keyboard-reachable; WCAG AA contrast; status, dice, advantage, and crit results shown as text, not color alone; grid cells have text labels for occupants.
- Persistence: M1 none. M2 saves the full encounter (combatants, HP, effects with remaining duration, initiative position, round) via
ecs-serialize.
7. Path to a real app¶
- Rules data (stats, speed, reach, abilities, effects, monster templates, map size) lives in
src/content/and can be swapped for SRD-style data files. - Dice and RNG behind one seam, so fights can be seeded and replayed.
- Turn pipeline as
ecs-schedulephases, so new phases (reactions, movement) slot in without rewriting systems. - Monster AI behind one decision function per monster (M1: lowest-HP hero), replaceable later.
- World state serializable, leaving room for networked or async multiplayer.
8. Out of scope¶
- Terrain, cover, line of sight, and opportunity attacks in M1 (see DND-F14).
- Party selection and character creation, leveling, inventory, and campaigns. The M1 party is fixed.
- Status effects other than Poisoned in M1.
- Full D&D 5e rules fidelity; only d20 + bonus vs. armor class, with advantage and crits (natural 20 hits and doubles damage dice; natural 1 misses).
- 3D rendering (R3F); plain 2D UI only.
- Multiplayer and networking.