# dnd-character-stats > Manage D&D character stats with ability scores, HP, and persistence - Author: Joe C - Repository: JoeCotellese/dnd-dm-skill - Version: 20251113162100 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/JoeCotellese/dnd-dm-skill - Web: https://mule.run/skillshub/@@JoeCotellese/dnd-dm-skill~dnd-character-stats:20251113162100 --- # Tutorial 2: Character Stats Learn about persistent state management with SQLite by building a D&D character sheet system! ## Overview This tutorial teaches you how to manage persistent data using SQLite databases, build on previous tutorials, and create interactive workflows with user feedback loops. You'll build a character management system that stores ability scores, calculates modifiers, and tracks HP. ## What You'll Learn (Skill Building) - **Database persistence**: Using SQLite for structured data storage - **CRUD operations**: Create, Read, Update, Delete characters - **Interactive workflows**: Roll → assign → confirm/adjust → save pattern - **Script composition**: Building on Tutorial 1's dice roller - **Calculated properties**: Deriving modifiers, HP, proficiency from base stats - **Data validation**: Ensuring character data integrity ## What You'll Build (D&D Feature) A character management system that: - Rolls ability scores (4d6 drop lowest, 6 times) - Auto-assigns scores based on class priorities - Allows interactive adjustment before saving - Persists characters in SQLite database - Displays formatted character sheets with modifiers - Updates stats (leveling up, ability score improvements) - Tracks current/max HP ## Prerequisites - Claude Code installed and configured - Completed Tutorial 1 (or understand dice rolling basics) - Basic familiarity with D&D ability scores ## Installation 1. Copy the entire tutorial directory to your skills folder: ```bash cp -r tutorial-2-character-stats ~/.claude/skills/dnd-character-stats ``` 2. The skill will be automatically available (Claude reads SKILL.md from the directory) 3. The database will be automatically created at `~/.claude/data/dnd-dm.db` on first use ## Usage Examples ### Creating a Character with Rolled Stats ``` You: Create a fighter named Thorin with rolled stats Skill: Rolling ability scores (4d6 drop lowest, 6 times)... Rolled: [15, 14, 13, 12, 11, 9] Auto-assigned for Fighter: | Ability | Score | Modifier | |---------|-------|----------| | STR | 15 | +2 | | CON | 14 | +2 | | DEX | 13 | +1 | | WIS | 12 | +1 | | CHA | 11 | +0 | | INT | 9 | -1 | Accept? (y/n) You: n Skill: What would you like to change? You: swap DEX and CON Skill: Updated: | Ability | Score | Modifier | |---------|-------|----------| | STR | 15 | +2 | | CON | 13 | +1 | | DEX | 14 | +2 | | WIS | 12 | +1 | | CHA | 11 | +0 | | INT | 9 | -1 | Accept? (y/n) You: y Skill: ✓ Created Thorin (fighter, Level 1) Thorin (fighter, Level 1) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STR: 15 (+2) DEX: 14 (+2) CON: 13 (+1) INT: 9 (-1) WIS: 12 (+1) CHA: 11 (+0) HP: 11/11 Proficiency: +2 ``` ### Creating with Manual Stats ``` You: Create wizard Elara with STR 8, DEX 14, CON 12, INT 16, WIS 13, CHA 10 Skill: ✓ Created Elara (wizard, Level 1) [Shows character sheet] ``` ### Viewing Characters ``` You: Show Thorin's stats Skill: Thorin (fighter, Level 1) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ STR: 15 (+2) ... ``` ``` You: List all my characters Skill: Characters: • Thorin (fighter, Level 1) • Elara (wizard, Level 1) • Grimm (rogue, Level 1) ``` ### Updating Characters ``` You: Thorin leveled up to 2 Skill: [Updates level and recalculates HP/proficiency] ``` ``` You: Increase Thorin's STR to 18 Skill: [Updates STR and shows new modifier] ``` ``` You: Thorin took 8 damage Skill: [Reduces HP from current max] ``` ## Code Walkthrough ### Database Schema The SQLite database stores all character data: ```sql CREATE TABLE characters ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, class TEXT NOT NULL, level INTEGER DEFAULT 1, strength INTEGER NOT NULL, dexterity INTEGER NOT NULL, constitution INTEGER NOT NULL, intelligence INTEGER NOT NULL, wisdom INTEGER NOT NULL, charisma INTEGER NOT NULL, hp_current INTEGER NOT NULL, hp_max INTEGER NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` ### character.py Script The Python script handles all database operations: **Key functions:** - `init_db()` - Creates database and table if they don't exist - `calculate_modifier(score)` - Converts ability score to modifier - `calculate_hp(con, class, level)` - Determines max HP - `create_character()` - Inserts new character - `show_character()` - Displays formatted character sheet - `update_character()` - Modifies existing character - `list_characters()` - Shows all characters The script uses argparse for a clean CLI: ```bash character.py create Thorin fighter --str 15 --dex 14 ... character.py show Thorin character.py update Thorin --hp 20 ``` ### Skill Workflow The skill.md orchestrates the interactive creation process: 1. **Roll dice**: Calls roll_dice.py 6 times with `--drop-lowest` 2. **Auto-assign**: Sorts rolls and assigns by class priority 3. **Display table**: Shows proposed assignment as markdown table 4. **Confirm loop**: - Ask "Accept? (y/n)" - If no: parse natural language adjustments - Update assignments and show table again - Repeat until yes 5. **Save**: Call character.py create with final values This teaches the pattern of: **generate → display → confirm → adjust → repeat → commit** ### Building on Tutorial 1 This tutorial copies `roll_dice.py` from Tutorial 1, demonstrating: - Code reuse across tutorials - Self-contained tutorial structure - Building more complex features on simpler foundations ## Key Concepts ### 1. SQLite for Persistence Instead of JSON files, we use SQLite because: - **Structured data**: Tables, columns, types enforce consistency - **Querying**: Easy to filter, sort, search characters - **Relationships**: Can link to other tables in future tutorials - **Atomic operations**: Update one field without reading/writing entire dataset - **Industry standard**: Real-world persistence pattern ### 2. Interactive Confirmation Loops The roll → assign → confirm → adjust pattern teaches: - Showing intermediate results before committing - Parsing user feedback in natural language - Maintaining state across multiple interactions - Graceful adjustment workflows ### 3. Calculated Properties The system automatically calculates: - **Modifiers** from ability scores: `(score - 10) / 2` - **HP** from class hit die + CON modifier + level - **Proficiency bonus** from level: `2 + ((level - 1) / 4)` This separates base data (what's stored) from derived data (what's calculated). ### 4. CLI Design for Skills The character.py script demonstrates good CLI patterns: - Subcommands (create, show, update, list) - Named arguments (--str, --dex) - Clear output formatting - Exit codes for errors - Help text ## Testing Your Skill Try these test cases: ### Character Creation - ✅ Create with rolled stats and auto-assignment - ✅ Adjust assignments before saving - ✅ Create with manual stats - ✅ Try different classes (fighter, wizard, rogue) - ❌ Create duplicate name (should error) ### Character Display - ✅ Show individual character - ✅ List all characters - ✅ List filtered by class - ❌ Show non-existent character (should error) ### Character Updates - ✅ Update single ability score - ✅ Update multiple scores - ✅ Change level (HP recalculates) - ✅ Adjust HP (damage/healing) ### Edge Cases - Character with all 8s in abilities - Character with all 20s in abilities - Level 20 character (proficiency +6) ## Extension Ideas Want to expand this tutorial? Try adding: - **Racial bonuses**: Apply +2 to certain abilities based on race - **Point buy system**: Alternative to rolling (assign points to buy scores) - **Ability score increases**: Track ASIs gained at levels 4, 8, 12, etc. - **Saving throw proficiencies**: Mark which saves the character is proficient in - **Skill proficiencies**: Track skills like Athletics, Stealth, Arcana - **Export/Import**: Backup characters to JSON files - **Character templates**: Save common builds to reuse ## Next Steps Ready to use your characters? Move on to: - **Tutorial 3: Simple Combat** - Use these characters to fight monsters - **Tutorial 5: Encounter Builder** - Manage multiple characters in combat ## Troubleshooting **Database not created?** - Check permissions on ~/.claude/data/ directory - Verify Python has sqlite3 module (built-in) **Character not found?** - Use `character.py list` to see all characters - Character names are case-sensitive **HP calculation seems wrong?** - Check the class hit die in character.py - Verify CON modifier is calculated correctly - Level 1 uses max die, additional levels use average **Skill not following workflow?** - Ensure skill.md clearly describes the confirmation loop - Check that Claude understands y/n responses - Try being more explicit in adjustments ("swap STR and DEX" not just "swap") ## Learn More - [SQLite Documentation](https://www.sqlite.org/docs.html) - [D&D 5E Ability Scores](https://www.dndbeyond.com/sources/basic-rules/using-ability-scores) - [Python sqlite3 Module](https://docs.python.org/3/library/sqlite3.html) - [Character Creation Rules](https://www.dndbeyond.com/sources/basic-rules/step-by-step-characters)