示例#1
0
def run(players, verbose=False):
    assert len(players) >= 2

    names = []
    for i in range(len(players)):
        if players[i].name is None:
            names.append("Player {}".format(i + 1))
        else:
            names.append("{} (Player {})".format(players[i].name, i + 1))

    new_env = BigTwoEnv(num_players=len(players))
    state = new_env.reset()
    num_finished = 0
    done = False
    while not done:
        cur_turn = state.turn
        must_pass = False

        if state.pass_only[cur_turn] or state.player_card_count[cur_turn] == 0:
            must_pass = True
            if verbose:
                print("\n{} must pass.".format(names[cur_turn]))
            action = CardCollection()
        else:
            if verbose:
                print("\n{}'s turn to play {}.".format(names[cur_turn],
                                                       state.mode))
            action = players[cur_turn].get_action(state)

        state, reward = new_env.step(action)
        done = state.done
        if not must_pass:
            if verbose:
                print("Played action {} and obtained reward {}.".format(
                    action, reward))
            else:
                if action.num_cards() > 0:
                    print("{} played {}.".format(names[cur_turn], action))
                else:
                    print("{} passed.".format(names[cur_turn]))

        if state.player_card_count[cur_turn] == 0 and action.num_cards() > 0:
            if num_finished == 0:
                print("{} finished in 1st place!".format(names[cur_turn]))
            elif num_finished == 1:
                print("{} finished in 2nd place!".format(names[cur_turn]))
            elif num_finished == 2:
                print("{} finished in 3rd place!".format(names[cur_turn]))
                for i in range(len(players)):
                    if state.player_card_count[i] > 0:
                        print("{} lost and had the remaining cards: {}".format(
                            names[i], new_env.player_cards[i]))
            num_finished += 1
示例#2
0
    def get_valid_moves(self):
        if self.done:
            return []
        if self.pass_only[self.turn]:
            return [CardCollection()]

        possible_plays = []
        if self.mode == "any" or self.mode == "single":
            possible_plays.extend(search_plays(self.hand, "single"))
        if self.mode == "any" or self.mode == "double":
            possible_plays.extend(search_plays(self.hand, "double"))
        if self.mode == "any" or self.mode == "triple":
            possible_plays.extend(search_plays(self.hand, "triple"))
        if self.mode == "any" or self.mode == "quad":
            possible_plays.extend(search_plays(self.hand, "quad"))
        if self.mode == "any" or self.mode == "fivecard":
            possible_plays.extend(search_plays(self.hand, "straight"))
            flushes = search_plays(self.hand, "flush")
            pure_flushes = []
            for f in flushes:
                play, _ = identify_play(f)
                if play == "flush":
                    pure_flushes.append(f)
            possible_plays.extend(pure_flushes)
            possible_plays.extend(search_plays(self.hand, "fullhouse"))
        else:
            possible_plays.extend(search_plays(self.hand, "straightflush"))

        possible_plays.extend(search_plays(self.hand, "bomb"))

        valid_plays = []
        if self.start:
            for play in possible_plays:
                if play.contains(Card(3, 'C')):
                    valid_plays.append(play)
            return valid_plays
        else:
            if self.mode == "any":
                return possible_plays
            else:
                valid_plays.append(CardCollection())
                for play in possible_plays:
                    if compare_plays(play, self.last_play) == 1:
                        valid_plays.append(play)
                return valid_plays
示例#3
0
    def get_action(self, state):
        print("Your hand contains: {}".format(state.hand))

        cards_to_play = []
        played_cards = 0
        command = None
        while command != "END" and command != "PASS" and played_cards < 5:
            command = input("Enter a card to play -> ")
            command = command.upper()
            if command != "END" and command != "PASS":
                try:
                    card = Card.str_to_card(command)
                    cards_to_play.append(card)
                    played_cards += 1
                except UnrecognizedCardException:
                    print("That command is invalid. Please try again.")
        return CardCollection(cards_to_play)
示例#4
0
    def reset(self):
        deck = Deck()
        deck.shuffle()
        self.player_cards = [
            sort_cards(hand) for hand in deck.deal(self.num_players)
        ]
        self.player_card_count = [pc.num_cards() for pc in self.player_cards]
        self.history = [CardCollection()]
        self.last_play = None
        self.pass_only = [False] * self.num_players
        self.mode = "any"
        self.start = True
        self.done = False

        for i in range(len(self.player_cards)):
            if self.player_cards[i].contains(Card(3, 'C')):
                self.turn = i

        return self.get_state()
示例#5
0
def sort_cards(cards):
    new_cards = sorted(cards.cards, key=get_card_value)
    return CardCollection(new_cards)
