Exemplo n.º 1
0
    def find_multiple(cards: Cards, level_to_beat: int, cards_to_find: int):
        """
        :param cards:
        :param level_to_beat:
        :param cards_to_find:
        :rtype: Combination
        """

        if cards_to_find <= 0 or cards_to_find > 4:
            raise ValueError('Illegal combination_type %s' % cards_to_find)

        if cards_to_find == 1:
            for card in (cards - Phoenix()).cards:
                if card.power > level_to_beat:
                    return Combination(cards_list=[card])

            # if no card could have been player, try to take the lead with your Phoenix
            # Phoenix can not be played on a Dragon
            if cards.phoenix_flag and level_to_beat < Dragon().power:
                return Combination(cards_list=[Phoenix()])

        # TODO - TO REFACTOR WITH LOGIC
        if cards_to_find == 2:
            for i in range(len(cards.cards) - 1):
                card = cards.cards[i]
                if card.power > level_to_beat and card.power == cards.cards[
                        i + 1].power:
                    return Cards(cards_list=[card, cards.cards[i + 1]])

        if cards_to_find == 3:
            for i in range(len(cards.cards) - 2):
                card = cards.cards[i]
                if card.power > level_to_beat and card.power == cards.cards[
                        i + 2].power:
                    return Cards(cards_list=[
                        card, cards.cards[i + 1], cards.cards[i + 2]
                    ])

        if cards_to_find == 4:
            for i in range(len(cards.cards) - 3):
                card = cards.cards[i]
                if card.power > level_to_beat and card.power == cards.cards[
                        i + 3].power:
                    return Cards(cards_list=[
                        card, cards.cards[i +
                                          1], cards.cards[i +
                                                          2], cards.cards[i +
                                                                          3]
                    ])

        # If no combination found, try to use Phoenix to play
        if cards.phoenix_flag and 1 <= cards_to_find < 4 and cards.size > 1:
            return Hand.find_multiple(cards - Phoenix(), level_to_beat,
                                      cards_to_find - 1) + Phoenix()
Exemplo n.º 2
0
    def find_straight(cards, level_to_beat, length=None, bomb=False):
        """
        1/ Start at level_to_beat - length +2:
        if level_to_beat is 10, length 6, their straight starts at 5, your straight has to start at 6
        2/ see if you can find a straight that beats that
        3/ see if you can find a length-1 straight at level_to_beat -1
        """
        # Get all possible start points for the straight
        if length is None:
            length = 5
        elif length <= 0:
            return None

        start_point = max(1, level_to_beat - length + 2)
        max_strength_power = Dragon().power - 1
        max_start_point = max_strength_power - length + 2
        start_points = range(start_point, max_start_point + 1)

        for card in cards.cards:
            for start in start_points:
                if card.power == start:
                    if length == 1:
                        return Cards(cards_list=[card])
                    else:
                        # TODO - jump in straights
                        # Issue constantly increasing threshold
                        rest = Hand.find_straight(cards - card,
                                                  card.power + length - 2,
                                                  length - 1,
                                                  bomb=bomb)

                        # TODO BOMB
                        if rest:
                            if not rest.phoenix_flag:
                                if min(rest.cards).power == card.power + 1:
                                    return rest + card
                            elif (len(rest.cards) == 1
                                  and Phoenix() in rest.cards) or min(
                                      (rest - Phoenix()
                                       ).cards).power <= card.power + 2:
                                return rest + card

        if cards.phoenix_flag:
            if length == 1:
                return Cards(cards_list=[Phoenix()])

            rest = Hand.find_straight(cards - Phoenix(),
                                      level_to_beat,
                                      length - 1,
                                      bomb=bomb)
            if rest:
                return rest + Phoenix()
Exemplo n.º 3
0
    def find_all_multiples(cards: Cards, multiple: int):
        cards = cards - Dog() - Dragon()
        buckets = Cards.bucketize_hands(cards.cards)
        multiples = []
        for level in range(Mahjong().power + 1, Dragon().power):
            cards_this_level = buckets[level]
            if (Phoenix().power in buckets.keys()) and (multiple != 4):
                cards_this_level.append(Phoenix())
            if len(cards_this_level) > 1:
                for pair in itertools.combinations(cards_this_level, multiple):
                    multiples.append(Combination(cards_list=list(pair)))

        return multiples
