Source code for haive.games.battleship.config

"""Battleship game agent configuration.

This module defines comprehensive configuration classes for Battleship game agents,
providing extensive customization options for game rules, AI behavior, UI preferences,
and performance settings.

The configuration system supports:
    - Board size and ship placement customization
    - Multiple difficulty levels and AI strategies
    - Turn time limits and timeout handling
    - Analysis and logging capabilities
    - UI themes and display preferences
    - Performance optimization settings

Classes:
    BattleshipAgentConfig: Main configuration class for Battleship agents
    ShipConfiguration: Configuration for ship types and placement rules
    GameRuleConfiguration: Game rule and validation settings
    UIConfiguration: User interface and display settings
    PerformanceConfiguration: Performance and optimization settings

Example:
    Creating a basic Battleship agent configuration:

        config = BattleshipAgentConfig(
            player_name="Admiral Hayes",
            difficulty="intermediate",
            board_size=10,
            enable_analysis=True,
            turn_timeout=30.0,
        )

        agent = BattleshipAgent(config)

Note:
    All configuration classes include comprehensive validation to ensure
    game rule consistency and prevent invalid combinations that would
    break gameplay mechanics.

"""

import uuid
from typing import Any

from haive.core.engine.agent.agent import AgentConfig
from haive.core.engine.aug_llm import AugLLMConfig
from langchain_core.runnables import RunnableConfig
from pydantic import Field, computed_field, model_validator

from haive.games.battleship.engines import build_battleship_engines
from haive.games.battleship.state import BattleshipState


