Source code for haive.games.mancala.models

"""Comprehensive data models for the Mancala (Kalah) board game.

This module defines the complete set of data structures for the traditional
Mancala game, providing models for move validation, strategic analysis, and
game state representation. The implementation follows standard Kalah rules
with 6 pits per player and seed redistribution mechanics.

Mancala is a classic strategy game involving:
- Two players with 6 pits each plus one store (mancala)
- Seed sowing mechanics with capture rules
- Strategic pit selection for optimal play
- Turn continuation and capture bonus rules

Key Models:
    MancalaMove: Represents a player's pit selection
    MancalaAnalysis: Strategic evaluation for AI decision-making

Examples:
    Making moves::

        from haive.games.mancala.models import MancalaMove

        # Select pit 2 for player 1
        move = MancalaMove(pit_index=2, player="player1")

        # Strategic center play
        center_move = MancalaMove(pit_index=3, player="player2")

    Strategic analysis::

        from haive.games.mancala.models import MancalaAnalysis

        analysis = MancalaAnalysis(
            captures_possible=[2, 4],
            free_turns_available=[1, 3],
            pit_values=[4, 3, 2, 5, 1, 6],
            strategy="Focus on pit 3 for free turn opportunity"
        )

The models support AI strategy development with comprehensive validation
and integration with the Mancala game engine.

"""

from typing import Literal

from pydantic import BaseModel, Field, ValidationInfo, field_validator


[docs] class MancalaMove(BaseModel): """Represents a move in Mancala. This class defines the structure of a move in Mancala, which includes the pit index to sow from and the player making the move. """ pit_index: int = Field( ..., ge=0, lt=6, description="Index of the pit to sow from (0-5)" ) player: Literal["player1", "player2"] = Field( ..., description="Player making the move" )
[docs] @field_validator("pit_index") @classmethod def validate_pit_index(cls, v: int, info: ValidationInfo) -> int: """Validate that the pit index is valid for the player. Args: v: The pit index to validate. info: Validation info containing other field values. Returns: The validated pit index. Raises: ValueError: If pit index is out of valid range. """ if "player" in info.data: # Adjust validation based on player if info.data["player"] == "player1" and not (0 <= v < 6): raise ValueError(f"Player 1 pit index must be 0-5, got {v}") if info.data["player"] == "player2" and not (0 <= v < 6): raise ValueError(f"Player 2 pit index must be 0-5, got {v}") return v
def __str__(self) -> str: """Return string representation of the move.""" return f"{self.player} sows from pit {self.pit_index}"
[docs] class MancalaAnalysis(BaseModel): """Analysis of a Mancala position. This class defines the structure of an analysis for a Mancala position, which includes the overall position evaluation, advantage level, stone distribution, pit recommendations, strategic focus, key tactics, and reasoning. """ position_evaluation: Literal["winning", "losing", "equal", "unclear"] = Field( ..., description="Overall position evaluation" ) advantage_level: int = Field( ..., ge=0, le=10, description="Level of advantage (0-10, where 10 is winning)" ) stone_distribution: str = Field(..., description="Analysis of stone distribution") pit_recommendations: list[int] = Field( ..., description="Recommended pits to play from" ) strategy_focus: Literal["offensive", "defensive", "balanced"] = Field( ..., description="Current strategic focus" ) key_tactics: list[str] = Field(..., description="Key tactical considerations") reasoning: str = Field(..., description="Detailed reasoning for the analysis")