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
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