[docs] class BattleshipAgentConfig(AgentConfig): """Comprehensive configuration for Battleship game agents with extensive. customization. This configuration class provides complete control over Battleship game mechanics, supporting various game modes, strategic analysis settings, visualization options, and LLM engine configurations. It includes validation for game consistency and provides factory methods for common Battleship scenarios. The configuration system supports: - Player identification and naming - Strategic analysis and decision-making options - Visualization and debugging settings - LLM engine configurations for different game actions - Performance optimization parameters - Game state management and persistence Attributes: name (str): Unique identifier for the agent instance. Used for logging, debugging, and multi-agent coordination. state_schema (type): Pydantic model class for game state management. Defines the structure and validation rules for game state. player1_name (str): Display name for the first player. Used in visualization and game logging. Auto-generated from engine config. player2_name (str): Display name for the second player. Used in visualization and game logging. Auto-generated from engine config. enable_analysis (bool): Enable strategic analysis during gameplay. When True, agents will perform detailed position analysis before moves. visualize_board (bool): Enable board visualization during gameplay. When True, displays game boards and move history in console. runnable_config (RunnableConfig): LangChain runnable configuration. Controls execution parameters including recursion limits and thread IDs. engines (Dict[str, AugLLMConfig]): LLM engine configurations for game actions. Contains engines for ship placement, move generation, and analysis. Examples: Standard competitive configuration::\\n config = BattleshipAgentConfig( name="tournament_battleship", player1_name="Strategic_AI", player2_name="Tactical_AI", enable_analysis=True, visualize_board=False ) Training and debugging configuration::\\n config = BattleshipAgentConfig( name="training_battleship", enable_analysis=True, visualize_board=True, player1_name="Learning_Agent", player2_name="Reference_Agent" ) Performance-optimized configuration::\\n config = BattleshipAgentConfig( name="speed_battleship", enable_analysis=False, visualize_board=False, runnable_config={ "configurable": { "recursion_limit": 5000, "thread_id": "speed_session" } } ) Note: Configuration validation ensures game rule consistency and prevents invalid combinations that would break gameplay mechanics or create unfair advantages. """ name: str = Field( default="battleship_agent", min_length=1, max_length=50, description="Unique identifier for the agent instance used for logging and debugging", examples=["battleship_agent", "tournament_battleship", "training_agent"], ) state_schema: type = Field( default=BattleshipState, description="Pydantic model class for game state management and validation", ) player1_name: str = Field( default="Player 1", min_length=1, max_length=30, description="Display name for the first player, auto-generated from engine config", examples=["Admiral_Nelson", "Strategic_AI", "Human_Player"], ) player2_name: str = Field( default="Player 2", min_length=1, max_length=30, description="Display name for the second player, auto-generated from engine config", examples=["Captain_Ahab", "Tactical_AI", "Computer_Opponent"], ) enable_analysis: bool = Field( default=True, description="Enable strategic analysis during gameplay for better decision-making", examples=[True, False], ) visualize_board: bool = Field( default=True, description="Enable board visualization during gameplay for debugging and monitoring", examples=[True, False], ) runnable_config: RunnableConfig = Field( default={"configurable": {"recursion_limit": 10000, "thread_id": None}}, description="LangChain runnable configuration with execution parameters and thread management", ) engines: dict[str, AugLLMConfig] = Field( default_factory=build_battleship_engines, description="LLM engine configurations for ship placement, move generation, and analysis", )
[docs] @model_validator(mode="after") def update_player_names_from_engines(self) -> Any: """Update player names based on LLM provider and model from engines. Automatically generates meaningful player names based on the configured LLM engines, creating identifiers that include provider and model information. Also ensures thread_id is set for proper session management. Returns: BattleshipAgentConfig: Self with updated player names and thread configuration. Examples: Configuration with OpenAI engines::\\n config = BattleshipAgentConfig() # After validation, player names might be: # player1_name = "azure-gpt-4o" # player2_name = "Player 2" """ if ( not self.runnable_config.get("configurable", {}).get("thread_id") or self.runnable_config["configurable"]["thread_id"] is None ): self.runnable_config["configurable"]["thread_id"] = str(uuid.uuid4()) try: if self.engines and self.player1_name == "Player 1": player1_engine = self.engines.get("player1_move") if player1_engine and hasattr(player1_engine, "llm_config"): llm_config = player1_engine.llm_config if hasattr(llm_config, "model"): model = getattr(llm_config, "model", "unknown") self.player1_name = f"azure-{model}" except Exception: pass return self
[docs] @classmethod def competitive(cls) -> "BattleshipAgentConfig": """Create a configuration optimized for competitive gameplay. Generates a configuration suitable for tournaments and competitive matches, with analysis enabled but visualization disabled for performance. Returns: BattleshipAgentConfig: Configuration optimized for competitive play. Examples: Creating a tournament-ready configuration::\\n config = BattleshipAgentConfig.competitive() agent = BattleshipAgent(config) # Results in: # - Analysis enabled for strategic depth # - Visualization disabled for performance # - Optimized recursion limits # - Tournament-appropriate naming """ return cls( name="competitive_battleship", enable_analysis=True, visualize_board=False, runnable_config={ "configurable": { "recursion_limit": 8000, "thread_id": f"competitive_{str(uuid.uuid4())[:8]}", } }, )
[docs] @classmethod def training(cls) -> "BattleshipAgentConfig": """Create a configuration optimized for training and development. Generates a configuration suitable for agent training, debugging, and development work, with full analysis and visualization enabled. Returns: BattleshipAgentConfig: Configuration optimized for training scenarios. Examples: Creating a training configuration::\\n config = BattleshipAgentConfig.training() agent = BattleshipAgent(config) # Results in: # - Analysis enabled for learning # - Visualization enabled for monitoring # - Extended recursion limits # - Training-appropriate naming """ return cls( name="training_battleship", enable_analysis=True, visualize_board=True, runnable_config={ "configurable": { "recursion_limit": 15000, "thread_id": f"training_{str(uuid.uuid4())[:8]}", } }, )
[docs] @classmethod def performance(cls) -> "BattleshipAgentConfig": """Create a configuration optimized for maximum performance. Generates a configuration suitable for high-speed gameplay and benchmarking, with analysis and visualization disabled for optimal performance. Returns: BattleshipAgentConfig: Configuration optimized for performance. Examples: Creating a performance-optimized configuration::\\n config = BattleshipAgentConfig.performance() agent = BattleshipAgent(config) # Results in: # - Analysis disabled for speed # - Visualization disabled for performance # - Reduced recursion limits # - Performance-appropriate naming """ return cls( name="performance_battleship", enable_analysis=False, visualize_board=False, runnable_config={ "configurable": { "recursion_limit": 5000, "thread_id": f"performance_{str(uuid.uuid4())[:8]}", } }, )
@computed_field @property def configuration_summary(self) -> dict[str, str]: """Get a summary of the current configuration settings. Returns: Dict[str, str]: Summary of key configuration parameters. Examples: Checking configuration summary::\\n config = BattleshipAgentConfig.competitive() summary = config.configuration_summary print(f"Mode: {summary['mode']}") print(f"Analysis: {summary['analysis_enabled']}") """ return { "name": self.name, "analysis_enabled": "Yes" if self.enable_analysis else "No", "visualization_enabled": "Yes" if self.visualize_board else "No", "recursion_limit": str( self.runnable_config.get("configurable", {}).get( "recursion_limit", "Unknown" ) ), "thread_id": ( self.runnable_config.get("configurable", {}).get( "thread_id", "Not set" )[:8] + "..." if self.runnable_config.get("configurable", {}).get("thread_id") else "Not set" ), "engine_count": str(len(self.engines)), }
[docs] class Config: """Pydantic configuration for flexible validation and type handling.""" arbitrary_types_allowed = True validate_assignment = True