Exemple #1
0
    def play_trick(self, leading_index, trick_nr):
        """
        Simulate a single trick.
        leading_index contains the index of the player that must begin.
        """
        player_index = leading_index
        trick = []
        are_hearts_broken = self.are_hearts_broken()
        for _ in range(4):
            player = self.players[player_index]
            player_hand = self._player_hands[player_index]
            played_card = player.play_card(player_hand, trick, trick_nr,
                                           are_hearts_broken)
            if not is_card_valid(player_hand, trick, played_card, trick_nr,
                                 are_hearts_broken):
                raise ValueError(
                    'Player {} ({}) played an invalid card {} to the trick {}.'
                    .format(player_index,
                            type(player).__name__, played_card, trick))
            trick.append(played_card)
            self._player_hands[player_index].remove(played_card)
            player_index = (player_index + 1) % 4

        for player in self.players:
            player.see_played_trick(trick, trick_nr)

        winning_index = self.winning_index(trick)
        winning_player_index = (leading_index + winning_index) % 4
        self.say('Player {} won the trick {}.', winning_player_index, trick)
        self._cards_taken[winning_player_index].extend(trick)
        return winning_player_index
Exemple #2
0
    def step(self, played_card=None):
        player_hand = self._player_hands[self.current_player_idx]

        if played_card is None:
            played_card = self.players[self.current_player_idx].play_card(self)

        if not is_card_valid(player_hand, self.trick, played_card,
                             self.trick_nr, self.is_heart_broken):
            raise ValueError('Player {} ({}) played an invalid card {} to the trick {}.'.format(\
                self.current_player_idx, type(self.players[self.current_player_idx]).__name__, played_card, self.trick))

        if played_card not in self._player_hands[self.current_player_idx]:
            raise ValueError("Not found {} card in this Player-{} hand cards({})".format(\
                played_card, self.current_player_idx, self._player_hands[self.current_player_idx]))

        self._player_hands[self.current_player_idx].remove(played_card)
        self.trick.append(played_card)

        for i in range(4):
            self.players[i].see_played_trick(played_card, self)

        for idx, card in zip(range(4, 0, -1), self.trick[::-1]):
            player_idx = (self.current_player_idx + idx) % 4
            self.trick_cards[self.trick_nr][player_idx] = card

        self.current_player_idx = (self.current_player_idx + 1) % 4
        if len(self.trick) == 4:
            self.round_over()
Exemple #3
0
    def play_card(self, hand, trick, trick_nr, are_hearts_broken):
        # Lead with a low card
        if not trick:
            hand.sort(key=lambda card:
                      100 if not are_hearts_broken and card.suit == Suit.hearts else
                      card.rank.value)
            return hand[0]

        hand.sort(key=self.undesirability, reverse=True)
        self.say('Hand: {}', hand)
        self.say('Trick so far: {}', trick)

        # Safe cards are cards which will not result in winning the trick
        leading_suit = trick[0].suit
        max_rank_in_leading_suit = max([card.rank for card in trick
                                        if card.suit == leading_suit])
        valid_cards = [card for card in hand
                       if is_card_valid(hand, trick, card, trick_nr, are_hearts_broken)]
        safe_cards = [card for card in valid_cards
                      if card.suit != leading_suit or card.rank <= max_rank_in_leading_suit]

        self.say('Valid cards: {}', valid_cards)
        self.say('Safe cards: {}', safe_cards)

        try:
            return safe_cards[0]
        except IndexError:
            queen_of_spades = Card(Suit.spades, Rank.queen)
            # Don't try to take a trick by laying the queen of spades
            if valid_cards[0] == queen_of_spades and len(valid_cards) > 1:
                return valid_cards[1]
            else:
                return valid_cards[0]
Exemple #4
0
    def play_trick(self, leading_index, trick_nr):
        """
        Simulate a single trick.
        leading_index contains the index of the player that must begin.
        """
        player_index = leading_index
        trick = []
        are_hearts_broken = self.are_hearts_broken()
        for _ in range(4):
            player = self.players[player_index]
            player_hand = self._player_hands[player_index]
            played_card = player.play_card(player_hand, trick, trick_nr, are_hearts_broken)
            if not is_card_valid(player_hand, trick, played_card, trick_nr, are_hearts_broken):
                raise ValueError('Player {} ({}) played an invalid card {} to the trick {}.'
                                 .format(player_index, type(player).__name__, played_card, trick))
            trick.append(played_card)
            self._player_hands[player_index].remove(played_card)
            player_index = (player_index + 1) % 4

        for player in self.players:
            player.see_played_trick(trick, trick_nr)

        winning_index = self.winning_index(trick)
        winning_player_index = (leading_index + winning_index) % 4
        self.say('Player {} won the trick {}.', winning_player_index, trick)
        self._cards_taken[winning_player_index].extend(trick)
        return winning_player_index
