| name | tutorial-6 |
| description | Manage D&D 5e party-based encounters with multiple heroes vs multiple monsters. Teaches collection management, priority queues (initiative), and state synchronization through interactive JSON-driven combat. Players control characters, AI controls monsters. |
D&D Party Encounter System
Overview
Orchestrate full D&D 5th Edition party combat encounters where 3-5 player characters face off against 2-5+ monsters. Handle initiative-based turn order (priority queue), manage multiple combatant states simultaneously (collection management), and keep all entity states synchronized. This tutorial teaches three critical skill-building concepts through tactical party combat.
Available Scripts
Access seven Python scripts in the scripts/ directory:
- roll_dice.py - Dice rolling (from Tutorial 1)
- character.py - Character management with party_id field (extended from Tutorial 5)
- party.py - NEW: Party creation and roster management
- bestiary.py - Monster database (from Tutorial 5)
- equipment.py - Equipment and AC (from Tutorial 3)
- spells.py - Spell database (from Tutorial 4)
- encounter.py - NEW: Interactive party combat with JSON-driven state
All scripts are located at: ~/.claude/skills/tutorial-6/scripts/
Tutorial 6 Core Concepts
Tutorial 6 introduces party-based combat and teaches three key skill-building concepts:
1. Collection Management
Managing multiple related entities with synchronized state. Track 5-10 combatants simultaneously, each with their own HP, AC, position, and status.
Real-world applications:
- Multi-user systems (chat rooms, collaborative editing)
- Inventory management (tracking stock across warehouses)
- Fleet management (vehicle tracking, delivery routes)
- Task queues (multiple workers processing jobs)
2. Priority Queues
Ordered processing based on dynamic priorities, not arrival time. Initiative system: roll 1d20 + DEX at combat start, act in order from highest to lowest.
Real-world applications:
- Task scheduling (CPU schedulers, job priorities)
- Emergency response (triage systems, priority 1-5)
- Customer support (premium customers served first)
- Network routing (QoS classes for packets)
3. State Synchronization
Keeping multiple interdependent states consistent across operations. When one combatant is defeated, update HP, defeated status, initiative order, and check victory conditions—all synchronized.
Real-world applications:
- Distributed systems (database replication, node synchronization)
- Transaction management (all-or-nothing updates)
- UI state management (React/Vue component state)
- Multiplayer games (player positions, game state broadcast)
For detailed explanations and code examples, see:
references/collection-management.mdreferences/priority-queues.mdreferences/state-synchronization.md
Party Combat Workflow
Follow this workflow for interactive party encounters:
Step 1: Create Party (One-Time Setup)
Create a party and add characters:
# Create party
python3 ~/.claude/skills/tutorial-6/scripts/party.py create heroes "The Heroes" --description "Brave adventurers"
# Add members
python3 ~/.claude/skills/tutorial-6/scripts/party.py add heroes Aria
python3 ~/.claude/skills/tutorial-6/scripts/party.py add heroes Theron
python3 ~/.claude/skills/tutorial-6/scripts/party.py add heroes Bob
# View party
python3 ~/.claude/skills/tutorial-6/scripts/party.py show heroes
Alternative: Characters can be created with party assignment:
python3 scripts/character.py create "Aria" wizard --str 8 --dex 14 --con 12 --int 16 --wis 13 --cha 10 --party heroes
Step 2: Seed Databases (First Time Only)
python3 ~/.claude/skills/tutorial-6/scripts/bestiary.py seed
python3 ~/.claude/skills/tutorial-6/scripts/spells.py seed
Step 3: Export Party to JSON
python3 ~/.claude/skills/tutorial-6/scripts/party.py export heroes > heroes.json
Output (heroes.json):
{
"heroes": [
{
"name": "Aria",
"class": "wizard",
"level": 1,
"hp_max": 8,
"hp_current": 8,
"ac": 12,
"abilities": {"str": 8, "dex": 14, "con": 12, "int": 16, "wis": 13, "cha": 10}
},
...
]
}
Step 4: Build Encounter (Export Foes to JSON)
# Export 3 goblins (auto-numbered: Goblin-1, Goblin-2, Goblin-3)
python3 ~/.claude/skills/tutorial-6/scripts/bestiary.py export Goblin Goblin Goblin > foes.json
# Or use pre-made encounter JSON files
cp ~/.claude/skills/tutorial-6/examples/foes-goblin-ambush.json foes.json
Alternative: Manually create foes.json with custom monsters.
Step 5: Start Encounter
python3 ~/.claude/skills/tutorial-6/scripts/encounter.py start heroes.json foes.json
Output:
============================================================
ENCOUNTER STARTED!
============================================================
Initiative Order:
1. [18] 👤 Theron (d20: 17, DEX: +1)
2. [16] 👹 Goblin-1 (d20: 14, DEX: +2)
3. [14] 👤 Aria (d20: 12, DEX: +2)
4. [12] 👹 Goblin-2 (d20: 10, DEX: +2)
5. [ 9] 👤 Bob (d20: 9, DEX: +0)
6. [ 8] 👹 Goblin-3 (d20: 6, DEX: +2)
============================================================
Round 1
Turn: Theron (Hero)
HP: 13/13
Available actions:
encounter.py attack Theron TARGET
encounter.py show
Targets:
• Goblin-1 (HP: 7/7, AC: 15)
• Goblin-2 (HP: 7/7, AC: 15)
• Goblin-3 (HP: 7/7, AC: 15)
Step 6: Combat Loop (Interactive Turns)
Hero Turn (Player Controls):
# Player decides action
python3 ~/.claude/skills/tutorial-6/scripts/encounter.py attack Theron Goblin-1 longsword
Output:
Theron attacks Goblin-1 with longsword!
Attack roll: 1d20+5 = 19
HIT! Damage: 1d8+3 = 9
Goblin-1: 7 → 0 HP
💀 Goblin-1 has been DEFEATED!
Goblin-2 attacks Theron!
Attack roll: 1d20+4 = 12
MISS! (AC 16)
Goblin-3 attacks Theron!
Attack roll: 1d20+4 = 18
HIT! Damage: 1d6+2 = 5
Theron: 13 → 8 HP
Round 1
Turn: Aria (Hero)
HP: 8/8
Available actions:
encounter.py attack Aria TARGET
encounter.py cast Aria SPELL TARGET
encounter.py show
Targets:
• Goblin-2 (HP: 7/7, AC: 15)
• Goblin-3 (HP: 7/7, AC: 15)
Spellcasting:
python3 ~/.claude/skills/tutorial-6/scripts/encounter.py cast Aria "Fire Bolt" Goblin-2
Monster Turns (AI-Controlled): Monsters act automatically, targeting the hero with lowest HP. No user input required—encounter.py handles monster turns and advances to next player turn.
Step 7: View State Anytime
python3 ~/.claude/skills/tutorial-6/scripts/encounter.py show
Output:
============================================================
ENCOUNTER STATE - Round 2
============================================================
Heroes:
• Aria HP: 5/8
• Theron HP: 8/13
• Bob HP: 10/10
Foes:
• Goblin-1 💀 DEFEATED
• Goblin-2 HP: 0/7, AC: 15
• Goblin-3 HP: 4/7, AC: 15
============================================================
Current turn: Bob (Hero)
============================================================
Step 8: Combat Ends Automatically
When all foes or all heroes are defeated, encounter.py ends combat and outputs results:
Output (Victory):
============================================================
ENCOUNTER ENDED: VICTORY!
============================================================
📊 Combat Summary:
Rounds: 3
Total XP: 150
XP per hero: 50
📄 Results saved to: encounter-results.json
💡 Update characters with:
progression.py award Aria 50
progression.py award Theron 50
progression.py award Bob 50
Step 9: Apply XP Awards
# Update each character
python3 ~/.claude/skills/tutorial-6/scripts/progression.py award Aria 50
python3 ~/.claude/skills/tutorial-6/scripts/progression.py award Theron 50
python3 ~/.claude/skills/tutorial-6/scripts/progression.py award Bob 50
Characters may level up if XP threshold reached (see Tutorial 5 for leveling mechanics).
State Files
encounter.py creates two files during combat:
encounter-state.json - Active combat state (turn-by-turn)
{
"round": 2,
"turn_index": 3,
"combatants": [
{"name": "Theron", "type": "hero", "hp_current": 8, "hp_max": 13, ...},
{"name": "Goblin-1", "type": "foe", "hp_current": 0, "is_defeated": true, ...},
...
],
"combat_log": [...]
}
encounter-results.json - Final results (created when combat ends)
{
"outcome": "victory",
"rounds": 3,
"heroes": [
{"name": "Aria", "hp_final": 5, "hp_max": 8, "xp_earned": 50},
...
],
"foes": [...],
"total_xp": 150,
"xp_per_hero": 50
}
Commands Reference
Party Management (party.py)
# Create party
party.py create PARTY_ID NAME [--description DESC]
# Add member
party.py add PARTY_ID CHARACTER_NAME [--force]
# Remove member
party.py remove CHARACTER_NAME
# Show party
party.py show PARTY_ID
# List all parties
party.py list
# Export to JSON
party.py export PARTY_ID > heroes.json
# Delete party
party.py delete PARTY_ID
Bestiary Management (bestiary.py)
# Export monsters to JSON
bestiary.py export MONSTER [MONSTER ...] > foes.json
# Example: 3 goblins and 1 orc
bestiary.py export Goblin Goblin Goblin Orc > foes.json
# Output: Goblin-1, Goblin-2, Goblin-3, Orc
# Other commands from Tutorial 5
bestiary.py seed
bestiary.py list [--max-cr CR]
bestiary.py show MONSTER_NAME
Encounter Combat (encounter.py)
# Start encounter
encounter.py start HEROES_FILE FOES_FILE
# Character attack
encounter.py attack CHARACTER TARGET [WEAPON]
# Character cast spell
encounter.py cast CHARACTER SPELL TARGET
# Show current state
encounter.py show
Narrative Style
Use the radio drama narrative style for combat descriptions. See references/narrative-guide.md for detailed guidance on creating vivid, cinematic combat narration.
Example narration:
The goblins spring from the shadows! Theron draws his longsword as the creatures shriek
and charge. Aria's hands crackle with arcane energy while Bob raises his holy symbol.
[Initiative rolled]
Theron strikes first! His blade flashes in the dim light, cleaving through Goblin-1's
leather armor. The creature collapses with a final wheeze.
The remaining goblins counterattack! One's scimitar clangs off Theron's shield, but the
other finds a gap in his armor. Blood flows from a shallow cut across his shoulder.
"Burn!" shouts Aria, launching a bolt of flame at Goblin-2...
Example JSON Files
Tutorial 6 includes ready-to-use encounter files in examples/:
- heroes-level1.json - Level 1 starting party (Aria, Theron, Bob)
- foes-goblin-ambush.json - 3 Goblins (CR 1/4 each, easy)
- foes-orc-warband.json - 2 Orcs (CR 1/2 each, medium)
Use these for quick testing or as templates for custom encounters.
Troubleshooting
"No active encounter found"
You need to start an encounter first:
encounter.py start heroes.json foes.json
"Not CHARACTER's turn"
Check turn order with encounter.py show. Only the current character can act.
"Target not found"
Verify target name exactly matches (case-sensitive). Use encounter.py show to see combatant names.
"Monster already defeated"
Cannot target defeated foes. Choose a different target.
Important Notes
- Database location:
~/.claude/data/dnd-dm.db - State persistence: encounter-state.json tracks active combat
- Monster AI: Automatically targets hero with lowest HP
- Physical attacks only: Monster spellcasting saved for later tutorial
- XP split evenly: All heroes get equal share, including defeated ones
- Defeated heroes: Can still earn XP if party wins
Reference Documentation
For detailed information on specific topics, see:
references/collection-management.md- Managing multiple entities, iteration patterns, filtering, bulk updatesreferences/priority-queues.md- Initiative system, dynamic priorities, turn order, real-world applicationsreferences/state-synchronization.md- Keeping state consistent, atomic operations, cascading updatesreferences/narrative-guide.md- Radio drama combat narrative style for party encounters
Load these references as needed when conducting party combat encounters.
Error Handling
Handle these common scenarios:
- No party members: Suggest creating party and adding characters
- No monsters in bestiary: Run seed command
- JSON parse errors: Validate heroes.json and foes.json format
- Encounter already active: Finish or delete encounter-state.json
- Character not found: Check character.py list
Extension Ideas
Once you've completed this tutorial, try extending it:
- AOE Spells - Fireball hits multiple targets, apply damage to all
- Healing Spells - Cure Wounds during combat (not just end)
- Conditions - Stunned, prone, poisoned affecting combat
- Monster Spellcasting - Add spellcasting monsters with AI spell selection
- Terrain/Cover - Modify AC based on cover, difficult terrain slows movement
- Death Saving Throws - Defeated heroes make death saves instead of instant death
- Encounter Templates - Pre-built encounters from encounter_tables.json
What's Next?
Tutorial 7: Advanced Combat Mechanics will teach:
- Reactions - Opportunity attacks, Shield spell, Counterspell
- Legendary Actions - Boss monsters with extra actions
- Monster Spellcasting - AI decides when to cast vs attack
- Conditions and Status Effects - Stunned, paralyzed, poisoned
- Environmental Hazards - Traps, lava, collapsing ceilings
You'll build complex boss encounters with mechanics that challenge even experienced players.