Implementing Dynamic Boss Battle Dialogue Generation System

Overview This module handles the generation of all boss battle dialogues before combat begins. Based on the player's current moral composition (good/neutral/evil), the system pre-generates the demon lord's (boss's) complete set of lines including entry narration, advantage taunts (10 lines), disadvantage monologues (10 lines), defeat declaration, and victory declaration. These dialogues are cached in the battle context and displayed as needed during combat.

Core Functions

2.1 Helper Function: Determine Dominant Tendency

def determine_dominant_moral_axis(
    moral_composition: Dict[str, float], 
    dominance_threshold: float = 0.5
) -> str:
    """
    Identifies the dominant moral tendency based on ratio distribution.

    Args:
        moral_composition: Dictionary containing 'good', 'neutral', 'evil' 
                          ratios (must sum to 1.0)
        dominance_threshold: Minimum ratio to qualify as dominant (default 0.5)

    Returns:
        One of: 'good', 'evil', 'neutral', 'balanced'
        - Returns the dominant axis if any ratio >= threshold
        - Returns 'balanced' if no single axis exceeds threshold
    """
    for tendency in ['good', 'evil', 'neutral']:
        if moral_composition.get(tendency, 0) >= dominance_threshold:
            return tendency
    return 'balanced'

2.2 Primary Function: Generate All Battle Dialogues

def generate_battle_dialogues(moral_composition: Dict[str, float]) -> Dict[str, Any]:
    """
    Pre-generates complete dialogue set for boss encounter.

    Args:
        moral_composition: Player moral ratios, e.g., 
                          {'good': 0.3, 'neutral': 0.2, 'evil': 0.5}

    Returns:
        Dictionary containing:
        {
            'entrance': str,           # Entry narration
            'taunts': List[str],       # Advantage taunts (10 items)
            'thinking': List[str],     # Disadvantage monologues (10 items)
            'defeat': str,             # Defeat declaration
            'victory': str             # Victory declaration
        }
        Falls back to default dialogues if generation fails.
    """
    # Implementation details follow

Implementation Guide

3.1 Template Loading

Dialogue templates reside in the project root's templates/ directory with the following filenames:

boss_entrance_template.txt boss_taunt_templates.txt boss_thinking_templates.txt boss_defeat_template.txt boss_victory_template.txt

Use the same path resolution approach as scene_generator.py. Consider caching templates at module load time since they rarely change. Define a module-level dictionary mapping dialogue types to template strings.

3.2 LLM Integration

Reuse the llm object and check_api_key function exported from llm_hint.py. If llm is None or the API key is invalid, return default dialogues immediately.

Create internal generation functions for each dialogue type, such as _create_entrance_lines(ratios). Use ChatPromptTemplate to format templates and invoke llm.invoke().

For list outputs (taunts and thinking), instruct the LLM to return a JSON array like ["line1", "line2", ...]. After parsing, verify the list contains exactly 10 items, padding with defaults if necessary.

3.3 Error Handling and Retries

Each generation task allows maximum 2 retry attempts (on exceptions or parse failures) If all retries fail, select defaults based on moral tendency using determine_dominant_moral_axis Default values for lists must contain exactly 10 dialogue lines

3.4 Default Dialogue Repository

DEFAULT_BATTLE_LINES = {
    'good': {
        'entrance': 'Every soul you saved... has perished.',
        'taunts': [
            'Your righteousness cannot shield you.',
            'Mercy is the refuge of the weak.',
            'Compassion is your undoing.',
            'Heroes always fall hardest.',
            'Your light blinds you.',
            'Good intentions pave the road to ruin.',
            'I\'ve watched saints crumble.',
            'Your halo weighs you down.',
            'Altruism never won battles.',
            'Virtue is a beautiful lie.'
        ],
        'thinking': [
            'Why... does it have to be me?',
            'This wasn\'t supposed to happen...',
            'I can\'t accept this.',
            'Was my path truly wrong?',
            'The heavens have abandoned me.',
            'Even angels fall.',
            'My conviction wavers.',
            'Is sacrifice meaningless?',
            'I gave everything...',
            'What did I fight for?'
        ],
        'defeat': 'Righteousness... prevails?',
        'victory': 'False virtue ends here.'
    },
    'evil': {
        'entrance': 'The ones you slaughtered... have come for you.',
        'taunts': [
            'Strike harder, coward.',
            'Is this the extent of your cruelty?',
            'I expected more blood.',
            'You disappoint me.',
            'Even demons show more fury.',
            'Your darkness is shallow.',
            'Hesitation is death.',
            'Pain is a gift I grant.',
            'Terrorize me properly.',
            'You lack conviction.'
        ],
        'thinking': [
            'This complicates things...',
            'They\'re stronger than anticipated.',
            'A worthy adversary emerges.',
            'Perhaps I underestimated them.',
            'The tables may turn.',
            'Tactics must change.',
            'Is this where it ends?',
            'Calculations prove inaccurate.',
            'Survival instincts activate.',
            'Retreat becomes an option.'
        ],
        'defeat': 'Evil... meets its maker?',
        'victory': 'You exceed even my depravity.'
    },
    'neutral': {
        'entrance': 'You chose nothing.',
        'taunts': [
            'Hesitation means defeat.',
            'Caution is cowardice.',
            'Stand and fight or fall.',
            'Your fence-sitting ends here.',
            'Neutrality is not protection.',
            'The middle path leads nowhere.',
            'Decide or die undecided.',
            'Balance is a myth.',
            'Neither hero nor villain—worse.',
            'Timidity kills.'
        ],
        'thinking': [
            'Perhaps I should have committed...',
            'My spirit wavers.',
            'Was there a better choice?',
            'Regret serves no purpose.',
            'Should I have taken a side?',
            'The middle ground crumbles.',
            'Courage eludes me.',
            'My principles collapse.',
            'What was my purpose?',
            'Void consumes everything.'
        ],
        'defeat': 'Was caution... my flaw?',
        'victory': 'The indecisive deserve death.'
    },
    'balanced': {
        'entrance': 'Who... are you really?',
        'taunts': [
            'Still performing?',
            'Even you cannot see yourself.',
            'The mask slips.',
            'Which face is genuine?',
            'Your duality betrays you.',
            'No one believes your act.',
            'Two souls, one vessel.',
            'Face your other self.',
            'The act grows tiresome.',
            'Your contradictions show.'
        ],
        'thinking': [
            'Cornered by my own self?',
            'Confusion consumes me.',
            'I... have fractured.',
            'Which path led here?',
            'Dual nature destroys balance.',
            'My reflection mocks me.',
            'Identity splinters.',
            'What am I becoming?',
            'Order becomes chaos.',
            'I am my own enemy.'
        ],
        'defeat': 'So... we are one.',
        'victory': 'I am you. You are me.'
    }
}

3.5 Return Value Specification

The function returns a complete dictionary of all dialogues. If generation succeeds entirely, return LLM-generated content. For partial failures, substitute failed components with default values while preserving successful ones.

Important Implementation Notes

Template placeholders: Each template must include {good_ratio}, {neutral_ratio}, and {evil_ratio} placeholders so the LLM understands the player's moral composition. JSON parsing: LLM responses may be wrapped in markdown code blocks. Use regex to strip these before parsing. Reference the parse_llm_response function in scene_generator.py for reuse. Logging: Use the logging module to record key steps and errors for debugging. Performance: This function executes once per boss encounter. With only 3 total encounters, computational cost remains manageable.

Testing

Create test cases in if name == "main": to invoke generate_battle_dialogues and verify outputs under various moral compositions. Also simulate LLM failures to confirm default dialogue fallback works correctly.

File Structure

Create src/game_logic/boss_dialogues.py as a dedicated module for dialogue pre-generation. This separation of concerns keeps the module focused. Import and use it from boss_fight.py as needed.

Tags: python game-development nlp-integration prompt-templates error-handling

Posted on Wed, 20 May 2026 19:50:43 +0000 by perfume