Exemple #5
0
 def play_card(self, hand, trick, trick_nr, are_hearts_broken):
     # Play first card that is valid
     for card in hand:
         if is_card_valid(hand, trick, card, trick_nr, are_hearts_broken):
             return card
     raise AssertionError(
         'Apparently there is no valid card that can be played. This should not happen.'
     )
Exemple #6
0
 def play_card(self, hand, trick, trick_nr, are_hearts_broken):
     # Play first card that is valid
     for card in hand:
         if is_card_valid(hand, trick, card, trick_nr, are_hearts_broken):
             return card
     raise AssertionError(
         'Apparently there is no valid card that can be played. This should not happen.'
     )
Exemple #7
0
    def get_valid_cards(self, hand, game):
        cards = [
            card for card in hand if is_card_valid(
                hand, game.trick, card, game.trick_nr, game.is_heart_broken)
        ]
        cards.sort(key=lambda x: self.undesirability(x, game.take_pig_card),
                   reverse=(True if game.trick else False))

        return cards
Exemple #8
0
    def play_card(self, game):
        hand = game._player_hands[game.current_player_idx]

        # Play first card that is valid
        shuffle(hand)
        for card in hand:
            if is_card_valid(hand, game.trick, card, game.trick_nr,
                             game.is_heart_broken):
                return card

        game.verbose = True
        game.print_game_status()
        raise AssertionError(
            'Apparently there is no valid card that can be played. This should not happen.'
        )
Exemple #9
0
    def step(self, played_card=None):
        hand_cards = self._player_hands[self.current_player_idx]

        if played_card is None:
            played_card, results = self.players[
                self.current_player_idx].play_card(
                    self, simulation_time_limit=self.simulation_time_limit)

        if not is_card_valid(hand_cards, self.trick, played_card,
                             self.trick_nr, self.is_heart_broken):
            raise ValueError('{} round - Player {} ({}) played an invalid card {}({}) to the trick {}.'.format(\
                self.trick_nr, self.current_player_idx, type(self.players[self.current_player_idx]).__name__, played_card, hand_cards, self.trick))

        if played_card not in self._player_hands[self.current_player_idx]:
            raise ValueError("{} round - Not found {} card in this Player-{} hand cards({})".format(\
                self.trick_nr, played_card, self.current_player_idx, self._player_hands[self.current_player_idx]))

        possible_cards = [[], [], [], []]
        possible_cards[self.current_player_idx] = hand_cards

        for player_idx, info in self.players[
                self.current_player_idx].void_info.items():
            if player_idx != self.current_player_idx:
                possible_cards[player_idx] = self.players[
                    self.current_player_idx].get_remaining_cards(hand_cards)[:]
                for suit, is_void in sorted(info.items(), key=lambda x: x[0]):
                    if is_void:
                        for card in possible_cards[player_idx][:]:
                            if card.suit == suit:
                                possible_cards[player_idx].remove(card)
                                #print("try to remove {} card from player-{}, current_suit is {}, {}".format(\
                                #    card, player_idx, suit, info))

        for player_idx, cards in self.players[
                self.current_player_idx].transfer_cards.items():
            for idx in range(len(possible_cards)):
                if idx != player_idx:
                    for card in cards:
                        if card in possible_cards[idx]:
                            possible_cards[idx].remove(card)

        trick_cards = self.trick

        valid_cards, probs = [], [0] * 52
        for card, prob in results:
            valid_cards.append(card)
            probs[card2v(card)] = prob

        probs = log_softmax(probs)

        leading_cards = len(self.trick) == 0
        expose_cards = self.expose_info

        self._short_memory.append([
            self.current_player_idx, self.trick_cards, self.score_cards,
            possible_cards, trick_cards, valid_cards, leading_cards,
            expose_cards, probs, None
        ])

        if IS_DEBUG:
            print_a_memory(self._short_memory[-1])

        self._player_hands[self.current_player_idx].remove(played_card)
        self.trick.append(played_card)

        if len(self.trick) == 4:
            for idx, card in zip(range(4, 0, -1), self.trick[::-1]):
                player_idx = (self.current_player_idx + idx) % 4
                self.trick_cards[self.trick_nr][player_idx] = card

        for i in range(4):
            self.players[i].see_played_trick(played_card, self)

        self.current_player_idx = (self.current_player_idx + 1) % 4

        if len(self.trick) == 4:
            self.round_over()