def __end_taki_with_no_color_actions(self, taki_card, taki_combinations, no_color_cards): """ Add no color cards to the end of every possible open taki move. :param current_subset: list of every possible open taki move :param no_color_cards: list of special cards with no color from current player's hand :return: list of actions of open taki moves that ends with no color card. """ actions = [] change_color_indices = [ i for i in range(len(no_color_cards)) if no_color_cards[i].is_change_color() ] for index in change_color_indices: # add every possible color for change color action actions.extend([ Action([taki_card] + s + [no_color_cards[index]], no_op=False, change_color=color) for color in Color if color is not Color.NO_COLOR for s in taki_combinations ]) if len(change_color_indices) < len(no_color_cards): # add other no color cards actions.extend([ Action([taki_card] + s + [special_card]) for special_card in no_color_cards if not special_card.is_change_color() for s in taki_combinations ]) return actions
def get_legal_actions(self, player_cards, card_on_top_of_pile=None, active_color=None, include_draw=True): """ :param player_cards: :return: """ if not card_on_top_of_pile: card_on_top_of_pile = self.game.get_pile()[-1] if not active_color: active_color = self.game.active_color if include_draw: legal_actions = [Action([], no_op=True)] # draw card action else: legal_actions = [] if self.__active_plus_2(card_on_top_of_pile): # only king or plus 2 cards can answer to active plus 2 legal_actions.extend(self.__search_for_plus_2(player_cards)) legal_actions.extend(self.__search_for_king(player_cards)) return sorted(list(set(legal_actions)), key=lambda x: len(x.get_cards())) legal_actions.extend( self.__search_color_cards(player_cards, active_color)) legal_actions.extend( self.__search_same_value_cards(player_cards, card_on_top_of_pile)) legal_actions.extend(self.__add_no_color_actions(player_cards)) # add another turn options for plus or king actions and for stop action with 2 players game legal_actions.extend( self.__add_another_turn_actions(player_cards, legal_actions)) return sorted(list(set(legal_actions)), key=lambda x: len(x.get_cards()))
def __add_no_color_actions(self, player_cards): """ Generates all possible no color moves from given player's cards. :param player_cards: current player's cards. :return: list of all possible no color actions from the given cards. """ no_color_actions = [] no_color_cards = [ card for card in player_cards if card.get_color() is Color.NO_COLOR ] for card in no_color_cards: if card.is_change_color(): no_color_actions.extend([ Action([card], no_op=False, change_color=other_color) for other_color in Color if other_color is not Color.NO_COLOR ]) else: no_color_actions.extend([Action([card])]) return no_color_actions
def __generate_taki_card_moves(self, player_cards, color): """ Generates every possible open taki move from the given cards and color. :param player_cards: current player's hand. :param color: color for open taki move. :return: list of every possible open taki move from the given cards and color. """ if color is Color.NO_COLOR: current_color_cards = [ card for card in player_cards if card.get_color() is self.game.active_color and not card.is_taki_card(color) ] else: current_color_cards = [ card for card in player_cards if card.get_color() is color and not card.is_taki_card(color) ] taki_cards = [ card for card in player_cards if card.is_taki_card(color) ] no_color_cards = [ card for card in player_cards if card.get_color() is Color.NO_COLOR and not card.is_taki_card(Color.NO_COLOR) ] subsets = [] for i in range(len(taki_cards)): relevent_taki_sets = [ sorted(list(s)) for s in self.__subsets_comb(current_color_cards) ] # get all sets # change only the last card in each taki set and sort the rest to avoid redundancy taki_combinations = [ s[:i] + s[i + 1:] + [s[i]] for s in relevent_taki_sets for i in range(len(s)) ] current_subset = [ Action([taki_cards[i]] + s) for s in taki_combinations ] # add the taki card subsets.extend(current_subset) # open taki in any color can end with no color card, add those options to every existing option subsets.extend( self.__end_taki_with_no_color_actions(taki_cards[i], relevent_taki_sets, no_color_cards)) return subsets
def __search_same_value_cards(self, player_cards, active_card): """ Generates every possible move from the given player's cards and the active card value. :param player_cards: current player's hand. :param active_card: top of the pile card. :return: list of all possible actions from the given cards and the active card value. """ possible_actions = [] if active_card.is_taki_card(active_card.get_color()): # add all possible open taki moves for other_color in Color: if other_color is not active_card.get_color(): possible_actions.extend( self.__generate_taki_card_moves( player_cards, other_color)) else: possible_actions.extend([ Action([card]) for card in player_cards if card.get_value() is active_card.get_value() ]) return possible_actions
def __search_color_cards(self, player_cards, color): """ Generates every possible move from the given cards and color. :param player_cards: current player's hand. :param color: color for taki move. :return: list of all possible actions from the given cards and oolor. """ if color is Color.NO_COLOR: possible_actions = [] for other_color in Color: if other_color is not Color.NO_COLOR: # prevent infinite loop, add all possible options from other colors possible_actions.extend( self.__search_color_cards(player_cards, other_color)) else: possible_actions = [ Action([card]) for card in player_cards if card.get_color() is color ] possible_actions.extend( self.__generate_taki_card_moves(player_cards, color)) return possible_actions
def __search_for_plus_2(self, player_cards): return [Action([card]) for card in player_cards if card.is_plus_2()]
def __search_for_king(self, player_cards): return [Action([card]) for card in player_cards if card.is_king()]