예제 #1
0
    def get_combination_to_play(self, trick, wish=None):
        combination_to_play = None

        if Mahjong() in self.hand.cards:
            return Combination(cards_list=[Mahjong()])

        # if there is a trick being played
        last_play = trick.get_last_play()
        if last_play:

            last_combination = last_play.combination

            combination_to_play = self.hand.find_lowest_combination(
                last_combination.level, last_combination.type)

        # If we are leading
        else:
            for combination_type in self.lead_preference:
                # -1 otherwise the dog is never played
                combination_to_play = self.hand.find_lowest_combination(
                    -1, combination_type)
                # as soon as a combination is found, play it
                if combination_to_play:
                    break

        return combination_to_play
예제 #2
0
    def run_game(self):

        # Until 3 players are out
        # Game
        self.exchange_cards()

        for player in self.players:
            if Mahjong() in player.hand.cards:
                self.lead_player = player
                break

        #TODO How to decide lead player
        else:
            self.lead_player = self.players[0]

        while not self.is_game_over():
            print('',
                  '### new trick with players %s' %
                  (', '.join(['%s (%spts)' % (player.name, player.points) for player in self.get_player_still_game()])),
                  '### leading player is %s' % self.lead_player,
                  '### trick - %s' % self.present_trick,
                  '',
                  sep='\n')
            # Take action from the lead player
            self.get_player_action(self.lead_player)

            # Check if game is over
            if self.is_game_over():
                continue
            self.check_for_bomb()

            # Initialize the rolling cycle of player
            player_iterator = self.next_active_player()

            if self.lead_player.is_out():
                self.lead_player = next(player_iterator)
                continue

            active_player = next(player_iterator)

            # Until somebody wins the hand
            while not self.present_trick.is_over() and not self.is_game_over():
                player_action = self.get_player_action(active_player)

                if not player_action.has_passed():

                    # Check if game is over
                    if self.is_game_over():
                        break

                    self.check_for_bomb()

                    if self.lead_player.is_out():
                        self.lead_player = next(player_iterator)

                self.check_for_bomb()
                active_player = next(player_iterator)

            self.end_of_trick()
예제 #3
0
파일: action.py 프로젝트: peopzen/ticher
    def assert_valid(self):
        if self.action_type == ActionsType.play:
            if self.combination is None:
                raise IllegalAction('a play must come with cards')

        if self.action_type == ActionsType.passes:
            if self.combination is not None:
                raise IllegalAction('No cards can be played while passing')

        if self.wish is not None:
            if self.combination is None and Mahjong() not in self.combination:
                raise IllegalAction('Must play the Mahjong to wish for a card')
예제 #4
0
파일: hand.py 프로젝트: peopzen/ticher
    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
예제 #5
0
파일: player.py 프로젝트: peopzen/ticher
    def play(self, trick: Trick, wish=None):
        combination_to_play = self.get_combination_to_play(trick, wish)

        if combination_to_play is not None:
            self.hand -= combination_to_play
            self.hand_size -= combination_to_play.size

            if Mahjong() in combination_to_play.cards:
                return Action.play(player=self, combination=combination_to_play, wish=self.wish)
            else:
                return Action.play(player=self, combination=combination_to_play)

        else:
            # Empty action means passing
            return Action.passes(player=self)
예제 #6
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)
예제 #7
0
파일: hand.py 프로젝트: peopzen/ticher
    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