Manage D&D 5e party-based encounters with multiple heroes vs multiple monsters...
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.
Access seven Python scripts in the scripts/ directory:
All scripts are located at: ~/.claude/skills/tutorial-6/scripts/
Tutorial 6 introduces party-based combat and teaches three key skill-building concepts:
Managing multiple related entities with synchronized state. Track 5-10 combatants simultaneously, each with their own HP, AC, position, and status.
Real-world applications:
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:
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:
For detailed explanations and code examples, see:
references/collection-management.mdreferences/priority-queues.mdreferences/state-synchronization.mdFollow this workflow for interactive party encounters:
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
python3 ~/.claude/skills/tutorial-6/scripts/bestiary.py seed
python3 ~/.claude/skills/tutorial-6/scripts/spells.py seed
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}
},
...
]
}
# 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.
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)
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.
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)
============================================================
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
# 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).
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
}
# 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
# 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
# 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
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...
Tutorial 6 includes ready-to-use encounter files in examples/:
Use these for quick testing or as templates for custom encounters.
You need to start an encounter first:
encounter.py start heroes.json foes.json
Check turn order with encounter.py show. Only the current character can act.
Verify target name exactly matches (case-sensitive). Use encounter.py show to see combatant names.
Cannot target defeated foes. Choose a different target.
~/.claude/data/dnd-dm.dbFor 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 encountersLoad these references as needed when conducting party combat encounters.
Handle these common scenarios:
Once you've completed this tutorial, try extending it:
Tutorial 7: Advanced Combat Mechanics will teach:
You'll build complex boss encounters with mechanics that challenge even experienced players.