Пример #1
0
 def setUp(self):
     agent_1 = RandomHeartsAgent()
     agent_2 = RandomHeartsAgent()
     agent_3 = RandomHeartsAgent()
     agent_4 = RandomHeartsAgent()
     self.adj = HeartsAdjudicator()
     self.game = GameManager(
         agent_list=[0, agent_1, agent_2, agent_3, agent_4],
         adjudicator=self.adj)
Пример #2
0
 def __init__(self):
     self.own_adj = HeartsAdjudicator()
     # Given the masked state, only cards in hand of agent
     # and played cards is available
     self.cards_in_hand = []
     self.player_position = -1
     self.id = 3
     self.agent_name = "The Equalizer"
     self.version = 1.0
Пример #3
0
def worker(var):
    # for j in range(0, 25):
    game_uuid = uuid.uuid4().hex
    adj = HeartsAdjudicator()
    state = HeartsState()
    agent_1 = get_agent()
    agent_2 = get_agent()
    agent_3 = get_agent()
    agent_4 = get_agent()
    agent_list = [0, agent_1, agent_2, agent_3, agent_4]
    game = GameManager(agent_list, adjudicator=adj, state=state)
    # Save starting game information
    save_game(game_uuid, agent_list)
    # Play a game.
    game.play_game()
    # The game is over, save the states of the game into the database.
    process_state_data(game_uuid, game)
Пример #4
0
 def __init__(self):
     self.own_adj = HeartsAdjudicator()
     self.cards_in_hand = []
Пример #5
0
class MinimizingAgent(Agent):
    """
    An random agent who selects from available legal moves.
    """
    def __init__(self):
        self.own_adj = HeartsAdjudicator()
        self.cards_in_hand = []

    def __str__(self):
        return "The Low Layer"

    def get_action(self, partial_state: HeartsState):
        """
        The get_action() method inspects the state for open positions and picks one randomly.
        :param partial_state: the position vector of the game.
        :return: an Action.
        """
        # Given the masked state, only cards in hand of agent is available
        for i in range(len(partial_state.values)):
            if 0 < partial_state.values[i] < 5:
                self.cards_in_hand.append(i)

        # Agent picks 3 cards to pass
        if partial_state.pass_type > 0:
            c1 = random.choice(self.cards_in_hand)
            self.cards_in_hand.remove(c1)
            c2 = random.choice(self.cards_in_hand)
            self.cards_in_hand.remove(c2)
            c3 = random.choice(self.cards_in_hand)
            self.cards_in_hand.remove(c3)
            three_cards = [c1, c2, c3]
            return HeartsAction(three_cards)

        # Agent picks a card to play
        # elif partial_state.trick_number > 0 and len(cards_in_hand) > 0:
        else:
            choice = self.select_card(partial_state)
            self.cards_in_hand = []
            return HeartsAction(choice)

    def select_card(self, partial_state: HeartsState):
        # our player is leading, choosing a random card for now
        if self.is_lead(partial_state):
            choice = random.choice(self.cards_in_hand)
        else:
            # we're following, not leading
            if self.not_void(partial_state):
                # Not void in the leading suit
                # pick the lowest card compared to the highest currently played
                choice = self.get_highest_low_card(partial_state)
            else:
                # Void in the leading suit
                # just randomly play for now
                choice = random.choice(self.cards_in_hand)
        return choice

    def is_lead(self, partial_state: HeartsState):
        """Returns true if agent is leading currently"""
        played = partial_state.values[partial_state.values > 20]

        if len(played) >= 4:
            return True
        return False

    def not_void(self, partial_state: HeartsState):
        """Returns true if agent is not void in the leading suit"""
        lead_suit = self.own_adj.lead_suit(partial_state)
        begin = 13 * lead_suit  # beginning of range of valid cards
        end = 13 * (lead_suit + 1)  # end of range of valid cards
        for x in self.cards_in_hand:
            if begin <= x < end:
                return True
        return False

    def get_highest_low_card(self, partial_state: HeartsState):
        """Find the cards that are lowest than the card currently set to win and
        choose the highest one"""
        max_card_played = self.own_adj.find_max_card(partial_state)
        max_card_player = -1
        lead_suit = self.own_adj.lead_suit(partial_state)
        begin = 13 * lead_suit  # beginning of range of valid cards
        end = 13 * (lead_suit + 1)  # end of range of valid cards
        for x in self.cards_in_hand:
            if begin <= x < end:
                if max_card_played > x > max_card_player:
                    max_card_player = x

        # TODO might need to do something other than "just play whatever and hope for the best"
        # TODO if we end up with a hand where none of the cards are less than the current max
        if max_card_player == -1:
            max_card_player = self.cards_in_hand[0]
        return max_card_player
