Exemplo n.º 1
0
    def check_for_forced_discard(self, round_info, player_number):
        if player_number is round_info.player_turn:
            player_hand = round_info.true_hand_info()
        else:
            player_hand = utils.get_player_hand_by_number(
                round_info, player_number)

        known = self.list_all_known_cards(round_info, player_number)
        remaining = utils.list_remaining_playable_cards(round_info)

        for card in player_hand:
            if known[card.real_suit][card.real_rank] > 1:
                return ChoiceDetails(Choice.DISCARD, card.hand_position)

        for card in player_hand:
            if remaining[card.real_suit][card.real_rank] > 1:
                return ChoiceDetails(Choice.DISCARD, card.hand_position)

        best_card_rank = -1
        best_card = None
        for card in player_hand:
            if card.real_rank.value > best_card_rank:
                best_card = card.hand_position
                best_card_rank = card.real_rank.value

        return ChoiceDetails(Choice.DISCARD, best_card)
    def initialize_variables(self, round_info):
        self.remaining = utils.list_remaining_playable_cards(round_info)
        self.point_of_uselessness = {}
        for suit in utils.Suit:
            self.point_of_uselessness[suit] = None
            for rank in utils.Rank:
                if round_info.board_state[suit] < rank.value:
                    if self.point_of_uselessness[suit] is None and self.remaining[suit][rank] == 0:
                        self.point_of_uselessness[suit] = rank

        original_player_number = round_info.player_turn
        player_number = utils.next_player_number(round_info, original_player_number)

        oldest_age = -1
        for card in round_info.player_hand:
            card_age = round_info.current_turn - card.drawn_on_turn
            if card_age > oldest_age:
                oldest_age = card_age
                self.oldest_card[original_player_number] = card.hand_position

        while player_number is not original_player_number:
            player_hand = utils.get_player_hand_by_number(round_info, player_number)
            oldest_age = -1
            for card in player_hand:
                card_age = round_info.current_turn - card.drawn_on_turn
                if card_age > oldest_age:
                    oldest_age = card_age
                    self.oldest_card[player_number] = card.hand_position

            player_number = utils.next_player_number(round_info, player_number)
Exemplo n.º 3
0
    def check_for_guess_discard(self, round_info, player_number):
        if player_number is round_info.player_turn:
            player_hand = round_info.player_hand
        else:
            player_hand = utils.get_player_hand_by_number(round_info, player_number)

        unmarked = []
        for card in player_hand:
            if card.revealed_rank is None and card.revealed_suit is None:
                unmarked.append(card)

        if len(unmarked) == 0:
            known = utils.list_all_known_cards(round_info, player_number)[0]
            remaining = utils.list_remaining_playable_cards(round_info)
            discarded = utils.list_discarded_cards(round_info)

            for card in player_hand:
                if card.revealed_rank is None:
                    add = True
                    for rank in utils.Rank:
                        if round_info.board_state[card.revealed_suit] < rank.value and \
                                remaining[card.revealed_suit][rank] == 1 and \
                                known[card.revealed_suit][rank] - discarded[card.revealed_suit][rank] == 0:
                            add = False
                    if add:
                        unmarked.append(card)

                elif card.revealed_suit is None:
                    add = True
                    for suit in remaining:
                        if round_info.board_state[suit] < card.revealed_rank.value and \
                                remaining[suit][card.revealed_rank] == 1 and \
                                known[suit][card.revealed_rank] - discarded[suit][card.revealed_rank] == 0:
                            add = False
                    if add:
                        unmarked.append(card)

        if len(unmarked) == 0:
            unmarked = player_hand

        oldest = unmarked[0]
        for card in unmarked:
            if card.drawn_on_turn < oldest.drawn_on_turn:
                oldest = card

        return ChoiceDetails(
            Choice.DISCARD,
            oldest.hand_position
        )
    def check_for_obvious_discard(self, round_info, player_number):
        if player_number is round_info.player_turn:
            player_hand = round_info.player_hand
        else:
            player_hand = utils.get_player_hand_by_number(round_info, player_number)

        known = utils.list_all_known_cards(round_info)[0]
        discarded = utils.list_discarded_cards(round_info)
        remaining = utils.list_remaining_playable_cards(round_info)

        for card in player_hand:
            useless = False

            if card.revealed_suit is not None:
                useless = True
                future_ranks_useless = False
                for rank in utils.Rank:
                    if round_info.board_state[card.revealed_suit] < rank.value:
                        if not future_ranks_useless and remaining[card.revealed_suit][rank] - \
                                known[card.revealed_suit][rank] + discarded[card.revealed_suit][rank] > 0:
                            useless = False
                        else:
                            future_ranks_useless = True

            if card.revealed_rank is not None:
                useless = True
                for suit in utils.Suit:
                    if round_info.board_state[suit] < card.revealed_rank.value:
                        if remaining[suit][card.revealed_rank] - known[suit][card.revealed_rank] + \
                                discarded[suit][card.revealed_rank] > 0:
                            useless = False

            if card.revealed_suit is not None and card.revealed_rank is not None:
                if round_info.board_state[card.revealed_suit] >= card.revealed_rank.value:
                    useless = True

            if useless:
                return ChoiceDetails(
                    Choice.DISCARD,
                    card.hand_position
                )
        return False
