Source code for gogame.player

from __future__ import annotations
from abc import ABC, abstractmethod
import functools
from typing import (
    Optional,
    TYPE_CHECKING
)

import numpy as np

from .enum import Color

if TYPE_CHECKING:
    from .territory import Territory
    from .board import Board


def in_game(func):
    @functools.wraps(func)
    def f(self, *args, **kwargs):
        if self._in_game:
            if self._color and self._board:
                return func(self, *args, **kwargs)
            else:
                raise Exception("Player is in game but is not fully initialized")
        else:
            raise Exception("Player is not currently in game")
    return f


[docs] class Player(ABC): """Represents a go player. This class has to be overridden to implement the :func:`play()` method""" def __init__(self, name: Optional[str] = None, color: Optional[Color] = None): """ Args: name: The name of the player (only used to identify it) color: The color the player will player, if set to None, it's automatically set by the board """ self._in_game: bool = False self._board: Optional[Board] = None self._color: Optional[Color] = color self.name = name def __str__(self): if self.name: return self.name else: return self.__repr__() def __repr__(self): return f"<{self.__class__.__name__} color={self._color} board={self._board}>" def _initiate(self, board: Board): self._in_game = True self._board = board def _clear_state(self): self._in_game = False self._board = None self._color = None @property def is_in_game(self) -> bool: """Check if the player is currently linked to a board""" return self._in_game @property def color(self) -> Optional[Color]: """Returns the color of the player if any""" return self._color @property def board(self) -> Optional[Board]: """Returns the associated board if any""" return self._board
[docs] @in_game def get_board_matrix(self) -> np.ndarray: """Returns the current state of the board (0 for empty, 1 for the player, -1 for the opponent)""" return self._board.matrix()
[docs] @in_game def playable_moves(self) -> list[tuple[int, int]]: """Returns the list of all vertices available for playing""" return self._board.playable_moves(self._color)
[docs] @in_game def my_vertices(self) -> list[tuple[int, int]]: """Returns a list of all vertices owned by the player""" return self._board.vertices(self._color)
[docs] @in_game def get_vertices(self, color: Color) -> list[tuple[int, int]]: """Returns a list of all vertices owned by the opponent""" return self._board.vertices(color)
[docs] @in_game def free_vertices(self) -> list[tuple[int, int]]: """Returns a list of all empty vertices on the board""" return self._board.vertices(Color.Empty)
[docs] @in_game def my_territories(self) -> list[Territory]: """Returns a list of territories owned by the player""" return self._board.territories(self._color)
[docs] @in_game def get_territories(self, color: Color) -> list[Territory]: """Returns a list of territories owned by the opponent""" return self._board.territories(color)
[docs] @in_game def territories(self) -> list[Territory]: """Returns all territories on the board""" return self._board.territories()
[docs] @abstractmethod def play(self) -> Optional[tuple[int, int]]: """This method has to be overridden by subclasses It's called when the player has to play and must return a 2-tuple (x, y) representing a move, or None for skipping the turn""" pass