Game System¶
Overview¶
The Game System provides a framework for managing in-session gameplay, including initiative tracking, encounter management, and turn tracking. It enables GMs to prepare encounters in advance and manage them during gameplay.
The system is designed to support several workflows:
- Individual Character Testing: Players can test their character's attacks and abilities without a full game session
- Standalone Dice Roller: Players can use the bot for accurate dice rolling in offline or third-party games
- Full Campaign Management: GMs can run complete campaigns in Discord with initiative tracking and encounter management
Implementation Status¶
Completed Features ✅¶
- Initiative System
- Basic initiative tracking with turn order
- Player joining initiative with character
- DM adding monsters/NPCs
- Turn advancement
- Initiative rerolling
- Combatant removal
- Initiative state persistence
- Channel-specific initiative instances
- Permission model for DMs and players
- Combat state tracking (HP, conditions, etc.)
- Real-time HP display in initiative tracker for all combatants
-
Support for both rolled and fixed turn order modes
- Rolled mode: Traditional initiative based on dice rolls
- Fixed mode: Simulates table play where players act in seating order
- Once an initiative is created with a turn order mode, it can't switch to another mode.
-
Core Architecture
- Command module structure
- Database schemas for initiative and combatants
- Context modules for state management
- Integration with Discord message formatting
Fixed mode initiative¶
Shadowdark-specific initiative rules in fixed mode:
- Turn Order vs Turn Advancement: Fixed mode distinguishes between turn order (for display) and turn advancement (for actual gameplay)
- Turn Order (Display): All combatants are sorted by join order (the order in which they joined the initiative). The list is then rotated so that the combatant with the highest initiative roll is first, and the order continues in join order from that point, wrapping around as needed. This includes all player characters, the DM's placeholder character, and all monsters/NPCs.
- Turn Advancement (Gameplay): Only player characters and the DM's placeholder character advance turns. Monsters and NPCs are conceptually grouped with the DM's turn and do not get individual turns.
- Auto-Generated DM Placeholder: When an initiative is created in fixed mode, a DM placeholder combatant is automatically created and added to the initiative. This placeholder:
- Is created at the same timestamp as the initiative (ensuring it's always first in join order)
- Has a default name of "DM" (can be customized via !init begin [name] [mode]
)
- Has no associated character (character_id is nil)
- Cannot be removed from the initiative until it ends
- Acts as a non-combatant placeholder that represents the DM's turn
- Monster/NPC Grouping: When it's the DM's turn, the DM can control all monsters and NPCs in whatever order they choose. The grouping is conceptual and enforced through turn advancement logic, not database structure.
- DM's Actual Characters: If the DM joins the initiative with actual characters from their character sheet, these are treated as NPCs and grouped with the DM's turn, not as player characters.
- Convention-Based System: The system relies on conventions rather than strict enforcement:
- Visual Grouping Convention: To maintain visual grouping in the initiative tracker, monsters and NPCs should be added after all player characters have joined. If monsters are added during Round 0 while players are still joining, they will appear scattered throughout the turn order instead of grouped with the DM's turn.
- Flexible Timing: While the convention is to add monsters after players join, the system technically allows monsters to be added at any time during the initiative.
- No Enforcement: The bot cannot enforce this convention and cannot know how many players will join or when the DM will add monsters.
- Database Structure: All combatants (players, DM placeholder, monsters) are stored as individual records. The grouping happens at the turn advancement level, not the database level.
- Initiative Rerolling: Initiative can be rerolled when entering/exiting combat. In fixed mode, the DM uses the highest Dexterity modifier from all their characters/monsters for a single roll.
- Round 0: The period after initiative creation where players are joining. During Round 0, there is no current combatant, and the turn order is being established.
- Round 0 to Round 1 Transition: When advancing from Round 0 to Round 1 (the first !init next
command), only player characters are considered for determining who goes first. The DM placeholder and all monsters/NPCs are ignored during this transition. If no player characters have joined, the initiative cannot advance to Round 1.
- DM Placeholder Initiative: The DM placeholder receives an initiative roll during initiative rerolls, using the highest Dexterity modifier from all DM-controlled characters and monsters.
- Fixed Mode Only: The auto-generated DM placeholder is only created in fixed mode. Rolled mode uses traditional initiative where all combatants get individual turns.
Planned Features 📋¶
- Combat Actions
- Attack resolution system
- Damage application
- Healing system
- Condition tracking
-
Combat log
-
Encounter System
- Basic encounter creation and management
- Encounter state persistence
- Creature addition and removal
- Hidden creature support
- Encounter templates
- Integrating encounters with initiative tracker
- Encounter balancing tools
-
Encounter difficulty calculation
-
Campaign Management
- Session tracking
- XP tracking
- Loot distribution
- Quest tracking
Command Interface¶
Game Commands¶
!game start # Start a new game session
!game end # End current game session
Encounter Commands¶
!encounter new <name> # Create new encounter and select it
!encounter select <name> # Select an encounter to work with
!encounter list # List all encounters
!encounter show # Show current encounter details
!encounter delete # Delete current encounter
!encounter add <creature> # Add creature to selected encounter
!encounter hide <creature> # Hide creature in selected encounter
!encounter remove <creature> # Remove creature from selected encounter
!encounter start <name> # Start a prepared encounter
!encounter end # End current encounter
Initiative Commands¶
!init begin [name] [mode] # Start initiative tracking in current channel
# mode can be 'rolled' (default) or 'fixed'
!init end # End initiative tracking (DM only)
!init join # Join initiative (rolls initiative in rolled mode)
!init madd <name> # Manually add a monster/NPC to initiative (DM only)
!init remove <name> # Remove a combatant from initiative (DM only)
!init list # Show initiative order with current/max HP
!init reroll # Reroll initiative for all combatants (rolled mode only)
!init next # Advance to next turn
Combat Action Commands¶
!attack <target> # Attack a specific target
!hp <amount> # Modify current combatant's HP (healing/damage)
!condition <target> <condition> # Add/remove conditions
Example Workflows¶
DM Encounter Preparation¶
!encounter new "Ancient Temple - Guardian Chamber"
!encounter add "Stone Guardian" --hp 45 --ac 15
!encounter add "Temple Acolyte" --hp 22 --ac 12
!encounter hide "High Priest" --hp 35 --ac 14
!encounter new "Ancient Temple - Treasure Vault"
!encounter add "Cursed Statue" --hp 30 --ac 13
!encounter hide "Shadow Stalker" --hp 25 --ac 14
Combat Session Play¶
DM: !init begin "Ancient Temple - Guardian Chamber"
Bot: Initiative tracking started in #game-session
Current status: crawl
DM: !init madd "Stone Guardian"
Bot: Added Stone Guardian to initiative
DM: !init madd "Temple Acolyte"
Bot: Added Temple Acolyte to initiative
Player1: !init join
Bot: Player1 has joined the initiative
Player2: !init join
Bot: Player2 has joined the initiative
DM: !init list
Bot: Initiative Order: Round 0
1. Player1 - 18 <25/25>
2. Player2 - 15 <30/30>
3. Stone Guardian - 12 <45/45>
4. Temple Acolyte - 8 <22/22>
Current turn: Player1
Player1: !init next
Bot: Turn ended. Next up: Player2
[Combat continues...]
DM: !init remove "Temple Acolyte"
Bot: Temple Acolyte removed from initiative
DM: !init end
Bot: Are you sure you want to end initiative tracking?
Type `!init end confirm` to proceed
DM: !init end confirm
Bot: Initiative tracking ended in #game-session
System Architecture¶
The Game System follows the existing architecture patterns of the bot, with a focus on maintaining separation between command handling and game state management.
Command Modules¶
Stingbatbot.Commands.InitiativeCommand
- Initiative command handlerStingbatbot.Commands.Initiative.*
- Subcommand handlers for specific initiative actions
These modules are responsible for: - Parsing command arguments - Validating user permissions - Dispatching to the appropriate game state module - Formatting and sending responses
Core Modules¶
Stingbatbot.InitiativeRoll
- Handles initiative rolling logic- Manages dice rolling for initiative
- Calculates initiative modifiers
- Handles advantage/disadvantage
- Generates tiebreakers
Data Schemas¶
Stingbatbot.Schemas.Initiative
- Initiative tracking schema- Tracks channel-specific initiative state
- Maintains round number and status
- References current combatant's turn
- Links to all combatants in initiative
- Supports turn order modes (rolled/fixed)
- Note: Uses
:nilify_all
for current_combatant to handle combatant deletion gracefully -
Note: All Discord IDs (guild_id, dm_id, channel_id, message_id) are stored as
:integer
in schemas and:bigint
in the database -
Stingbatbot.Schemas.Combatant
- Combatant tracking schema - Stores combatant details (name, initiative roll)
- Links to character (if player character)
- Stores monster stats (if NPC/monster)
- Tracks current state during combat (hp, conditions, etc.)
- Belongs to an initiative
- Note: Uses
:delete_all
for initiative (deleted when initiative ends) and:nilify_all
for character (keeps combatant if character deleted) - Note: All Discord IDs (user_id, channel_id, message_id) are stored as
:integer
in schemas and:bigint
in the database - Note:
stats
field stores the initial/reference state, whilecurrent_stats
tracks temporary state changes during combat
These schemas define the database structure for: - Initiative tracking data - Combatant details and turn order - Current turn tracking
Context Modules¶
Stingbatbot.Contexts.Initiatives
- Initiative context- Manages initiative lifecycle (begin/end)
- Handles combatant management
- Manages turn order and advancement
- Coordinates initiative state updates
- Initializes combat state when combatants join
- Provides methods for managing current combat state
- Supports both rolled and fixed turn order modes
- Handles combatant sorting based on turn order mode
Key Methods:
- initialize_current_stats/1
- Sets up initial combat state for a new combatant
- For player characters: Copies relevant stats from character data
- For monsters: Copies relevant stats from monster data
- Initializes HP, conditions, and other combat-specific state
- reset_current_stats/1
- Resets a combatant's current state to their initial state
- Useful for effects that expire at the end of a turn or round
- Can be used to clear temporary conditions or buffs
- update_current_stats/2
- Updates a combatant's current state
- Takes a combatant and a map of stat changes
These modules are responsible for: - Database operations for game data - Data validation and transformation - Query interface for game state - Long-term persistence
Integration Modules¶
Stingbatbot.InitiativeFormatter
- Formats initiative state for DiscordStingbatbot.Commands.Utils
- Common command utilities
These modules are responsible for: - Formatting initiative state for Discord display - Managing Discord notifications - Handling turn alerts - Providing common command functionality
Implementation Flow¶
- Commands receive and parse Discord messages
- Commands invoke Context modules to modify state
- Context modules operate on Schemas for database operations
- InitiativeRoll module handles dice rolling and initiative calculations
- Formatter modules handle notifications back to Discord
This approach fits naturally with the existing codebase while providing initiative tracking functionality.
State Management¶
The Game System uses the database for all state management, ensuring persistence across bot restarts and providing a consistent view of the game state.
Persistent State¶
The system uses the database for: - Initiative tracking data - Combatant details - Player/character data
This ensures that initiative state remains available across sessions and bot restarts.
Permission Model¶
The Initiative System implements a permission model:
- DM permissions for initiative management:
- Starting/ending initiative tracking
- Manually adding monsters/NPCs
- Removing combatants
- Rerolling initiative
- Advancing turns for NPCs/Monsters
-
Advancing the first turn
-
Player permissions:
- Joining initiative with their character
- Advancing their own turn (not other players' turns)
-
Viewing initiative order
-
Channel-specific initiative instances:
- Each channel can have its own initiative tracking
- Initiative state is isolated to specific channels
- Players can only interact with initiative in channels they have access to
This ensures that: - Only DMs can manage initiative tracking - Only DMs can manually add monsters/NPCs - Only DMs can advance turns for NPCs/Monsters - Players can only control their own characters and advance their own turns - Initiative state is isolated to specific channels
Command Module Structure¶
The initiative system uses a modular command structure:
Stingbatbot.Commands.InitiativeCommand
- Main command module- Handles command routing and shared functionality
- Provides common utilities for subcommands
- Manages initiative tracker message updates
-
Implements DM permission verification
-
Subcommand modules under
Stingbatbot.Commands.Initiative.*
: BeginInit
- Handles starting initiative trackingEndInit
- Handles ending initiative trackingJoin
- Handles players joining initiativeMadd
- Handles DM adding monsters/NPCsRemove
- Handles removing combatantsList
- Handles displaying initiative orderReroll
- Handles rerolling initiativeNext
- Handles turn advancement
This structure allows for: - Clean separation of concerns - Reuse of common functionality - Easy addition of new subcommands - Consistent error handling and messaging