Exemplo n.º 5
0
    def check_card_usefulness(self, round_info, card):
        remaining = utils.list_remaining_playable_cards(round_info)
        useless = False

        point_of_uselessness = {}
        for suit in utils.Suit:
            point_of_uselessness[suit] = None
            for rank in utils.Rank:
                if round_info.board_state[suit] < rank.value:
                    if point_of_uselessness[suit] is None and remaining[suit][rank] == 0:
                        point_of_uselessness[suit] = rank

        if card.revealed_suit is not None:
            if round_info.board_state[card.revealed_suit] == 5 or \
                    (point_of_uselessness[card.revealed_suit] is not None and
                     round_info.board_state[card.revealed_suit] + 1 is point_of_uselessness[card.revealed_suit].value):
                useless = True

        if card.revealed_rank is not None:
            useless = True
            for suit in utils.Suit:
                if round_info.board_state[suit] < card.revealed_rank.value and \
                        (point_of_uselessness[suit] is None or
                         point_of_uselessness[suit].value > card.revealed_rank.value):
                    useless = False

        if card.revealed_suit is not None and card.revealed_rank is not None:
            if round_info.board_state[card.revealed_suit] < card.revealed_rank.value and \
                    (point_of_uselessness[card.revealed_suit] is None or
                     point_of_uselessness[card.revealed_suit].value > card.revealed_rank.value):
                useless = False
            else:
                useless = True

        if useless:
            return ChoiceDetails(
                Choice.DISCARD,
                card.hand_position
            )
        return False
    def check_for_necessary_tip(self, round_info, player_number):
        if round_info.hints == 0:
            return False

        remaining = utils.list_remaining_playable_cards(round_info)
        next_player_hand = utils.next_player_hand(round_info, player_number)
        next_player_number = utils.next_player_number(round_info, player_number)
        discarded_position = self.check_for_guess_discard(round_info, next_player_number)[1]
        discarded = next_player_hand[discarded_position]

        if round_info.board_state[discarded.real_suit] < discarded.real_rank.value and \
                remaining[discarded.real_suit][discarded.real_rank] == 1 and \
                discarded.real_rank.value - round_info.board_state[discarded.real_suit] <= 1:
            if discarded.revealed_rank is None:
                return ChoiceDetails(
                    Choice.HINT,
                    HintDetails(utils.next_player_number(round_info, player_number), discarded.real_rank)
                )
            else:
                return ChoiceDetails(
                    Choice.HINT,
                    HintDetails(utils.next_player_number(round_info, player_number), discarded.real_suit)
                )
        return False