Пример #6
0
class TestHeartsState(unittest.TestCase):
    def setUp(self):
        agent_1 = RandomHeartsAgent()
        agent_2 = RandomHeartsAgent()
        agent_3 = RandomHeartsAgent()
        agent_4 = RandomHeartsAgent()
        self.adj = HeartsAdjudicator()
        self.game = GameManager(
            agent_list=[0, agent_1, agent_2, agent_3, agent_4],
            adjudicator=self.adj)

    def test_pass_round(self):

        self.adj.start_game()
        while not self.adj.is_finished():
            # New round, check passing
            if self.adj.lead_suit == -2:
                for i in range(0, 4):
                    agent_index, partial_state = self.adj.agent_turn()
                    p_action = self.game.agent_list[agent_index].get_action(
                        partial_state)
                    self.adj.step_game(p_action)

                # Passing CW
                if self.adj.state.pass_type == 0:
                    self.assertTrue(x for x in self.adj.pass_actions[0]
                                    if self.adj.state.values[x] == 2)
                    self.assertTrue(x for x in self.adj.pass_actions[1]
                                    if self.adj.state.values[x] == 3)
                    self.assertTrue(x for x in self.adj.pass_actions[2]
                                    if self.adj.state.values[x] == 4)
                    self.assertTrue(x for x in self.adj.pass_actions[3]
                                    if self.adj.state.values[x] == 1)
                # Passing CCW
                elif self.adj.state.pass_type == 1:
                    self.assertTrue(x for x in self.adj.pass_actions[0]
                                    if self.adj.state.values[x] == 4)
                    self.assertTrue(x for x in self.adj.pass_actions[1]
                                    if self.adj.state.values[x] == 1)
                    self.assertTrue(x for x in self.adj.pass_actions[2]
                                    if self.adj.state.values[x] == 2)
                    self.assertTrue(x for x in self.adj.pass_actions[3]
                                    if self.adj.state.values[x] == 3)
                # Passing Straight
                elif self.adj.state.pass_type == 2:
                    self.assertTrue(x for x in self.adj.pass_actions[0]
                                    if self.adj.state.values[x] == 3)
                    self.assertTrue(x for x in self.adj.pass_actions[1]
                                    if self.adj.state.values[x] == 4)
                    self.assertTrue(x for x in self.adj.pass_actions[2]
                                    if self.adj.state.values[x] == 1)
                    self.assertTrue(x for x in self.adj.pass_actions[3]
                                    if self.adj.state.values[x] == 2)
                # No pass
                elif self.adj.state.pass_type == 3:
                    self.assertTrue(x for x in self.adj.pass_actions[0]
                                    if self.adj.state.values[x] == 1)
                    self.assertTrue(x for x in self.adj.pass_actions[1]
                                    if self.adj.state.values[x] == 2)
                    self.assertTrue(x for x in self.adj.pass_actions[2]
                                    if self.adj.state.values[x] == 3)
                    self.assertTrue(x for x in self.adj.pass_actions[3]
                                    if self.adj.state.values[x] == 4)

            agent_index, partial_state = self.adj.agent_turn()
            p_action = self.game.agent_list[agent_index].get_action(
                partial_state)
            self.adj.step_game(p_action)

    def test_player_turns_trick_winner(self):
        self.adj.start_game()
        # Set Trick 1, player 4 wins trick
        self.adj.state.set_encoding(11, '2C')
        self.adj.state.set_encoding(12, '3C')
        self.adj.state.set_encoding(13, '4C')
        self.adj.state.set_encoding(14, '5C')
        self.adj.state.trick_winner = 4
        self.adj.state.trick_number = 2
        self.adj.state.current_player = 4
        self.adj.lead_suit = 0
        self.assertEqual(4, self.adj.state.current_player)

        # Set Trick 2, player 4 plays, player 1 is next player
        agent_index, partial_state = self.adj.agent_turn()
        p_action = self.game.agent_list[agent_index].get_action(partial_state)
        state = self.adj.step_game(p_action)
        self.assertEqual(1, state.current_player)

        # Player 1 plays, player 2 is next player
        agent_index, partial_state = self.adj.agent_turn()
        p_action = self.game.agent_list[agent_index].get_action(partial_state)
        state = self.adj.step_game(p_action)
        self.assertEqual(2, state.current_player)

        # Player 1 plays, player 2 is next player
        agent_index, partial_state = self.adj.agent_turn()
        p_action = self.game.agent_list[agent_index].get_action(partial_state)
        state = self.adj.step_game(p_action)
        self.assertEqual(3, state.current_player)

        # Player 4 plays, trick_winner is the next player and starts next trick
        agent_index, partial_state = self.adj.agent_turn()
        p_action = self.game.agent_list[agent_index].get_action(partial_state)
        state = self.adj.step_game(p_action)
        self.assertEqual(state.trick_winner, state.current_player)
