"""
Module representing the board evaluators.
"""
import queue
from enum import Enum
from typing import Any, Protocol
import chess
import chipiron.environments.chess_env.board as boards
from chipiron.players.boardevaluators.board_evaluation.board_evaluation import (
BoardEvaluation,
)
from chipiron.utils.communication.gui_messages import EvaluationMessage
from chipiron.utils.dataclass import IsDataclass
[docs]class BoardEvaluator(Protocol):
"""
Protocol representing a board evaluator.
"""
[docs] def value_white(self, board: boards.IBoard) -> float:
"""
Evaluates a board and returns the value for white.
"""
...
[docs]class IGameBoardEvaluator(Protocol):
"""
Protocol representing a game board evaluator.
"""
[docs] def evaluate(self, board: boards.IBoard) -> tuple[float | None, float]:
"""
Evaluates a board and returns the evaluation values for stock and chi.
"""
[docs] def add_evaluation(
self, player_color: chess.Color, evaluation: BoardEvaluation
) -> None:
"""
Adds an evaluation value for a player.
"""
[docs]class GameBoardEvaluator:
"""
This class is a collection of evaluators that display their analysis during the game.
They are not players, just external analysis and display.
"""
board_evaluator_stock: BoardEvaluator | None
board_evaluator_chi: BoardEvaluator
def __init__(
self,
board_evaluator_stock: BoardEvaluator | None,
board_evaluator_chi: BoardEvaluator,
):
self.board_evaluator_stock = board_evaluator_stock
self.board_evaluator_chi = board_evaluator_chi
[docs] def evaluate(self, board: boards.IBoard) -> tuple[float | None, float]:
"""
Evaluates a board and returns the evaluation values for stock and chi.
"""
evaluation_chi = self.board_evaluator_chi.value_white(board=board)
evaluation_stock = (
self.board_evaluator_stock.value_white(board=board)
if self.board_evaluator_stock is not None
else None
)
return evaluation_stock, evaluation_chi
[docs] def add_evaluation(
self, player_color: chess.Color, evaluation: BoardEvaluation
) -> None:
"""
Adds an evaluation value for a player.
"""
[docs]class ObservableBoardEvaluator:
"""
This class represents an observable board evaluator.
"""
game_board_evaluator: GameBoardEvaluator
mailboxes: list[queue.Queue[IsDataclass]]
evaluation_stock: Any
evaluation_chi: Any
evaluation_player_black: Any
evaluation_player_white: Any
def __init__(self, game_board_evaluator: GameBoardEvaluator):
self.game_board_evaluator = game_board_evaluator
self.mailboxes = []
self.evaluation_stock = None
self.evaluation_chi = None
self.evaluation_player_black = None
self.evaluation_player_white = None
[docs] def subscribe(self, mailbox: queue.Queue[IsDataclass]) -> None:
"""
Subscribe to the ObservableBoardEvaluator to get the EvaluationMessage.
Args:
mailbox: The mailbox queue.
"""
self.mailboxes.append(mailbox)
[docs] def evaluate(self, board: boards.IBoard) -> tuple[float | None, float]:
"""
Evaluates a board and returns the evaluation values for stock and chi.
"""
self.evaluation_stock, self.evaluation_chi = self.game_board_evaluator.evaluate(
board=board
)
self.notify_new_results()
return self.evaluation_stock, self.evaluation_chi
[docs] def add_evaluation(
self, player_color: chess.Color, evaluation: BoardEvaluation
) -> None:
"""
Adds an evaluation value for a player.
"""
if player_color == chess.BLACK:
self.evaluation_player_black = evaluation
if player_color == chess.WHITE:
self.evaluation_player_white = evaluation
self.notify_new_results()
[docs] def notify_new_results(self) -> None:
"""
Notifies the subscribers about the new evaluation results.
"""
for mailbox in self.mailboxes:
message: EvaluationMessage = EvaluationMessage(
evaluation_stock=self.evaluation_stock,
evaluation_chipiron=self.evaluation_chi,
evaluation_player_white=self.evaluation_player_white,
evaluation_player_black=self.evaluation_player_black,
)
mailbox.put(item=message)