예제 #1
0
    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)))
예제 #2
0
 def test_check_call(self):
     own_hand = ["2h", "3h", "4h", "5h", "6h", "7h", "8h", "9h", "Th"]
     p1 = Player.player_start_of_game(0, own_hand)
     res = p1.check_call()
     expected = [(0, x) for x in card_utils.find_cards("Lh")]
     self.assertTrue(res, "Did not call")
     self.assertEqual(
         res, expected,
         "Did not attribute the cards with the correct player")
예제 #3
0
 def _check_card_guarenteed(self):
     """
     Checks if an opponent player has a card that you know you are guarenteed to guess correctly
     If so, return a tuple (player_id, card)
     If not, return False
     """
     for hs in card_utils.gen_all_halfsuits():
         if self.hs_info[self.ID][hs] > 0:
             for card in card_utils.find_cards(hs):
                 for ID in self._get_opponents():
                     if self.info[ID][card] == YES:
                         return ID, card
     return False
예제 #4
0
 def report_call(self, hs):
     """
     Updates the player_cards dict
     Makes each player update their info in response to a call
     :param hs: half suit being called
     """
     hs_info_dict = {ID: 0 for ID in range(NUM_PLAYERS)}
     for card in card_utils.find_cards(hs):
         for ID in range(NUM_PLAYERS):
             if card in self.player_cards[ID]:
                 self.player_cards[ID].remove(card)
                 hs_info_dict[ID] += 1
     for player in self.players:
         player.update_call(hs, hs_info_dict)
예제 #5
0
 def test_update_info_endgame(self):
     own_hand = ["2h", "3h"]
     p1 = Player.player_start_of_game(0, own_hand)
     p1.num_cards = {0: 2, 1: 0, 2: 2, 3: 0, 4: 2, 5: 0}
     for c in card_utils.gen_all_cards():
         for ID in range(constants.NUM_PLAYERS):
             if c not in card_utils.find_cards(
                     "Lh") or ID in p1._get_opponents():
                 p1.info[ID][c] = constants.NO
     p1.info[2]["4h"] = constants.NO
     p1.info[2]["5h"] = constants.NO
     p1._update_info()
     self.assertEqual(p1.info[4]["4h"], constants.YES,
                      "Did not conclude player 4 had 4h")
     self.assertEqual(p1.info[2]["6h"], constants.YES,
                      "Did not conclude player 2 had 2h")
예제 #6
0
 def check_call(self):
     """
     Check if you can call a half suit
     Returns a list of tuples like this:
     [(player, card), (player, card) ...]
     If no call can be made, return False
     """
     for hs in card_utils.gen_all_halfsuits():
         call = []
         for card in card_utils.find_cards(hs):
             for ID in self._get_teammates():
                 if self.info[ID][card] == YES:
                     call.append((ID, card))
         if len(call) == HS_SIZE:
             return call
     return False
예제 #7
0
    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
예제 #8
0
 def test_update_call(self):
     own_hand = ["2h", "3h", "4h", "5h", "6h", "7h", "8h", "9h", "Th"]
     p1 = Player.player_start_of_game(0, own_hand)
     p1.update_call("8J", {0: 1, 1: 0, 2: 2, 3: 0, 4: 3, 5: 0})
     self.assertEqual(p1.num_cards, {
         0: 8,
         1: 9,
         2: 7,
         3: 9,
         4: 6,
         5: 9
     }, "Number of cards is incorrect")
     for ID in range(constants.NUM_PLAYERS):
         for card in card_utils.find_cards("8J"):
             self.assertEqual(
                 p1.info[ID][card], constants.NO,
                 "A player still has a card in the called half suit")
         self.assertEqual(
             p1.hs_info[ID]["8J"], 0,
             "A player is still marked as having at least 1 card in the half suit"
         )
예제 #9
0
 def force_call(self, hs):
     """
     Forces the player to call the half suit hs.
     Typically this happens at the end of the game
     :param hs: half suit that is being forced
     :return: A "call" list of tuples
     [(player, card), (player, card) ...]
     """
     call = []
     teammates = self._get_teammates()
     for card in card_utils.find_cards(hs):
         found = False
         for ID in range(NUM_PLAYERS):
             if self.info[ID][card] == YES and ID in teammates:
                 call.append((ID, teammates))
                 found = True
         if not found:
             call.append(teammates[random.randint(0,
                                                  len(teammates) - 1)],
                         call)
     return call
예제 #10
0
    def update_call(self, hs, card_count_hs):
        """
        Given a half suit being called, update the player's info and half suit info
        This essentially sets the info on all players to knowing that they don't have cards in that half suit

        hs: the half suit being called
        card_count_hs: the number of cards that each player had in the half suit
        This is a dictionary of {Player ID: num_cards}

        Note that there's no difference whether the call succeeds or fails!
        """
        self.remaining_hs.remove(hs)
        for ID in range(NUM_PLAYERS):
            for card in card_utils.find_cards(hs):
                self.info[ID][card] = NO
                self.public_info[ID][card] = NO
            self.hs_info[ID][hs] = 0
            self.public_hs_info[ID][hs] = 0
            self.num_cards[ID] -= card_count_hs[ID]
        self._update_info()
        self._update_public_info()
예제 #11
0
    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