示例#6
0
    def step(self, action):
        valid = self.is_valid(action)
        if not valid:
            if self.start:
                action = CardCollection([Card(3, 'C')])
                print(
                    "Warning: invalid play was submitted, playing 3C single..."
                )
            elif self.mode == "any":
                chosen_card = self.player_cards[self.turn].cards[0]
                action = CardCollection([chosen_card])
                print(
                    "Warning: invalid play was submitted, playing {} single..."
                    .format(chosen_card))
            else:
                action = CardCollection()
                print("Warning: invalid play was submitted, passing turn...")

        play, play_rep = identify_play(action)
        if self.mode == "any":
            if play == "single" or play == "double" or play == "triple" or play == "quad":
                self.mode = play
            else:
                self.mode = "fivecard"

        if play == "bomb" or play == "straightflush":
            self.mode = "fivecard"

        if play == "pass":
            self.pass_only[self.turn] = True
            if len(self.history) >= (self.num_players - 2):
                all_pass = True
                for past_play in self.history[-(self.num_players - 2):]:
                    if past_play.num_cards() != 0:
                        all_pass = False
                if all_pass:
                    self.pass_only = [False] * self.num_players
                    self.mode = "any"

        reward = action.num_cards() / 5.0

        self.player_cards[self.turn].subtract(action)
        self.player_card_count[self.turn] -= action.num_cards()
        self.history.append(action)
        if play != "pass":
            self.last_play = action
        self.start = False

        nonzero = 0
        for count in self.player_card_count:
            if count > 0:
                nonzero += 1
        if self.player_card_count[self.turn] == 0 and play != "pass":
            reward += 2.0 * nonzero
        if nonzero <= 1:
            self.done = True

        self.turn = (self.turn + 1) % self.num_players

        while self.mode == "any" and self.player_card_count[self.turn] == 0:
            self.turn = (self.turn - 1) % self.num_players

        return self.get_state(), reward
示例#7
0
 def _collection_combination(iterable, num):
     return [
         CardCollection(list(hand)) for hand in combinations(iterable, num)
     ]
示例#8
0
def search_plays(hand, type):
    def _collection_combination(iterable, num):
        return [
            CardCollection(list(hand)) for hand in combinations(iterable, num)
        ]

    def _enumerate_multiples(hand, num):
        plays = []
        cur_rank = None
        start_ind = 0
        counter = 0
        for i in range(hand.num_cards()):
            if hand.cards[i].rank == cur_rank:
                counter += 1
            else:
                if counter >= num:
                    plays.extend(
                        _collection_combination(hand.cards[start_ind:i], num))
                cur_rank = hand.cards[i].rank
                start_ind = i
                counter = 1

        if counter >= num:
            plays.extend(_collection_combination(hand.cards[start_ind:], num))

        return plays

    def _enumerate_straights(cards, c_count):
        if len(c_count) == 1:
            return [[card] for card in cards]

        straights = []
        for i in range(c_count[0]):
            sub_straights = _enumerate_straights(cards[c_count[0]:],
                                                 c_count[1:])
            for s in sub_straights:
                new_s = [cards[i]]
                new_s.extend(s)
                straights.append(new_s)

        return straights

    hand = sort_cards(hand)
    if hand.num_cards() == 0:
        return []

    if type == "single":
        return [CardCollection([card]) for card in hand.cards]
    elif type == "double":
        return _enumerate_multiples(hand, 2)
    elif type == "triple":
        return _enumerate_multiples(hand, 3)
    elif type == "quad":
        return _enumerate_multiples(hand, 4)
    elif type == "bomb":
        possible_plays = []
        quads = _enumerate_multiples(hand, 4)
        for q in quads:
            for card in hand.cards:
                if q.cards[0].rank != card.rank:
                    possible_plays.append(
                        CardCollection.merge_collections(
                            (q, CardCollection([card]))))
        return possible_plays
    elif type == "fullhouse":
        possible_plays = []
        doubles = _enumerate_multiples(hand, 2)
        triples = _enumerate_multiples(hand, 3)
        for d in doubles:
            for t in triples:
                if d.cards[0].rank != t.cards[0].rank:
                    possible_plays.append(
                        CardCollection.merge_collections((d, t)))
        return possible_plays
    elif type == "straight":
        possible_plays = []
        c_count = [0] * 15
        end_cards = []
        for card in hand.cards:
            c_count[card.rank - 1] += 1
            if card.rank == 1 or card.rank == 2:
                c_count[card.rank + 12] += 1
                end_cards.append(card)
        end_cards.extend(hand.cards)

        last_zero = -1
        cumul_start = 0
        cumul_cur = 0
        for i in range(len(c_count)):
            if c_count[i] == 0:
                last_zero = i
                cumul_start = cumul_cur
            else:
                cumul_cur += c_count[i]
                if i - last_zero >= 5:
                    play_list = _enumerate_straights(
                        end_cards[cumul_start:cumul_cur], c_count[i - 4:i + 1])
                    possible_plays.extend(
                        [CardCollection(c_list) for c_list in play_list])
                    cumul_start += c_count[i - 4]
        return possible_plays
    elif type == "flush":
        possible_plays = []
        card_suits = {'C': [], 'D': [], 'H': [], 'S': []}
        for card in hand.cards:
            card_suits[card.suit].append(card)
        for suit in card_suits:
            possible_plays.extend(_collection_combination(card_suits[suit], 5))
        return possible_plays
    elif type == "straightflush":
        possible_plays = []
        flushes = search_plays(hand, "flush")
        for f in flushes:
            play, _ = identify_play(f)
            if play == "straightflush":
                possible_plays.append(f)
        return possible_plays
    else:
        raise InvalidHandTypeException("That hand type is not recognized.")