Пример #7
0
            for data in state_data:
                deck = data["deck"].tolist()
                action = data["actions"]
                score = data["scores"]
                writer.writerow([deck, action, score, game_uuid])

    if MYSQL_SERVER:
        db.insert_state(directory)


for i in range(0, 10000):

    # Create the players, the adjudicator, and the game object.

    game_uuid = uuid.uuid4().hex
    adj = HeartsAdjudicator()
    state = HeartsState()
    agent_1 = get_agent()
    agent_2 = get_agent()
    agent_3 = get_agent()
    agent_4 = get_agent()
    agent_list = [0, agent_1, agent_2, agent_3, agent_4]
    game = GameManager(agent_list, adjudicator=adj, state=state)

    # Save starting game information
    save_game()
    # Play a game.
    game.play_game()
    # The game is over, save the states of the game into the database.
    process_state_data()
Пример #8
0
 def __init__(self):
     self.own_adj = HeartsAdjudicator()
     self.cards_in_hand = []
     self.id = 2
     self.agent_name = "The Low Layer"
     self.version = 1.0
Пример #9
0
class LowLayer(Agent):
    """
    An random agent who selects from available legal moves.
    """

    def __init__(self):
        self.own_adj = HeartsAdjudicator()
        self.cards_in_hand = []
        self.id = 2
        self.agent_name = "The Low Layer"
        self.version = 1.0

    def __repr__(self):
        return {"id": self.id, "name": self.agent_name, "version": self.version}

    def __str__(self):
        return self.agent_name

    def get_action(self,
                   partial_state: HeartsState):
        """
        The get_action() method inspects the state for open positions and picks one randomly.
        :param partial_state: the position vector of the game.
        :return: an Action.
        """

        # Agent picks 3 cards to pass
        if partial_state.pass_type > 0:
            # three_cards = self.passing_smart_sequence(partial_state)
            three_cards = self.passing_smart_face_values(partial_state)
            return HeartsAction(three_cards)

        for i in range(len(partial_state.deck)):
            if 0 < partial_state.deck[i] < 5:
                self.cards_in_hand.append(i)

        # Agent picks a card to play
        # elif partial_state.trick_number > 0 and len(cards_in_hand) > 0:
        else:
            choice = self.select_card(partial_state)
            self.cards_in_hand = []
            return HeartsAction(choice)

    def select_card(self,
                    partial_state: HeartsState):
        # our player is leading, choosing a random card for now
        if self.spade_lead_check(partial_state):
            suits = self.sort_suits(partial_state)

        if self.is_lead(partial_state):

            if self.spade_lead_check(partial_state):  # Draw out the Queen
                suits = self.sort_suits(partial_state)
                choice = random.choice(suits[2])

            elif self.lead_low_check(partial_state):  # Play safe and play low cards
                counter = 0
                index = []
                suits = self.sort_suits(partial_state)
                for i in suits:
                    if (len(i) > 0):
                        index.append(counter)
                    counter += 1

                pre_select = random.choice(index)
                selected_suit = suits[pre_select]
                choice = selected_suit[0]
            else:
                choice = random.choice(self.cards_in_hand)
        else:
            # we're following, not leading
            if self.not_void(partial_state):
                # Not void in the leading suit
                # pick the lowest card compared to the highest currently played
                choice = self.get_highest_low_card(partial_state)
            else:
                # Void in the leading suit
                # just randomly play for now
                choice = self.sloughing(partial_state)
        return choice

    def is_lead(self,
                partial_state: HeartsState):
        """Returns true if agent is leading currently"""
        played = partial_state.deck[partial_state.deck > 20]

        if len(played) >= 4:
            return True
        return False

    def not_void(self,
                 partial_state: HeartsState):
        """Returns true if agent is not void in the leading suit"""
        lead_suit = self.own_adj.lead_suit(partial_state)
        begin = 13 * lead_suit  # beginning of range of valid cards
        end = 13 * (lead_suit + 1)  # end of range of valid cards
        for x in self.cards_in_hand:
            if begin <= x < end:
                return True
        return False

    def get_highest_low_card(self,
                             partial_state: HeartsState):
        """Find the cards that are lowest than the card currently set to win and
        choose the highest one"""
        max_card_played = self.own_adj.find_max_card(partial_state)
        max_card_player = -1
        lead_suit = self.own_adj.lead_suit(partial_state)
        begin = 13 * lead_suit  # beginning of range of valid cards
        end = 13 * (lead_suit + 1)  # end of range of valid cards
        for x in self.cards_in_hand:
            if begin <= x < end:
                if max_card_played > x > max_card_player:
                    max_card_player = x

        # TODO might need to do something other than "just play whatever and hope for the best"
        # TODO if we end up with a hand where none of the cards are less than the current max
        if max_card_player == -1:
            max_card_player = self.cards_in_hand[0]
        return max_card_player

    def sort_suits(self,
                   partial_state: HeartsState):
        """ Sort out the Cards by Suit and return a List of the suits"""
        # Clubs - Diamond - Spades - Hearts
        cards = []
        clubs = []
        Diamond = []
        spades = []
        hearts = []
        for i in range(len(partial_state.deck)):
            if 0 < partial_state.deck[i] < 5:
                cards.append(i)

        for i in range(4):
            start = i * 13
            end = start + 13
            for card in cards:
                if i == 0:
                    if start <= card < end:
                        clubs.append(card)
                elif i == 1:
                    if start <= card < end:
                        Diamond.append(card)
                elif i == 2:
                    if start <= card < end:
                        spades.append(card)
                elif i == 3:
                    if start <= card < end:
                        hearts.append(card)

        suits = [clubs, Diamond, spades, hearts]
        return suits

    def passing_smart_sequence(self, partial_state: HeartsState):
        """
        Method one passing : Pass highest cards in trouble suits: suits where the lowest
        card is higher than any other lowest card in other suits. If the player becomes void,
        then pass off the next high cards from the next trouble suit.
        """

        sorted_cards_in_hand = self.sort_suits(partial_state)
        return self.pick_trouble_card(sorted_cards_in_hand)

    def passing_smart_face_values(self,
                                 partial_state: HeartsState):
        """
        Method 2: Average the face cards in each suit, and pass the highest cards from the suit with the
        highest average. (J = 9, Q = 10, K = 11, A = 12). Repeat if void.
        """

        sorted_hands = self.sort_suits(partial_state)
        
        cards_to_pass = []

        for card in range(3):
            # Face_value_cards is a sorted by suits list of only face cards.
            face_value_cards = [[card for card in suit if 8 < (card % 13) < 13] for suit in sorted_hands]
            # Face_value_cards modulo 13 for average calculations.
            modded_face_value_cards = [self.mod_13(suit) for suit in face_value_cards]
            # Avg_face_value is a list of averaged face value cards.
            avg_face_value = [self.average_cards(suit) for suit in modded_face_value_cards]
            
            # Calculate suit_index for first check if suit is void
            highest_average = max(avg_face_value)
            suit_index = avg_face_value.index(highest_average)

            # Check if the player has any face cards to begin with
            if (avg_face_value == [0,0,0,0]):
                # There are no face cards so move on to method1 which does not rely on that
                method1 = self.pick_trouble_card(sorted_hands)
                while (len(cards_to_pass) < 3):
                    cards_to_pass.append(method1.pop(0))
                return cards_to_pass

            if sorted_hands[suit_index]:
                # Index of the highest card in sorted_hands.
                highest_card_index = len(sorted_hands[suit_index]) - 1
                # Value of the highest card in sorted_hands.
                highest_card = sorted_hands[suit_index][highest_card_index]
                # Add to cards_to_pass.
                cards_to_pass.append(highest_card)
                sorted_hands[suit_index].remove(highest_card)

        return cards_to_pass

    @staticmethod
    def average_cards(hand):
        if not hand:
            return 0
        return sum(hand) / len(hand)

    def pick_trouble_card_suit(self, sorted_hands):
        """Choose the suit with the least amount of cards
                    """

        index = -1  # Array index
        store_pos = 0
        num_cards = -1
        for suit in sorted_hands:
            index += 1
            if len(suit) > num_cards:
                num_cards = len(suit)
                store_pos = index
        return store_pos

    def has_qs_been_played(self, partial_state: HeartsState):
        """ Return True if the queen has been play and false otherwise """
        pos = 0
        for i in range(len(partial_state.deck)):
            if (partial_state.deck[i] == 36) & (partial_state.deck[i] < 20):
                return True
        return False

    def pick_trouble_card(self, sorted_hands):
        """
        Choose the suit where the lowest card is higher than the lowest card in any other suit, and pass those
        starting with the highest card. If the trouble suit becomes void, then pick the next highest card from
        the next trouble suit.

        :param sorted_hands: sort_hands is a list of lists. Each list in sorted_hands contains the cards in hand for a
        particular suit. [ C[0, 1, 4], D[13, 15], ... etc.]
        :return cards_to_pass: Cards_to_pass is a list of the 3 cards to pass following the strategy stated above.
        """

        cards_to_pass = []
        # Remove empty suits/empty lists on the off chance that an agent is void a suit at the start of the game.
        # This prevents issues with zip() and empty lists.
        if not all(sorted_hands):
            for suit in sorted_hands:
                if not suit:
                    sorted_hands.remove(suit)
        # Mod 13 each value of each suit in order to find the lo/hi cards.
        trouble_suit = [self.mod_13(suit) for suit in sorted_hands]
        for i in range(3):
            # Remove voided suits (empty lists) from sorted_hands and trouble_suit.
            # This prevents zip() issues with empty lists.
            for suit, t_suit in zip(sorted_hands, trouble_suit):
                # Suit is void, remove empty suit list from sorted_hands and trouble_suit.
                if not suit:
                    sorted_hands.remove(suit)
                    trouble_suit.remove(t_suit)
            # Stores the value of the first indices of each suit to list: lowest_cards_in_each_suit.
            lowest_cards_in_each_suit = list(zip(*trouble_suit))[0]
            # Calculate the highest card out of the lowest cards.
            lowest_high_card = max(lowest_cards_in_each_suit)
            # Get the suit index of lowest_high_card. C = 0, D = 1, S = 2, H = 3.
            suit_index = lowest_cards_in_each_suit.index(lowest_high_card)
            # Get the value of the highest card in the trouble suit.
            highest_card_in_trouble_suit = sorted_hands[suit_index].__getitem__(len(sorted_hands[suit_index]) - 1)
            cards_to_pass.append(highest_card_in_trouble_suit)
            # Remove chosen card from the lists to account for future calculations.
            sorted_hands[suit_index].__delitem__(len(sorted_hands[suit_index]) - 1)
            trouble_suit[suit_index].__delitem__(len(trouble_suit[suit_index]) - 1)
        return cards_to_pass

    @staticmethod
    def mod_13(sorted_hands):
        return [suit % 13 for suit in sorted_hands]

    def average_suit_weight(self, Suit_list):
        """ Uses the face card values in order to calculate the average """
        sum = 0
        for cards in Suit_list:
            sum += (cards % 13) + 1
        if sum == 0:
            return 0
        return sum / len(Suit_list)

    def sloughing(self,
                  partial_state: HeartsState):
        suit_to_slough = self.bad_suit()
        begin = 13 * suit_to_slough
        end = 13 * (suit_to_slough + 1)
        max_card = -1
        for cards in self.cards_in_hand:
            if begin <= cards < end and cards > max_card:
                max_card = cards
        if max_card == -1:
            max_card = self.cards_in_hand[0]
        return max_card

    def bad_suit(self):
        suit_avg = [0, 0, 0, 0]
        counter = 0
        # count up the number of problem cards per suit
        # whichever suit has more problem cards is the one we're going to slough from
        for x in range(4):
            begin = 13 * x
            end = 13 * (x + 1)
            for cards in range(begin, end):
                if cards in self.cards_in_hand:
                    suit_avg[x] += cards % 13
                    counter += 1
            if counter != 0:
                suit_avg[x] = suit_avg[x] / counter
            counter = 0

        bad_suit_index = 0
        for suit_index in range(len(suit_avg)):
            if suit_avg[suit_index] > suit_avg[bad_suit_index]:
                bad_suit_index = suit_index

        return bad_suit_index

    def spade_lead_check(self, partial_state: HeartsState):
        """not holding the QS and not in spades trouble
              (not holding KS or AS or has enough low spades to cover for the KS or AS).
              Lead with any spades to draw out the QS."""
        # Spade in the trouble suit
        suits = self.sort_suits(partial_state)
        if self.pick_trouble_card_suit(suits) == 2:
            return False

        # Spade is the trouble suit and we have to check for QS , KS , or AS
        for i in suits[2]:
            if i == 36 | i == 35 | i == 26:
                return False

        if len(suits[2]) == 0:
            return False

        return True

    def lead_low_check(self, partial_state: HeartsState):
        """Has no spades or the QS has been played, lead with the lowest card of any suit.
            Or lead with the suit that has been played the least."""
        suits = self.sort_suits(partial_state)

        # There are spades in the hand
        if (self.has_qs_been_played(partial_state)) | (len(suits[2]) == 0):
            return True

        return False