def test_shuffle(self):
        def is_deck_shuffled(list1, list2):
            is_different = False
            for i in range(len(list1)):
                if list1[i] != list2[i]:
                    is_different = True
            return is_different

        deck = Deck()
        deck.initialize()
        list_of_cards1 = list(deck.cards)
        deck.shuffle()
        list_of_cards2 = list(deck.cards)
        self.assertTrue(is_deck_shuffled(list_of_cards1, list_of_cards2))
        deck.shuffle()
        list_of_cards3 = list(deck.cards)
        self.assertTrue(is_deck_shuffled(list_of_cards3, list_of_cards2))
Exemple #2
0
 def test_shuffle_no_seed(self, mock_seed, mock_shuffle):
     # call it twice, ensure it's the same order?
     deck = Deck()
     deck.shuffle()
     assert not mock_seed.called, 'seed was set and should not have been'
     mock_shuffle.assert_called_once_with(deck.card_list)
Exemple #3
0
 def test_shuffle_seed(self, mock_seed, mock_shuffle):
     # Assert the seed is used before shuffle is called
     deck = Deck()
     deck.shuffle(seed=1234)
     mock_seed.assert_called_once_with(1234)
     mock_shuffle.assert_called_once_with(deck.card_list)
Exemple #4
0
class GameController(object):
    """Takes a list containing each player, as well as a seed for the deck."""
    def __init__(self, players, deck_seed=False):
        num_players = len(players)
        if not 2 <= num_players <= 5:
            raise ValueError(
                "There must be between 2 and 5 players to play Hanabi.")
        for player in players:
            if not isinstance(player, Player):
                raise ValueError(
                    "All players must inherit from the Player class.")
        self.colors = ('r', 'y', 'g', 'w', 'b')  # TODO: rainbow/mixed/wilds
        self.numbers = (1, 1, 1, 2, 2, 3, 3, 4, 4, 5)
        self.players = players
        self.deck = Deck(colors=self.colors, numbers=self.numbers)
        self.deck.shuffle(seed=None)
        self.player_hands = [[] for _ in range(len(self.players))]
        self.master_game_state = GameState(Board(self.deck), self.player_hands)

    def deal_initial_hand(self):
        cards_to_deal = 5
        if len(self.players) > 3:
            cards_to_deal = 4
        for rounds in range(cards_to_deal):
            for player in range(len(self.players)):
                self.player_hands[player].append(self.deck.draw_card())
        self.master_game_state.player_hands = self.player_hands

    def game_over(self, current_player, game_state=None):
        if game_state is None:
            game_state = self.master_game_state
        # Check if we blew up
        if game_state.board.fuse_tokens < 1:
            # print("no more fuses")
            return True
        # Check if we've completed all the stacks
        MAX_STACK_SCORE = 5  # Todo: figure out a better place for a global var like this
        if game_state.board.compute_score() == (len(self.colors) *
                                                MAX_STACK_SCORE):
            # print("You win!")
            return True
        # Check if the deck is done and everyone played their final turn:
        if len(self.deck
               ) == 0 and current_player == game_state.board.game_almost_over:
            # print("game almost over")
            #print(player_id)
            return True
        # Otherwise, the engine is not over
        return False

    # Turn order: move, check end, draw card, initiate final round, next player
    def play_game(self):
        self.deal_initial_hand()
        self.master_game_state.board.deck_size = len(self.deck)
        for player_id in cycle(range(len(self.players))):
            player_game_state = PlayerGameState(self.master_game_state,
                                                player_id)
            new_move = self.players[player_id].make_move(player_game_state)
            assert isinstance(new_move, Move)
            try:
                self.master_game_state = new_move.apply(self.master_game_state)
            except AssertionError, e:
                raise Exception(
                    "{p} submitted unplayable move: {m}".format(
                        p=str(self.players[player_id]), m=str(new_move)), e)
            if self.game_over(player_id):
                game_score = self.master_game_state.board.compute_score()
                #print("Game over: Score {score}".format(score=game_score))
                return game_score
            if len(self.deck) > 0:
                self.player_hands[player_id].append(self.deck.draw_card())
                self.master_game_state.player_hands = self.player_hands
                self.master_game_state.board.deck_size = len(self.deck)
            # This triggers when the last card is drawn, every player including this one takes one more turn.
            if len(
                    self.deck
            ) == 0 and self.master_game_state.board.game_almost_over is None:
                self.master_game_state.board.game_almost_over = player_id
