def __init__(self, player_from, player_to, trick): check_param(player_to in range(4) and ((player_from+1)% 4 == player_to or (player_from-1)% 4 == player_to), param=(player_from, player_to)) check_isinstance(trick, Trick) check_param(Card.DRAGON is trick.last_combination.card) super().__init__(player_pos=player_from) self._trick = trick self._to = player_to
def __init__(self, straight): check_isinstance(straight, Straight) check_true(len({ c.suit for c in straight }) == 1) # only one suit (takes also care of the phoenix) super().__init__(straight.cards) self._height = straight.height + 1000 # 1000 to make sure it is higher than any other non straightbomb
def __init__(self, player_pos, trick): """ :param player_pos: the player winning the trick :param trick: The won trick """ check_isinstance(trick, Trick) super().__init__(player_pos=player_pos) self._trick = trick
def __init__(self, player_pos, trick, hand_cards): """ :param player_pos: :param hand_cards: The HandCardSnapshot of the players when the trick finished """ from .handcardsnapshot import HandCardSnapshot check_isinstance(hand_cards, HandCardSnapshot) super().__init__(player_pos=player_pos, trick=trick) self._hand_cards = hand_cards
def merge(self, combs, target_comb): """ :param combs: the combinations that merged :param target_comb: the combination resulting from the merge :return: Returns a Partition with combs removed and the target added """ check_isinstance(target_comb, Combination) return Partition( self._combs.difference(set(combs)).union({target_comb}))
def __init__(self, team1, team2, winner_team, points, target_points, rounds): check_isinstance(team1, Team) check_isinstance(team2, Team) check_isinstance(winner_team, Team) check_isinstance(points, tuple) check_param(len(points) == 2) check_isinstance(target_points, int) check_all_isinstance(rounds, RoundHistory) check_param(len(rounds) > 0) super().__init__()
def __init__(self, pair, trio): check_isinstance(pair, Pair) check_param(trio, Trio) check_param( not (pair.contains_phoenix() and trio.contains_phoenix())) # phoenix can only be used once cards = set(pair.cards + trio.cards) check_param(len(cards) == 5, param=(pair, trio)) super().__init__(cards) self._height = trio.height self._pair = pair self._trio = trio
def __lt__(self, other): if isinstance(other, Bomb): return True check_isinstance(other, Single) check_true(self.card is not Card.DOG and other.card is not Card.DOG, ex=TypeError, msg="Can't compare") # dog can't be compared if self.card is Card.DRAGON: return False # dragon is the highest single card if other.is_phoenix() and other.height == Card.PHOENIX.card_height: return True # if the phoenix is on the right hand side of '<' and its value has not been changed, return True return self.height < other.height
def search(self, start_state): check_isinstance(start_state, MctsState) if start_state not in self: _ = self.clear() self.add_root(start_state) iteration = 0 while not self.is_end_search(iteration): iteration += 1 leaf_states = self._tree_policy(start_state) for ls in leaf_states*self._nbr_rollouts: rollout_result, final_state = self._rollout_policy(ls) self.backup(ls, rollout_result) action = self.best_action(start_state) return action
def set_phoenix_height(self, newheight): """ Set the height of tis single to the given height ONLY IF the Phoenix is the card of this single. Otherwise the call is ignored and a warning is printed. :param newheight: :return: the height of the single after this call """ check_isinstance(newheight, (int, float)) check_param( newheight == Card.PHOENIX.card_height or 2 <= newheight < 15, param=newheight) # newheight must be between 2 and 14 (TWO and As) if self._card is Card.PHOENIX: self._height = newheight # else: # warnings.warn("Tried to set the height of a non-phoenix single. The height was not set.") return self.height
def __init__(self, initial_points): check_param(len(initial_points) == 2) check_isinstance(initial_points, tuple) self._initial_points = initial_points self._points = initial_points empty_hcs = HandCardSnapshot(ImmutableCards([]), ImmutableCards([]), ImmutableCards([]), ImmutableCards([])) self._grand_tichu_hands = empty_hcs # A HandCardSnapshot (initially all hands are empty) self._before_swap_hands = empty_hcs # A HandCardSnapshot (initially all hands are empty) self._swap_actions = set() self._complete_hands = empty_hcs # A HandCardSnapshot (initially all hands are empty) self._announced_grand_tichus = set() self._announced_tichus = set() self._tricks = list() self._current_trick = UnfinishedTrick() self._handcards = list() self._ranking = list() self._events = list()
def __init__(self, parent, state=None, initial_reward_ratio=float("inf")): """ :param parent: MonteCarloTreeNode; The parent node of this None :param state: MctsState of this none :param initial_reward_ratio: The initial reward ratio (when the node was not yet visited) """ check_isinstance(state, MctsState) parent is None or check_isinstance(parent, MonteCarloTreeNode) super().__init__(parent=parent, data=state) self._visited_count = 0 self._reward_count = 0 self._reward_ratio = self._reward_count / self._visited_count if self._visited_count != 0 else initial_reward_ratio self._possible_actions = set(state.possible_actions()) assert check_all_isinstance(self._possible_actions, PlayerAction) self._expanded_actions = set() self._remaining_actions = list(self._possible_actions)
def __init__(self, cards, phoenix_as=None): check_param(len(cards) >= 5) if Card.PHOENIX in cards: check_isinstance(phoenix_as, Card) check_param(phoenix_as not in cards, param=(phoenix_as, cards)) check_param(phoenix_as.suit is not CardSuit.SPECIAL, param=phoenix_as) cards_phoenix_replaced = [c for c in cards if c is not Card.PHOENIX ] + [phoenix_as] if phoenix_as else cards check_param( len({c.card_value for c in cards_phoenix_replaced }) == len(cards_phoenix_replaced)) # different card values cardheights = [c.card_height for c in cards_phoenix_replaced] check_param( max(cardheights) - min(cardheights) + 1 == len(cards_phoenix_replaced)) # cards are consecutive super().__init__(cards) self._height = max(cardheights) self._ph_as = phoenix_as
def play_combination(self, game_history, wish): """ Called by the the tichu manager to request a move. :param game_history: The history of the tichu game so far. :param wish: The CardValue beeing wished, None if no wish is present :return: pass, or the combination the players wants to play as CombinationAction or PassAction. """ assert len(self._hand_cards) > 0 action = self._agent.play_combination(wish=wish, round_history=game_history.current_round.build()) check_isinstance(action, (CombinationAction, PassAction)) check_true(action.player_pos == self._position) with ignored(AttributeError, ValueError): action.combination.set_phoenix_height(game_history.current_round.last_combination.height + 0.5) action.check(played_on=game_history.current_round.last_combination, has_cards=self) TichuPlayer._check_wish(game_history.current_round.last_combination, action, self.hand_cards, wish) if isinstance(action, CombinationAction): self._hand_cards.remove_all(action.combination.cards) self._update_agent_handcards() return action
def _append_round(self, round_history): check_isinstance(round_history, RoundHistory) self._rounds.append(round_history)
def team2(self, team): check_isinstance(team, Team) self._team2 = team
def winner_team(self, team): check_isinstance(team, Team) self._winner_team = team
def wish(self, val): check_isinstance(val, CardValue) self._wish = val
def trick_on_table(self, val): if isinstance(val, Trick): self._trick_on_table = UnfinishedTrick.from_trick(val) else: check_isinstance(val, UnfinishedTrick) self._trick_on_table = val.copy()
def __add__(self, other): check_isinstance(other, ImmutableCards) return ImmutableCards(self._cards.union(other._cards))
def complete_hands(self, hands): check_isinstance(hands, HandCardSnapshot) self._complete_hands = hands
def grand_tichu_hands(self, hands): check_isinstance(hands, HandCardSnapshot) self._grand_tichu_hands = hands
def __lt__(self, other): check_isinstance(other, (type(self), Bomb), msg="Can't compare") return self.height < other.height
def __init__(self, parent, data=None): # assert action is None or isinstance(action, PlayerAction), f"action: {action}" parent is None or check_isinstance(parent, GameTreeNode) self._parent = parent # the parent node (None for root) self._data = data # any object self._children = set()
def points(self, points): check_isinstance(points, tuple) check_param(len(points) == 2) check_all_isinstance(points, int) self._points = points
def __init__(self, initial_points, final_points, points, grand_tichu_hands, before_swap_hands, card_swaps, complete_hands, announced_grand_tichus, announced_tichus, tricks, handcards, ranking, events): check_isinstance(initial_points, tuple) check_isinstance(final_points, tuple) check_isinstance(points, tuple) check_param( len(initial_points) == len(final_points) == len(points) == 2) check_all_isinstance( [grand_tichu_hands, before_swap_hands, complete_hands], HandCardSnapshot) if card_swaps != frozenset(): check_isinstance(card_swaps, frozenset) check_all_isinstance(card_swaps, SwapCardAction) check_param(len(card_swaps) == 12, param=card_swaps) check_param(len({sca.player_pos for sca in card_swaps}) == 4) check_param(len({sca.to for sca in card_swaps}) == 4) check_isinstance(announced_grand_tichus, frozenset) check_isinstance(announced_tichus, frozenset) check_all_isinstance(tricks, Trick) check_all_isinstance(handcards, HandCardSnapshot) check_param(len(tricks) == len(handcards)) check_isinstance(ranking, tuple) check_param(len(ranking) <= 4) check_isinstance(events, tuple) check_all_isinstance(events, GameEvent) super().__init__()
def before_swap_hands(self, hands): check_isinstance(hands, HandCardSnapshot) self._before_swap_hands = hands
def hand_cards(self, val): check_isinstance(val, HandCardSnapshot) self._hand_cards = val
def append_event(self, event): check_isinstance(event, GameEvent) self._handle_event(event) self._events.append(event)
def add_won_trick(self, pos, trick): check_isinstance(trick, Trick) self._won_tricks[pos].append(trick)