Exemplo n.º 4
0
    def __init__(self,
                 cards_list: list = None,
                 cards_dict_list: list = None,
                 cards_string: str = None):
        # Get phoenix, get type, get level
        new_cards_list = None
        if cards_string is not None:
            new_cards_list = self.parse_string(cards_string)

        if cards_dict_list is not None:
            new_cards_list = [
                Card(card_dict=card_dict) for card_dict in cards_dict_list
            ]

        if new_cards_list is not None:
            Cards.__init__(self, cards_list=new_cards_list)
            return

        # TODO - Should we break on empty cards list
        # if cards_list is None or len(cards_list) == 0:
        #     raise ValueError('Empty cards list')

        # Check that we do not have duplicates

        if len(set(cards_list)) != len(cards_list):
            raise ValueError('duplicated cards')

        cards_list.sort()
        self.cards = cards_list
        self.size = len(cards_list)
        self.phoenix_flag = Phoenix() in self.cards
Exemplo n.º 5
0
    def get_type(self):
        phoenixless_combination = [card for card in self.cards if card != Phoenix()]
        combination = [card for card in self.cards]
        phoenixless_combination_size = len(phoenixless_combination)

        if phoenixless_combination_size == 0:
            self.type = 'SINGLE'
            return

        if Dog() in phoenixless_combination and len(combination) > 1:
            raise ValueError('Dog is played alone')

        if Dragon() in phoenixless_combination and len(combination) > 1:
            raise ValueError('Dragon is played alone')

        if Mahjong() in phoenixless_combination and len(combination) == 2 and self.phoenix_flag:
            raise ValueError('No pairs with Mahjong')

        distinct_values = list(set([card.power for card in phoenixless_combination]))
        number_of_values_except_ph = len(distinct_values)

        distinct_suits = list(set([card.suit for card in phoenixless_combination]))
        number_of_suits = len(distinct_suits)

        value_span = max(distinct_values) - min(distinct_values) + 1

        if number_of_values_except_ph == 1:

            if phoenixless_combination_size == 1:
                if not self.phoenix_flag:
                    self.type = 'SINGLE'
                else:
                    self.type = 'PAIR'
                    self.get_phoenix().set_power(max(distinct_values))
                return

            if phoenixless_combination_size == 2:
                if not self.phoenix_flag:
                    self.type = 'PAIR'
                else:
                    self.type = 'TRIO'
                    self.get_phoenix().set_power(max(distinct_values))
                return

            if phoenixless_combination_size == 3:
                self.type = 'TRIO'
                return

            if phoenixless_combination_size == 4 and not self.phoenix_flag:
                self.type = 'SQUAREBOMB'
                return

        elif phoenixless_combination_size == number_of_values_except_ph and len(combination) >= 5:
            if self.phoenix_flag:
                if value_span == phoenixless_combination_size:
                    self.type = 'STRAIGHT'
                    self.get_phoenix().set_power(max(distinct_values) + 1)
                    return
                elif value_span == phoenixless_combination_size + 1:
                    # it is a straight with the phoenix in the middle
                    self.type = 'STRAIGHT'
                    # Not assigning level because of no interest
                    return
                else:
                    raise ValueError('Incoherent Straight')
            if not self.phoenix_flag:
                if value_span != phoenixless_combination_size:
                    raise ValueError('Incoherent Straight')
                if number_of_suits == 1:
                    self.type = 'STRAIGHTBOMB'
                    return
                else:
                    self.type = 'STRAIGHT'
                    return

        # STEPS AND FULLHOUSE
        elif phoenixless_combination_size / 2 == number_of_values_except_ph:
            if self.phoenix_flag and phoenixless_combination_size == 4:
                self.type = 'FULLHOUSE'
                # Not assigning level because of no interest
                return

            elif value_span == phoenixless_combination_size / 2:
                self.type = 'STEPS'
                return
        # TODO [Phoenix, 2_Pa, 3_Pa, 4_Pa, 5_Pa, 5_Sw, 5_Ja, 5_St] not working
        elif value_span == phoenixless_combination_size // 2 + 1 and phoenixless_combination_size % 2 == 1 and self.phoenix_flag:
            self.type = 'STEPS'
            # Not assigning level because of no interest
            return

        elif number_of_values_except_ph == 2 and phoenixless_combination_size == 5 and not self.phoenix_flag:
            self.type = 'FULLHOUSE'
            return

        raise ValueError('Unknown Combination %s' % self)
