Source code for haive.games.battleship.debug

"""Debug script for testing Battleship game.

This module provides a debugging interface for the Battleship game,
with detailed logging and visualization of game state at each step.
It's designed for:
    - Diagnosing game logic issues
    - Visualizing internal state transitions
    - Testing new features and configurations
    - Analyzing LLM decision making

Run this script directly to start a debug session:
    python -m haive.games.battleship.debug

"""

import time

from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.traceback import install

from haive.games.battleship.agent import BattleshipAgent
from haive.games.battleship.config import BattleshipAgentConfig

# Enable rich traceback for better debugging
install()
console = Console()


[docs] def test_battleship(): """Run a test game of Battleship with detailed logging. Creates and runs a Battleship game in debug mode, displaying detailed information about each step of the game, including: - Game phase and player turns - Ship placements during setup - Move history and results - Strategic analysis from LLMs - Error messages and game status This function is useful for: - Diagnosing issues with game logic - Validating LLM outputs and decisions - Testing state transitions and error handling - Visualizing the internal game state Returns: None Raises: Exception: Catches and logs any exceptions that occur during gameplay """ console.rule("[bold blue]Battleship Game Debug Test") console.print("Initializing game agent...") # Create configuration with debugging enabled config = BattleshipAgentConfig( name="battleship_debug", enable_analysis=True, visualize_board=True, debug=True, ) try: # Create agent agent = BattleshipAgent(config) console.print("[green]Agent initialized successfully![/green]") # Run the game step by step step_count = 0 for state in agent.app.stream( {}, stream_mode="values", debug=True, config=agent.runnable_config, ): step_count += 1 # Display step information console.rule(f"[bold cyan]Step {step_count}") # Basic game state phase = state.get("game_phase", "unknown") current_player = state.get("current_player", "unknown") winner = state.get("winner", None) # Create status table status = Table(title="Game Status") status.add_column("Phase") status.add_column("Current Player") status.add_column("Winner") status.add_row( f"[bold]{phase}[/bold]", f"[bold]{current_player}[/bold]", f"[bold green]{winner}[/bold green]" if winner else "None", ) console.print(status) # Display error if any if state.get("error_message"): console.print( Panel( f"[bold red]{state['error_message']}[/bold red]", title="ERROR", border_style="red", ), ) # Phase-specific displays if phase == "setup": player1_placed = state.get("player1_state", {}).get( "has_placed_ships", False, ) player2_placed = state.get("player2_state", {}).get( "has_placed_ships", False, ) setup_status = Table(title="Setup Status") setup_status.add_column("Player") setup_status.add_column("Ships Placed") setup_status.add_row( "Player 1", "[green]Yes[/green]" if player1_placed else "[red]No[/red]", ) setup_status.add_row( "Player 2", "[green]Yes[/green]" if player2_placed else "[red]No[/red]", ) console.print(setup_status) # Display ship placements if available if player1_placed or player2_placed: ships_table = Table(title="Ship Placements") ships_table.add_column("Player") ships_table.add_column("Ship Type") ships_table.add_column("Coordinates") if player1_placed: placements = state.get("player1_state", {}).get( "ship_placements", [], ) for placement in placements: ships_table.add_row( "Player 1", str(placement.get("ship_type", "Unknown")), str( [ f"({c.get('row', '?')},{c.get('col', '?')})" for c in placement.get("coordinates", []) ], ), ) if player2_placed: placements = state.get("player2_state", {}).get( "ship_placements", [], ) for placement in placements: ships_table.add_row( "Player 2", str(placement.get("ship_type", "Unknown")), str( [ f"({c.get('row', '?')},{c.get('col', '?')})" for c in placement.get("coordinates", []) ], ), ) console.print(ships_table) elif phase == "playing": # Display move history move_history = state.get("move_history", []) if move_history: moves_table = Table(title="Recent Moves") moves_table.add_column("Player") moves_table.add_column("Target") moves_table.add_column("Result") # Display the last 5 moves for player, result in move_history[-5:]: result_text = result.get("result", "unknown") result_style = { "hit": "[bold green]HIT[/bold green]", "miss": "[bold red]MISS[/bold red]", "sunk": "[bold yellow]SUNK[/bold yellow]", "invalid": "[bold orange]INVALID[/bold orange]", }.get(result_text, result_text) moves_table.add_row( player, f"({result.get('row', '?')}, {result.get('col', '?')})", result_style, ) console.print(moves_table) # Display strategic analysis if available player1_analysis = state.get("player1_state", {}).get( "strategic_analysis", [], ) player2_analysis = state.get("player2_state", {}).get( "strategic_analysis", [], ) if player1_analysis or player2_analysis: analysis_table = Table(title="Strategic Analysis") analysis_table.add_column("Player") analysis_table.add_column("Analysis") if player1_analysis: latest = player1_analysis[-1] if player1_analysis else "" analysis_table.add_row( "Player 1", latest[:100] + "..." if len(latest) > 100 else latest, ) if player2_analysis: latest = player2_analysis[-1] if player2_analysis else "" analysis_table.add_row( "Player 2", latest[:100] + "..." if len(latest) > 100 else latest, ) console.print(analysis_table) # Game over display elif phase == "ended": console.print( Panel( f"[bold green]Game Over! Winner: {winner}[/bold green]", title="🏆 VICTORY 🏆", border_style="green", ), ) # Brief pause between steps time.sleep(0.5) # Final game summary console.rule("[bold green]Game Complete") console.print(f"Total steps: {step_count}") except Exception as e: console.print_exception() console.print(f"[bold red]Error:[/bold red] {e!s}")
if __name__ == "__main__": test_battleship()