"""
Module for handling game over events.
"""
from dataclasses import dataclass
from enum import Enum
import chess
[docs]class HowOver(Enum):
"""Represents the possible outcomes of a game.
Attributes:
WIN (int): Indicates a win.
DRAW (int): Indicates a draw.
DO_NOT_KNOW_OVER (int): Indicates that the outcome is unknown.
"""
WIN = 1
DRAW = 2
DO_NOT_KNOW_OVER = 3
[docs]class Winner(Enum):
"""Represents the winner of a chess game.
Args:
Enum: The base class for enumeration types.
Attributes:
WHITE (Winner): Represents the winner as white.
BLACK (Winner): Represents the winner as black.
NO_KNOWN_WINNER (Winner): Represents the absence of a known winner.
Methods:
is_none() -> bool: Checks if the winner is None.
is_white() -> bool: Checks if the winner is white.
is_black() -> bool: Checks if the winner is black.
"""
WHITE = chess.WHITE
BLACK = chess.BLACK
NO_KNOWN_WINNER = None
[docs] def is_none(self) -> bool:
"""Check if the winner is None.
Returns:
bool: True if the winner is None, False otherwise.
"""
return self is None
[docs] def is_white(self) -> bool:
"""Check if the winner is white.
Returns:
bool: True if the winner is white, False otherwise.
"""
is_white_bool: bool
if not self.is_none():
is_white_bool = bool(self) is chess.WHITE
else:
is_white_bool = False
return is_white_bool
[docs] def is_black(self) -> bool:
"""Check if the winner is black.
Returns:
bool: True if the winner is black, False otherwise.
"""
is_black_bool: bool
if not self.is_none():
is_black_bool = bool(self) is chess.BLACK
else:
is_black_bool = False
return is_black_bool
[docs]@dataclass(slots=True)
class OverEvent:
"""Represents an event that indicates the end of a game.
Attributes:
how_over (HowOver): The way the game ended.
who_is_winner (Winner): The winner of the game.
Raises:
AssertionError: If the `how_over` attribute is not a valid value from the `HowOver` enum.
AssertionError: If the `who_is_winner` attribute is not a valid value from the `Winner` enum.
Exception: If the winner is not properly defined.
Methods:
__post_init__: Performs additional initialization after the object is created.
becomes_over: Sets the `how_over` and `who_is_winner` attributes.
get_over_tag: Returns a tag string used in databases.
__bool__: Raises an exception.
is_over: Checks if the game is over.
is_win: Checks if the game ended with a win.
is_draw: Checks if the game ended with a draw.
is_winner: Checks if the specified player is the winner.
print_info: Prints information about the `OverEvent` object.
test: Performs tests on the `OverEvent` object.
"""
how_over: HowOver = HowOver.DO_NOT_KNOW_OVER
who_is_winner: Winner = Winner.NO_KNOWN_WINNER
termination: chess.Termination | None = None
[docs] def __post_init__(self) -> None:
assert self.how_over in HowOver
assert self.who_is_winner in Winner
if self.how_over == HowOver.WIN:
assert (
self.who_is_winner is Winner.WHITE or self.who_is_winner is Winner.BLACK
)
elif self.how_over == HowOver.DRAW:
assert self.who_is_winner is Winner.NO_KNOWN_WINNER
[docs] def becomes_over(
self,
how_over: HowOver,
termination: chess.Termination | None,
who_is_winner: Winner = Winner.NO_KNOWN_WINNER,
) -> None:
"""Sets the `how_over` and `who_is_winner` attributes.
Args:
how_over (HowOver): The way the game ended.
who_is_winner (Winner, optional): The winner of the game. Defaults to `Winner.NO_KNOWN_WINNER`.
"""
self.how_over = how_over
self.who_is_winner = who_is_winner
self.termination = termination
[docs] def get_over_tag(self) -> OverTags:
"""Returns a tag string used in databases.
Returns:
OverTags: The tag string representing the game outcome.
Raises:
Exception: If the winner is not properly defined.
"""
over_tag: OverTags
if self.how_over == HowOver.WIN:
if self.who_is_winner.is_white():
over_tag = OverTags.TAG_WIN_WHITE
elif self.who_is_winner.is_black():
over_tag = OverTags.TAG_WIN_BLACK
else:
raise ValueError("error: winner is not properly defined.")
elif self.how_over == HowOver.DRAW:
over_tag = OverTags.TAG_DRAW
elif self.how_over == HowOver.DO_NOT_KNOW_OVER:
over_tag = OverTags.TAG_DO_NOT_KNOW
else:
raise ValueError("error: over is not properly defined.")
return over_tag
[docs] def __bool__(self) -> None:
"""Raises an exception.
Raises:
Exception: Always raises an exception.
"""
raise ValueError("Nooooooooooo in over ebvent.py")
[docs] def is_over(self) -> bool:
"""Checks if the game is over.
Returns:
bool: True if the game is over, False otherwise.
"""
return self.how_over in {HowOver.WIN, HowOver.DRAW}
[docs] def is_win(self) -> bool:
"""Checks if the game ended with a win.
Returns:
bool: True if the game ended with a win, False otherwise.
"""
return self.how_over == HowOver.WIN
[docs] def is_draw(self) -> bool:
"""Checks if the game ended with a draw.
Returns:
bool: True if the game ended with a draw, False otherwise.
"""
return self.how_over == HowOver.DRAW
[docs] def is_winner(self, player: chess.Color) -> bool:
"""Checks if the specified player is the winner.
Args:
player (chess.Color): The player to check.
Returns:
bool: True if the specified player is the winner, False otherwise.
Raises:
AssertionError: If the `player` argument is not a valid value from the `chess.Color` enum.
"""
assert player in {chess.WHITE, chess.BLACK}
is_winner: bool
if self.how_over == HowOver.WIN:
is_winner = bool(
self.who_is_winner == Winner.WHITE
and player == chess.WHITE
or self.who_is_winner == Winner.BLACK
and player == chess.BLACK
)
else:
is_winner = False
return is_winner
[docs] def print_info(self) -> None:
"""Prints information about the `OverEvent` object."""
print(
"over_event:",
"how_over:",
self.how_over,
"who_is_winner:",
self.who_is_winner,
)
[docs] def test(self) -> None:
"""Performs tests on the `OverEvent` object."""
if self.how_over == HowOver.WIN:
assert self.who_is_winner is not None
assert self.who_is_winner.is_white() or self.who_is_winner.is_black()
if self.how_over == HowOver.DRAW:
assert self.who_is_winner is None