Source code for texasholdem.game.move

"""
The move module includes classes related to collections of moves
"""
import random
from typing import Dict, Tuple, Optional, Union, List
from collections.abc import Sequence
import warnings

from deprecated.sphinx import versionadded

from texasholdem.game.action_type import ActionType


[docs] @versionadded(version="0.9.0") class MoveIterator(Sequence): """ Arguments: moves (Dict[ActionType, Optional[range]): a dictionary from ActionType to Optional[range] where most of the values will be None with the ActionType.RAISE action having a range as a value. """ def __init__(self, moves: Dict[ActionType, Optional[range]]): self._raise_range = range(0) if ActionType.RAISE in moves: self._raise_range = moves[ActionType.RAISE] self._action_types = list( sorted(moves.keys(), key=tuple(ActionType).index, reverse=True) ) def __contains__(self, item) -> bool: if isinstance(item, ActionType): return item in self._action_types if isinstance(item, Tuple): action, maybe_val = item if not isinstance(action, ActionType): return False if action == ActionType.RAISE: if isinstance(maybe_val, float) and not maybe_val.is_integer(): warnings.warn("An integer was expected for value, got a float.") return False if isinstance(maybe_val, int) or ( isinstance(maybe_val, float) and maybe_val.is_integer() ): return maybe_val in self._raise_range if isinstance(item, int): return super().__contains__(item) return False def __len__(self) -> int: return len(self._action_types) + len(self._raise_range) - 1 def __getitem__(self, item: int) -> ActionType: if item < len(self._action_types) - 1: return self._action_types[item], None if not self._raise_range: raise IndexError if item < len(self): return ActionType.RAISE, self._raise_range[item - len(self._action_types)] raise IndexError def __delitem__(self, key) -> None: if isinstance(key, ActionType): if key in self._action_types: self._action_types.__delitem__(key) elif key == ActionType.RAISE: if key not in self._raise_range: raise KeyError self._raise_range = range(0) raise KeyError def __repr__(self) -> str: move_dict = {move: None for move in self._action_types} if self._raise_range: move_dict[ActionType.RAISE] = self._raise_range return self.__class__.__name__ + f"({repr(move_dict)})" def __str__(self) -> str: return repr(self) @property def action_types(self) -> List[ActionType]: """ Returns: List[ActionType]: A list of action types represented """ return self._action_types @property def raise_range(self) -> range: """ The range of the represented raise action, if no raise is possible this is just range(0) Returns: range: The range of the represented raise action. """ return self._raise_range
[docs] def sample( self, num=1 ) -> Union[ Tuple[ActionType, Optional[int]], List[Tuple[ActionType, Optional[int]]] ]: """ Arguments: num (int): The number of samples Returns: Union[Tuple[ActionType, Optional[int]], List[Tuple[ActionType, Optional[int]]]]: The sample(s) of action, total tuples """ action_types = random.choices(self.action_types, k=num) if ActionType.RAISE in self: totals = random.choices(self.raise_range, k=num) totals = [ totals[i] if action_types[i] == ActionType.RAISE else None for i in range(num) ] else: totals = [None for _ in range(num)] samples = list(zip(action_types, totals)) if num == 1: return samples[0] return samples