def _list_best_options(self): """ Returns a list of the highest probability asks you can make, according to self.info Ties are broken in this method by the following criteria: 1. Number of guarenteed cards in half suit If player A is guarenteed to have more cards in the half suit than player B, ask them This method does not account for the "danger" of asking certain players yet """ best_asks = [] highest_prob = 0 most_hs_cards = 0 for card in card_utils.gen_all_cards(): for ID in self._get_opponents(): if self._check_legal_ask(ID, card): if self.info[ID][card] != NO: best_asks = [(ID, card)] highest_prob = self.info[ID][card] most_hs_cards = self.hs_info[ID][ card_utils.find_half_suit(card)] elif self.info[ID][card] == highest_prob: if self.hs_info[ID][card_utils.find_half_suit( card)] > most_hs_cards: best_asks = [(ID, card)] most_hs_cards = self.hs_info[ID][ card_utils.find_half_suit(card)] elif self.hs_info[ID][card_utils.find_half_suit( card)] == most_hs_cards: best_asks.append((ID, card)) return best_asks
def check_call_correct(self, call, ID): """ Checks if a call is correct :param call: a call list of tuples :param ID: ID of player calling :return: hs, team, success """ success = True for ID, card in call: if card not in self.player_cards[ID]: success = False return [card_utils.find_half_suit(card), ID % 2, success]
def _init_hs_info_start_game(ID, own_cards): """ Returns the half suit info dictionary assuming its the start of a new game Uses data from the already intialized info dictionary """ blank_hs = {hs: 0 for hs in card_utils.gen_all_halfsuits()} hs_info = { player_id: blank_hs.copy() for player_id in range(NUM_PLAYERS) } for card in own_cards: hs_info[ID][card_utils.find_half_suit(card)] += 1 return hs_info
def _check_legal_ask(self, ID_target, card): """ Given a target player and a card to ask, check if the ask is legal Conditions for legality: 1. You must have a card in the same half suit 2. You must not have that card 3. The person you ask must be on the opposite team ID_target: The ID of the person the self wants to ask card: the card that we are checking the legality of """ if ID_target % 2 != self.ID % 2: if self.info[self.ID][card] == NO: for c in card_utils.find_cards( card_utils.find_half_suit(card)): if self.info[self.ID][c] == YES: return True return False
def update_transaction(self, ID_ask, ID_target, card, success): """ Given a transaction, updates the player's info, public info, and half suit info :param ID_ask: ID of player asking for the card :param ID_target: player being asked :param card: card being asked :param success: true if card was taken from ID_target """ if success: self.num_cards[ID_ask] += 1 self.num_cards[ID_target] -= 1 self.info[ID_ask][card] = YES self.info[ID_target][card] = NO self.public_info[ID_ask][card] = YES self.public_info[ID_target][card] = NO if self.hs_info[ID_ask][card_utils.find_half_suit(card)] == 0: self.hs_info[ID_ask][card_utils.find_half_suit(card)] = 1 self.hs_info[ID_ask][card_utils.find_half_suit(card)] += 1 if self.public_hs_info[ID_ask][card_utils.find_half_suit( card)] == 0: self.public_hs_info[ID_ask][card_utils.find_half_suit( card)] = 1 self.public_hs_info[ID_ask][card_utils.find_half_suit(card)] += 1 if self.hs_info[ID_target][card_utils.find_half_suit(card)] > 0: self.hs_info[ID_target][card_utils.find_half_suit(card)] -= 1 if self.public_hs_info[ID_target][card_utils.find_half_suit( card)] > 0: self.public_hs_info[ID_target][card_utils.find_half_suit( card)] -= 1 else: self.info[ID_ask][card] = NO self.info[ID_target][card] = NO self.public_info[ID_ask][card] = NO self.public_info[ID_target][card] = NO if self.hs_info[ID_ask][card_utils.find_half_suit(card)] == 0: self.hs_info[ID_ask][card_utils.find_half_suit(card)] = 1 if self.public_hs_info[ID_ask][card_utils.find_half_suit( card)] == 0: self.public_hs_info[ID_ask][card_utils.find_half_suit( card)] = 1 self._update_info( card_utils.find_cards(card_utils.find_half_suit(card))) self._update_public_info( card_utils.find_cards(card_utils.find_half_suit(card)))
def _is_consistent(info_dict, remaining_hs, hs_info, num_cards, check_cards=tuple(card_utils.gen_all_cards())): """ Checks if an info dictionary is consistent. If the info dictionary has a contradiction, returns false. Otherwise returns true. Info dictionaries must follow these rules: 1. No two players can have YES for the same card 2. If the half suit has not been called yet, at least 1 player must have at least the possibility of having any card in that half suit 3. If a player has at least X cards in a half suit, they cannot have more than HS_SIZE-X cards being NO in that half suit 4. If a player has X cards in their hand, they cannot have more than DECK_SIZE-X cards being NO :param info_dict: either a public info dict or player info dict :param remaining_hs: the remaining half suits in the game :param hs_info: the half suit info :param num_cards: number of each players cards :param check_cards: cards to check for consistency :return: True if consistent, false otherwise """ # Calculate check_hs based on check_cards check_hs = set([]) for c in check_cards: hs = card_utils.find_half_suit(c) if hs not in check_hs and hs in remaining_hs: check_hs.add(hs) # Rule 1 for card in check_cards: players_yes = 0 for ID in range(NUM_PLAYERS): if info_dict[ID][card] == YES: players_yes += 1 if players_yes > 1: return False # Rule 2 for hs in check_hs: for card in card_utils.find_cards(hs): players_no = 0 for ID in range(NUM_PLAYERS): if info_dict[ID][card] == NO: players_no += 1 if players_no == NUM_PLAYERS: return False # Rule 3 for hs in check_hs: for ID in range(NUM_PLAYERS): hs_no_count = 0 for card in card_utils.find_cards(hs): if info_dict[ID][card] == NO: hs_no_count += 1 if hs_info[ID][hs] + hs_no_count > HS_SIZE: return False # Rule 4 for ID in range(NUM_PLAYERS): no_count = 0 for card in card_utils.gen_all_cards(): if info_dict[ID][card] == NO: no_count += 1 if num_cards[ID] + no_count > DECK_SIZE: return False return True