Exemplo n.º 6
0
    def test_pairs_with_phoenix(self):

        cards = [Card(name='2', suit='Pagoda'), Phoenix()]
        combination = Combination(cards_list=cards)
        self.assertEqual(combination.type, 'PAIR')
        self.assertEqual(combination.level, 2)
Exemplo n.º 7
0
    Card(name='5', suit='Jade'),
    Card(name='5', suit='Star'),
    # Card(name='4', suit='Pagoda'),
    # Card(name='4', suit='Star'),
    # Card(name='5', suit='Star'),
    # Card(name='5', suit='Jade'),
    # Card(name='5', suit='Pagoda'),
    # Card(name='5', suit='Sword'),
    # Card(name='7', suit='Star'),
    # Card(name='8', suit='Star'),
    # Card(name='6', suit='Star'),
    # Card(name='9', suit='Star'),
    # Card(name='4', suit='Star'),
    # Card(name='4', suit='Pagoda'),
    # Card(name='4', suit='Pagoda'),
    Phoenix(),
    # Dog(),
    # Mahjong(),
    # Mahjong(),
    # Dragon(),
]
test = [1, 2, 3, 4]

d = Dragon()

hand1 = Hand(cards_string='K_Pa, K_Sw')
hand2 = Hand(cards_string='Phoenix, A_Pa, Q_Pa')
hand3 = Hand(cards_string='K_Pa, Mahjong, 2_Pa, 3_Pa, 4_Pa, 5_Pa, 6_Pa')
hand4 = Hand(cards_string='J_Pa')
# players = [DumbAI(hand1, 'AI1'), DumbAI(hand2, 'AI2'), DumbAI(hand3, 'AI3'), DumbAI(hand4, 'AI4')]
# players = [DumbAI(Hand(), 'AI1'), DumbAI(Hand(), 'AI2'), DumbAI(Hand(), 'AI3'), DumbAI(Hand(), 'AI4')]
Exemplo n.º 8
0
    def find_all_straights(cards: Cards):
        #TODO fix levels
        #TODO, put the level in there to differentiate phoenix at start and end
        #TODO Sort the combinations
        # remove Dog and Dragon from any straights
        cards = cards - Dog() - Dragon()

        buckets = Cards.bucketize_hands(cards.cards)
        power_values = buckets.keys()
        possible_straights_power_values = []

        # Get all possible power combinations
        for start in range(Mahjong().power, Dragon().power):

            length = 0
            current_straight_values = []

            for next_value in range(start, Dragon().power):
                found = False
                new_value = None

                if next_value in power_values:
                    found = True
                    new_value = next_value

                elif Phoenix().power in power_values and Phoenix(
                ).power not in current_straight_values:
                    if next_value != 1:
                        found = True
                        new_value = Phoenix().power

                if found and new_value not in current_straight_values:
                    current_straight_values.append(new_value)
                    length += 1
                    if length >= 5:
                        possible_straights_power_values.append(
                            current_straight_values.copy())

                elif not found:
                    break

        # Now that we have the powers, we get all possible straights
        straights = []
        for straight in possible_straights_power_values:
            straight_cards = [buckets[power] for power in straight]
            for combinations in itertools.product(*straight_cards):
                # straights.append(Cards(cards_list=list(combinations)))
                straights.append(Combination(cards_list=list(combinations)))

        # We replace the phoenix in all the straights where we can
        new_straights = []
        for straight in straights:
            if Phoenix() not in straight.cards:
                for card in straight.cards:
                    if not card == Mahjong():
                        new_cards = straight - card + Phoenix()
                        new_combo = Combination(cards_list=new_cards.cards)
                        new_straights.append(new_combo)
                        # new_straights.append(straight - card + Phoenix())
        straights.extend(new_straights)
        straights.sort()
        return straights