Source code for haive.games.clue.state_manager

"""State manager for the Clue game.

This module defines the state management for the Clue game, providing methods for game
logic and state transitions.

"""

from typing import Any

from haive.games.clue.models import ClueGuess
from haive.games.clue.state import ClueState
from haive.games.framework.base.state_manager import GameStateManager


[docs] class ClueStateManager(GameStateManager[ClueState]): """Manager for Clue game state."""
[docs] @classmethod def initialize(cls, **kwargs) -> ClueState: """Initialize a new Clue game. Args: **kwargs: Keyword arguments for game initialization Returns: ClueState: A new Clue game state """ return ClueState.initialize(**kwargs)
[docs] @classmethod def apply_move(cls, state: ClueState, move: ClueGuess) -> ClueState: """Apply a guess to the current state. Args: state: Current game state move: The guess to apply Returns: Updated game state """ # Validate player's turn # Note: ClueGuess doesn't have a player attribute, so we use current_player # This assumes the move is being made by the current player # Validate turn limit if len(state.guesses) >= state.max_turns: raise ValueError("Maximum number of turns reached") # Create a new state new_state = state.model_copy() # Add the guess new_state.guesses.append(move) # Determine if the guess matches the solution if ( move.suspect == new_state.solution.suspect and move.weapon == new_state.solution.weapon and move.room == new_state.solution.room ): # Winning move new_state.game_status = f"{move.player}_win" new_state.winner = move.player return new_state # Switch players new_state.current_player = "player2" if move.player == "player1" else "player1" # Check if max turns reached if len(new_state.guesses) >= new_state.max_turns: new_state.game_status = f"{new_state.solution.suspect}_win" new_state.winner = new_state.solution.suspect return new_state
[docs] @classmethod def check_game_status(cls, state: ClueState) -> ClueState: """Check and potentially update game status. Args: state: Current game state Returns: Updated game state """ return state
[docs] @classmethod def get_winner(cls, state: ClueState) -> str | None: """Get the winner of the game. Args: state: Current game state Returns: Winner of the game, or None if ongoing """ return state.winner
[docs] @classmethod def add_analysis( cls, state: ClueState, player: str, hypothesis: dict[str, Any] ) -> ClueState: """Add a hypothesis to the state. Args: state: Current game state player: Player performing the analysis hypothesis: Hypothesis details Returns: Updated state with added hypothesis """ new_state = state.model_copy() if player == "player1": new_state.player1_hypotheses.append(hypothesis) else: new_state.player2_hypotheses.append(hypothesis) return new_state
[docs] @classmethod def get_possible_solutions(cls, state: ClueState) -> set[tuple[str, str, str]]: """Get possible solutions based on the current game state. Args: state: Current game state Returns: Set of possible solutions as (suspect, weapon, room) tuples """ # Start with all possible combinations all_suspects = [ "Miss Scarlet", "Colonel Mustard", "Mrs. White", "Mr. Green", "Mrs. Peacock", "Professor Plum", ] all_weapons = [ "Candlestick", "Knife", "Lead Pipe", "Revolver", "Rope", "Wrench", ] all_rooms = [ "Hall", "Lounge", "Dining Room", "Kitchen", "Ballroom", "Conservatory", "Billiard Room", "Library", "Study", ] # Filter out known invalid combinations based on player cards and # guesses player_cards = set(state.player1_cards + state.player2_cards) possible_solutions = { (suspect, weapon, room) for suspect in all_suspects for weapon in all_weapons for room in all_rooms if ( suspect not in player_cards and weapon not in player_cards and room not in player_cards ) } return possible_solutions