Source code for core.game

import re
from typing import Final, Optional
from core.enums import PlayerColor, BugType, Direction

[docs] class Position: """ Tile position. """ def __init__(self, q: int, r: int): self.q: Final[int] = q self.r: Final[int] = r def __str__(self) -> str: return f"({self.q}, {self.r})" def __repr__(self): return self.__str__() def __hash__(self) -> int: return hash((self.q, self.r)) def __eq__(self, value: object) -> bool: return self is value or isinstance(value, Position) and self.q == value.q and self.r == value.r def __add__(self, other: object): return Position(self.q + other.q, self.r + other.r) if isinstance(other, Position) else NotImplemented def __sub__(self, other: object): return Position(self.q - other.q, self.r - other.r) if isinstance(other, Position) else NotImplemented
[docs] def clockwise(self): """ Rotate the position 60 degrees clockwise. :return: New rotated position. :rtype: Position """ return Position(-self.r, self.q + self.r)
[docs] def anticlockwise(self): """ Rotate the position 60 degrees anticlockwise. :return: New rotated position. :rtype: Position """ return Position(self.q + self.r, -self.q)
[docs] class Bug: """ Bug piece. """ COLORS: Final[dict[str, PlayerColor]] = {color.code: color for color in PlayerColor} """ Color code map. """ REGEX: Final[str] = f"({"|".join(COLORS.keys())})({"|".join(BugType)})(1|2|3)?" """ Regex to validate BugStrings. """
[docs] @classmethod def parse(cls, bug: str): """ Parses a BugString. :param bug: BugString. :type bug: str :raises ValueError: If it's not a valid BugString. :return: Bug piece. :rtype: Bug """ if (match := re.fullmatch(Bug.REGEX, bug)): color, bug_type, bug_id = match.groups() return Bug(Bug.COLORS[color], BugType(bug_type), int(bug_id or 0)) raise ValueError(f"'{bug}' is not a valid BugString")
def __init__(self, color: PlayerColor, bug_type: BugType, bug_id: int = 0) -> None: self.color: Final[PlayerColor] = color self.type: Final[BugType] = bug_type self.id: Final[int] = bug_id def __str__(self) -> str: return f"{self.color.code}{self.type}{self.id if self.id else ""}" def __repr__(self): return self.__str__() def __hash__(self) -> int: return hash(str(self)) def __eq__(self, value: object) -> bool: return self is value or isinstance(value, Bug) and self.color is value.color and self.type is value.type and self.id == value.id
[docs] class Move: """ Move. """ PASS: Final[str] = "pass" """ Pass move. """ REGEX = f"({Bug.REGEX})( ?({"|".join(f"\\{d}" for d in Direction.lefts())})?({Bug.REGEX})({"|".join(f"\\{d}" for d in Direction.rights())})?)?" """ MoveString regex. """
[docs] @classmethod def stringify(cls, moved: Bug, relative: Optional[Bug] = None, direction: Optional[Direction] = None) -> str: """ Converts the data for a move to the corresponding MoveString. :param moved: Bug piece moved. :type moved: Bug :param relative: Bug piece relative to which the other bug piece is moved, defaults to `None`. :type relative: Optional[Bug], optional :param direction: Direction of the destination tile with respect to the relative bug piece, defaults to `None`. :type direction: Optional[Direction], optional :return: MoveString. :rtype: str """ return f"{moved} {direction if direction and direction.is_left else ""}{relative}{direction if direction and direction.is_right else ""}" if relative else f"{moved}"
def __init__(self, bug: Bug, origin: Optional[Position], destination: Position) -> None: self.bug: Final[Bug] = bug self.origin: Final[Optional[Position]] = origin self.destination: Final[Position] = destination def __str__(self) -> str: return f"<{self.origin}, {self.bug}, {self.destination}>" def __repr__(self): return self.__str__() def __hash__(self) -> int: return hash((self.bug, self.origin, self.destination)) def __eq__(self, value: object) -> bool: return self is value or isinstance(value, Move) and self.bug == value.bug and self.origin == value.origin and self.destination == value.destination