Exemplo n.º 7
0
    def check_for_save_tip(self, round_info, player_number):
        best_player_number = -1
        best_play_priority = False
        best_hint_type = None
        best_hint_rank = 6

        remaining = utils.list_remaining_playable_cards(round_info)
        original_player_number = player_number
        player_number = utils.next_player_number(round_info, utils.next_player_number(round_info, player_number))

        while player_number is not original_player_number and not best_play_priority:
            player_hand = utils.get_player_hand_by_number(round_info, player_number)

            play_priority = False
            prev_player = utils.prev_player_number(round_info, player_number)
            play = self.check_for_obvious_play(round_info, prev_player)
            if play is False:
                play = self.check_for_hinted_play(round_info, prev_player)

            if play is not False:
                play_priority = True

            discarded_position = self.check_for_guess_discard(round_info, player_number)[1]
            discarded_card = player_hand[discarded_position]

            if remaining[discarded_card.real_suit][discarded_card.real_rank] == 1 and \
                    max(round_info.board_state.values()) < discarded_card.real_rank.value - 1 and \
                    discarded_card.revealed_rank is None and discarded_card.revealed_suit is None:
                best_player_number = player_number
                best_play_priority = play_priority
                best_hint_type = discarded_card.real_rank

            player_number = utils.next_player_number(round_info, player_number)

        if best_hint_type is None:
            player_number = utils.next_player_number(round_info, utils.next_player_number(round_info, player_number))

            while player_number is not original_player_number and not best_play_priority:
                player_hand = utils.get_player_hand_by_number(round_info, player_number)

                play_priority = False
                prev_player = utils.prev_player_number(round_info, player_number)
                if prev_player is not original_player_number:
                    play = self.check_for_obvious_play(round_info, prev_player)
                    if play is False:
                        play = self.check_for_hinted_play(round_info, prev_player)

                    if play is not False:
                        play_priority = True

                for card in player_hand:
                    if remaining[card.real_suit][card.real_rank] == 1 and \
                            max(round_info.board_state.values()) < card.real_rank.value - 1 and \
                            card.revealed_rank is None and card.revealed_suit is None and \
                            best_hint_rank > card.real_rank.value:
                        best_player_number = player_number
                        best_play_priority = play_priority
                        best_hint_type = card.real_rank
                        best_hint_rank = card.real_rank.value

                player_number = utils.next_player_number(round_info, player_number)

        if best_hint_type is not None:
            return ChoiceDetails(
                Choice.HINT,
                HintDetails(best_player_number, best_hint_type)
            )
        return False
Exemplo n.º 8
0
    def check_for_necessary_tip(self, round_info, player_number):
        if round_info.hints == 0 or round_info.hints == utils.MAX_HINTS:
            return False

        if player_number is round_info.player_turn:
            player_hand = round_info.player_hand
        else:
            player_hand = utils.get_player_hand_by_number(round_info, player_number)

        remaining = utils.list_remaining_playable_cards(round_info)
        next_player_hand = utils.next_player_hand(round_info, player_number)
        next_player_number = utils.next_player_number(round_info, player_number)

        if self.check_for_obvious_play(round_info, next_player_number) is not False:
            return False

        distrust = False
        play = self.check_for_hinted_play(round_info, next_player_number)
        if play is not False:
            play_position = play[1]
            played_card = next_player_hand[play_position]

            if round_info.board_state[played_card.real_suit] is not played_card.real_rank.value - 1:
                distrust = True

                own_play = None
                if self.check_for_obvious_play(round_info, player_number) is not False:
                    own_play = self.check_for_obvious_play(round_info, player_number)[1]
                if own_play is None and self.check_for_hinted_play(round_info, player_number) is not False:
                    own_play = self.check_for_hinted_play(round_info, player_number)[1]

                if own_play is not None and \
                        round_info.board_state[played_card.real_suit] is played_card.real_rank.value - 2:
                    own_card = player_hand[own_play]
                    if (own_card.revealed_rank is not None and
                        own_card.revealed_rank.value is played_card.real_rank.value - 1) or \
                            (own_card.revealed_suit is not None and
                             own_card.revealed_suit is played_card.real_suit):
                        distrust = False

        else:
            if self.check_for_obvious_discard(round_info, next_player_number) is False:
                played_position = self.check_for_guess_discard(round_info, next_player_number)[1]
                played_card = next_player_hand[played_position]

                if round_info.board_state[played_card.real_suit] < played_card.real_rank.value and \
                        remaining[played_card.real_suit][played_card.real_rank] == 1 and \
                        self.check_card_usefulness(round_info, played_card) is False:
                    distrust = True

        if distrust:
            if debug and round_info.log:
                self.info("good_tip:")
            answer = self.check_for_good_tip(round_info, player_number, only_next_player=True)
            if answer is False:
                if debug and round_info.log:
                    self.info("risky_tip:")
                answer = self.check_for_risky_tip(round_info, player_number, only_next_player=True)

            if answer is not False:
                return answer

            if played_card.revealed_rank is None:
                return ChoiceDetails(
                    Choice.HINT,
                    HintDetails(utils.next_player_number(round_info, player_number), played_card.real_rank)
                )
            else:
                return ChoiceDetails(
                    Choice.HINT,
                    HintDetails(utils.next_player_number(round_info, player_number), played_card.real_suit)
                )

        return False
