haive.games.tic_tac_toe.state

Comprehensive state management system for strategic Tic Tac Toe gameplay.

from typing import Any This module provides sophisticated state management for Tic Tac Toe games with complete support for game mechanics, strategic analysis, and LangGraph integration. The state system maintains game rules, move validation, and comprehensive game history for educational and competitive gameplay.

The state system supports: - Complete 3x3 board representation with move validation - Turn-based gameplay with X and O player management - Move history tracking for game replay and analysis - Strategic analysis integration for both players - Win condition detection (rows, columns, diagonals) - Draw detection and game status management - LangGraph reducers for concurrent state updates - Error handling and recovery mechanisms

Examples

Initializing a new game:

state = TicTacToeState.initialize(
    first_player="X",
    player_X="player1",
    player_O="player2"
)

Making a move and checking status:

# Make a center move
state.board[1][1] = "X"
state.move_history.append(
    TicTacToeMove(row=1, col=1, player="X")
)

# Check game state
if state.is_board_full:
    state.game_status = "draw"

Analyzing board positions:

empty_cells = state.empty_cells
print(f"Available moves: {empty_cells}")

# Pretty print the board
print(state.board_string)

Managing player turns:

current = state.current_player_name
if state.turn == "X":
    state.turn = "O"
else:
    state.turn = "X"

Note

All state updates should use LangGraph Commands to ensure proper reducer behavior and concurrent update handling.

Classes

TicTacToeState

Comprehensive state model for Tic Tac Toe gameplay with LangGraph integration.

Functions

add_messages_reducer(left, right)

Reducer for message-like lists that should be concatenated.

replace_board_reducer(left, right)

Special reducer for the board that always replaces with the new board.

replace_reducer(left, right)

Reducer that always takes the new value (right side).

Module Contents

class haive.games.tic_tac_toe.state.TicTacToeState(/, **data)[source]

Bases: haive.games.framework.base.state.GameState

Comprehensive state model for Tic Tac Toe gameplay with LangGraph integration.

This class provides complete state management for Tic Tac Toe games, supporting both traditional gameplay mechanics and advanced features for AI analysis. The state system maintains game rules, validates moves, tracks history, and integrates with LangGraph for distributed gameplay and concurrent updates.

The state model supports: - 3x3 board representation with None/X/O values - Turn management with alternating X and O players - Move history for game replay and analysis - Player-specific analysis storage - Win/draw detection and game status tracking - Error handling for invalid moves - LangGraph reducers for proper state updates - Pretty-printing for board visualization

All fields use explicit reducers to ensure proper behavior with LangGraph’s concurrent update system, preventing state corruption during parallel operations.

Parameters:

data (Any)

players

Player identifiers with accumulating reducer.

Type:

List[str]

board

3x3 game board with replace reducer.

Type:

List[List[Optional[str]]]

turn

Current player’s turn with replace reducer.

Type:

Literal[“X”, “O”]

game_status

Game state (ongoing/X_win/O_win/draw) with replace reducer.

Type:

Literal

move_history

Complete move history with accumulating reducer.

Type:

List[TicTacToeMove]

error_message

Error state with replace reducer.

Type:

Optional[str]

winner

Winner identifier with replace reducer.

Type:

Optional[str]

player_X

Player using X symbol with replace reducer.

Type:

Literal

player_O

Player using O symbol with replace reducer.

Type:

Literal

player1_analysis

Player 1’s analyses with accumulating reducer.

Type:

List[TicTacToeAnalysis]

player2_analysis

Player 2’s analyses with accumulating reducer.

Type:

List[TicTacToeAnalysis]

Examples

Creating and initializing a game:

state = TicTacToeState.initialize(
    first_player="X",
    player_X="Alice",
    player_O="Bob"
)
assert state.turn == "X"
assert state.game_status == "ongoing"
assert all(cell is None for row in state.board for cell in row)

Making moves and updating state:

# X plays center
state.board[1][1] = "X"
state.move_history.append(
    TicTacToeMove(row=1, col=1, player="X")
)
state.turn = "O"

# O plays corner
state.board[0][0] = "O"
state.move_history.append(
    TicTacToeMove(row=0, col=0, player="O")
)
state.turn = "X"

Checking win conditions:

# X wins with diagonal
state.board = [
    ["X", "O", None],
    ["O", "X", None],
    [None, None, "X"]
]
state.game_status = "X_win"
state.winner = "player1"

Board visualization:

print(state.board_string)
# Output:
#    0 1 2
#   -------
# 0 |X|O| |
#   -------
# 1 |O|X| |
#   -------
# 2 | | |X|
#   -------

Note

State updates should be performed through LangGraph Commands to ensure proper reducer behavior and prevent concurrent update conflicts.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

classmethod initialize(**kwargs)[source]

Initialize a new Tic Tac Toe game with optional configuration.

Factory method to create a properly initialized game state with all required fields set to appropriate starting values.