Exemple #5
0
class Dealer:
    def __init__(self, deck, seating, random_seed_for_shuffling=None):
        self.community_cards = []
        self.deck = deck
        self.seating = seating
        self.pot = None
        self.big_blind_size = None
        self.random_seed_for_shuffling = random_seed_for_shuffling

    def deal_cards_to_players(self):
        for player in self.seating.players:
            player.receive_cards(self.deck.draw(2))

    def move_button(self):
        self.seating.move_button()

    def collect_blinds(self, small_blind_size):
        for player in self.seating.players:
            player.money_in_pot = 0
        sb_player = self.seating.small_blind_player()
        bb_player = self.seating.big_blind_player()
        available_size_of_small_blind = min(small_blind_size, sb_player.stack)
        self.pot.player_calls(sb_player, available_size_of_small_blind)
        available_size_of_big_blind = min(small_blind_size * 2,
                                          bb_player.stack)
        self.pot.player_calls(bb_player, available_size_of_big_blind)

    def setup_deck(self):
        self.deck = Deck()
        self.deck.initialize()
        self.deck.shuffle(self.random_seed_for_shuffling)

    def add_community_cards(self, card_count):
        self.community_cards += self.deck.draw(card_count)
        for player in self.seating.players:
            player.see_community_cards(self.community_cards)
        print("Community cards: " +
              ", ".join([str(card) for card in self.community_cards]))

    def play_preflop(self, small_blind_size):
        self.big_blind_size = small_blind_size * 2
        self.pot = Pot()
        self.collect_blinds(small_blind_size)
        self.deal_cards_to_players()
        bb_player = self.seating.big_blind_player()
        amount_to_match = small_blind_size * 2
        return self.ask_players_for_actions(bb_player, amount_to_match, True)

    def play_flop(self):
        self.add_community_cards(3)
        last_player_to_go = self.seating.button_player()
        return self.ask_players_for_actions(last_player_to_go,
                                            last_player_to_go.money_in_pot,
                                            True)

    def play_turn(self):
        self.add_community_cards(1)
        last_player_to_go = self.seating.button_player()
        return self.ask_players_for_actions(last_player_to_go,
                                            last_player_to_go.money_in_pot,
                                            True)

    def play_river(self):
        self.add_community_cards(1)
        last_player_to_go = self.seating.button_player()
        winner = self.ask_players_for_actions(last_player_to_go,
                                              last_player_to_go.money_in_pot,
                                              True)
        if winner:
            return True
        else:
            for pot in self.pot.get_all_pots():
                winners = card_showdown.find_winners(pot.chips_per_player,
                                                     self.community_cards)
                players_share = int(pot.pot_size() / len(winners))
                for player in winners:
                    player.stack += players_share

    def ask_players_for_actions(self, player_who_raised, new_raised_amount,
                                include_last_player):
        next_player = self.seating.next_player_after_player(player_who_raised)
        amount_of_calls_to_make = len(self.seating.players)
        if not include_last_player:
            amount_of_calls_to_make -= 1
        for i in range(amount_of_calls_to_make):
            if next_player.cards and next_player.stack > 0:
                p_action, p_amount = next_player.act(new_raised_amount)
                if p_action == Action.ACTION_FOLD:
                    print(str(next_player) + " folds")
                    self.player_folds(next_player)
                elif p_action == Action.ACTION_CALL:
                    print(str(next_player) + " calls " + str(p_amount))
                    self.pot.player_calls(next_player, p_amount)
                elif p_action == Action.ACTION_RAISE:
                    print(str(next_player) + " raises to " + str(p_amount))
                    self.pot.player_calls(next_player, p_amount)
                    return self.ask_players_for_actions(
                        next_player, p_amount, False)
                if self.is_winner_determined():
                    winner = list(self.pot.chips_per_player.keys())[0]
                    winner.stack += self.pot.pot_size()
                    return True
            next_player = self.seating.next_player_after_player(next_player)
        return False

    def is_winner_determined(self):
        return len(self.pot.chips_per_player) == 1

    def player_folds(self, player):
        player.money_in_pot = 0
        player.release_cards()
        if player in self.pot.chips_per_player:
            self.pot.size += self.pot.chips_per_player[player]
            self.pot.chips_per_player.pop(player, None)