Exemplo n.º 9
0
    def check_for_hinted_play(self, round_info, player_number):
        if player_number is round_info.player_turn:
            player_hand = round_info.player_hand
        else:
            player_hand = utils.get_player_hand_by_number(round_info, player_number)

        alignment_delta = 2
        max_hint_size = 10

        if round_info.lives == 1:
            alignment_delta = 0
            max_hint_size = 1

        hinted_ranks = {}
        hinted_suits = {}
        for suit in utils.Suit:
            hinted_suits[suit] = 0
        for rank in utils.Rank:
            hinted_ranks[rank] = 0

        for x in range(0, len(player_hand)):
            if player_hand[x].revealed_suit is not None and player_hand[x].revealed_rank is None and \
                    self.card_hint_type[player_number][x] == "Play":
                hinted_suits[player_hand[x].revealed_suit] += 1
            if player_hand[x].revealed_rank is not None and player_hand[x].revealed_suit is None and \
                    self.card_hint_type[player_number][x] == "Play":
                hinted_ranks[player_hand[x].revealed_rank] += 1

        known = utils.list_all_known_cards(round_info, player_number)[0]
        remaining = utils.list_remaining_playable_cards(round_info)
        discarded = utils.list_discarded_cards(round_info)

        best_hint = -1
        best_hint_size = max_hint_size
        best_alignment = 0
        hint_type = None

        for suit in hinted_suits:
            if 0 < hinted_suits[suit] <= best_hint_size:
                rank = round_info.board_state[suit] + 1
                if rank <= 5:
                    rank_rank = utils.Rank(rank)
                    if remaining[suit][rank_rank] - known[suit][rank_rank] + discarded[suit][rank_rank] > 0:
                        best_hint = suit
                        best_hint_size = hinted_suits[suit]
                        best_alignment = 1
                        hint_type = 'suit'

        board_alignment = {}
        for rank in utils.Rank:
            board_alignment[rank] = 0
        for suit in round_info.board_state:
            rank = round_info.board_state[suit] + 1
            if rank <= 5:
                rank_rank = utils.Rank(rank)
                if remaining[suit][rank_rank] - known[suit][rank_rank] + discarded[suit][rank_rank] > 0:
                    board_alignment[rank_rank] += 1

        for rank in hinted_ranks:
            if 0 < board_alignment[rank] and ((0 < hinted_ranks[rank] < best_hint_size) or
                                              (0 < hinted_ranks[rank] <= best_hint_size and best_alignment <
                                               board_alignment[rank])):
                best_hint = rank
                best_hint_size = hinted_ranks[rank]
                best_alignment = board_alignment[rank]
                hint_type = 'rank'

        if best_hint != -1 and best_hint_size <= best_alignment + alignment_delta:
            for x in range(0, len(player_hand)):
                if hint_type == 'rank':
                    if player_hand[x].revealed_rank is not None and player_hand[x].revealed_suit is None and \
                            player_hand[x].revealed_rank is best_hint and \
                            self.card_hint_type[player_number][x] == "Play":
                        return ChoiceDetails(
                            Choice.PLAY,
                            x
                        )
                else:
                    if player_hand[x].revealed_suit is not None and player_hand[x].revealed_rank is None and \
                            player_hand[x].revealed_suit is best_hint and \
                            self.card_hint_type[player_number][x] == "Play":
                        return ChoiceDetails(
                            Choice.PLAY,
                            x
                        )

        return False