Parameters:

**kwargs – Optional configuration parameters: first_player (Literal[“X”, “O”]): Which player goes first (default: “X”). player_X (Literal[“player1”, “player2”]): Player using X (default: “player1”). player_O (Literal[“player1”, “player2”]): Player using O (default: “player2”).

Returns:

Newly initialized game state ready for play.

Return type:

TicTacToeState

Examples

Default initialization:

state = TicTacToeState.initialize()
assert state.turn == "X"
assert state.player_X == "player1"
assert state.player_O == "player2"

Custom player assignment:

state = TicTacToeState.initialize(
    first_player="O",
    player_X="player2",
    player_O="player1"
)
assert state.turn == "O"
assert state.current_player_name == "player1"

Tournament setup:

state = TicTacToeState.initialize(
    first_player="X",
    player_X="player1",
    player_O="player2"
)
# Ready for competitive play
classmethod validate_board(board)[source]

Validate that the board is a proper 3x3 grid with valid symbols.

Ensures the board maintains the correct structure and contains only valid values (None for empty, ‘X’, or ‘O’ for occupied cells).

Parameters:

board (List[List[Optional[str]]]) – The board to validate.

Returns:

Validated board or default empty board.

Return type:

List[List[Optional[str]]]

Raises:

ValueError – If the board structure is invalid or contains invalid values.

Examples

Valid board:

board = [["X", None, "O"], [None, "X", None], ["O", None, "X"]]
# Passes validation

Invalid board (wrong size):

board = [["X", "O"], ["O", "X"]]  # 2x2 instead of 3x3
# Raises ValueError: "Board must have 3 rows"

Invalid board (invalid symbol):

board = [["X", "Y", "O"], [None, None, None], [None, None, None]]
# Raises ValueError: "Cell values must be None, 'X', or 'O', got Y"
property board_string: str

Get a pretty-printed string representation of the board.

Creates a human-readable ASCII representation of the current board state with row and column indices for easy reference.

Returns:

Multiline string representing the current board state.

Return type:

str

Examples

Empty board:

   0 1 2
  -------
0 | | | |
  -------
1 | | | |
  -------
2 | | | |
  -------

Game in progress:

   0 1 2
  -------
0 |X|O| |
  -------
1 | |X| |
  -------
2 |O| |X|
  -------
property current_player_name: str

Get the identifier of the player whose turn it is.

Maps the current turn symbol (X or O) to the assigned player identifier.

Returns:

The player identifier (“player1” or “player2”).

Return type:

str

Examples

>>> state = TicTacToeState.initialize()
>>> state.turn = "X"
>>> state.current_player_name
'player1'
>>> state.turn = "O"
>>> state.current_player_name
'player2'
property empty_cells: list[tuple[int, int]]

Return a list of coordinates for all empty cells on the board.

Useful for determining available moves and checking if the game can continue.

Returns:

List of (row, col) tuples for empty cells.

Return type:

list[tuple[int, int]]

Examples

>>> state = TicTacToeState.initialize()
>>> state.empty_cells
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
>>> state.board[1][1] = "X"
>>> len(state.empty_cells)
8
property is_board_full: bool

Check whether the board is completely filled with no empty cells.

Used to detect draw conditions when no player has won.

Returns:

True if all cells are occupied, False otherwise.

Return type:

bool

Examples

>>> state = TicTacToeState.initialize()
>>> state.is_board_full
False
>>> # Fill the board
>>> state.board = [["X", "O", "X"], ["O", "X", "O"], ["O", "X", "X"]]
>>> state.is_board_full
True
haive.games.tic_tac_toe.state.add_messages_reducer(left, right)[source]

Reducer for message-like lists that should be concatenated.

This reducer is used for accumulating lists like move history and analysis results, preserving all historical data.

Parameters:
  • left (list) – Existing list in the state.

  • right (list) – New items to append.

Returns:

Concatenated list with all items.

Return type:

list

Examples

>>> add_messages_reducer([1, 2], [3, 4])
[1, 2, 3, 4]
>>> add_messages_reducer([], [1, 2])
[1, 2]
haive.games.tic_tac_toe.state.replace_board_reducer(left, right)[source]

Special reducer for the board that always replaces with the new board.

This ensures the board state is always consistent and prevents partial updates that could create invalid game states.

Parameters:
  • left (Any) – Existing board state.

  • right (Any) – New board state.

Returns:

The new board state.

Return type:

Any

haive.games.tic_tac_toe.state.replace_reducer(left, right)[source]

Reducer that always takes the new value (right side).

This reducer is used for fields that should be completely replaced on update rather than merged or concatenated.

Parameters:
  • left (Any) – Existing value in the state.

  • right (Any) – New value to replace with.

Returns:

The new value (right side).

Return type:

Any

Examples

>>> replace_reducer("X", "O")
'O'
>>> replace_reducer([1, 2], [3, 4])
[3, 4]