Esempio n. 1
0
    def test_shuffle(self, shuffle_mock):
        number = 1

        deck = Deck(number)
        deck.shuffle()

        shuffle_mock.assert_called_with(deck.cards)
    def test_shuffle_changes_cards_order(self):
        d = Deck()

        for _ in range(0, 4):
            deck_before = d.deck.copy()
            self.assertEqual(None, d.shuffle())
            self.assertNotEqual(d.deck, deck_before)
Esempio n. 3
0
class DeckTest(unittest.TestCase):
    def setUp(self):
        self.deck = Deck()

    def test_deck_reshuffle(self):
        self.assertIsNotNone(self.deck.cards)
        self.assertListEqual(self.deck.dealt, [])

    def test_generate_deck(self):
        new_deck = self.deck._generate()
        
        self.assertIsInstance(new_deck, list)
        self.assertEqual(len(set(new_deck)), 52)
        self.assertEqual(len(new_deck[0]), 2)

    def test_shuffle(self):
        old_deck = list(self.deck.cards)
        self.deck.shuffle()
        new_deck = list(self.deck.cards)

        self.assertEqual(len(old_deck), len(new_deck))
        self.assertNotEqual(old_deck, new_deck)
        self.assertEqual(sum([1 for card in self.deck.cards if card in old_deck]), len(old_deck))

    def test_deal(self):
        for n in [0, 1, 2, 52]:
            with self.subTest(n=n):
                old_deck = list(self.deck.cards)
                
                if n <=0:
                    with self.assertRaises(AssertionError):
                        self.deck.deal(n_cards=n)
                elif n > len(old_deck):
                    with self.assertRaises(DeckException):
                        self.deck.deal(n_cards=n)
                else:
                    dealt = self.deck.deal(n_cards=n)
                    dealt.reverse()

                    self.assertEqual(len(self.deck.cards), len(old_deck) - n)
                    self.assertEqual(len(dealt), n)
                    self.assertListEqual(old_deck[-n:], dealt)
                    self.assertNotIn(dealt[0], self.deck.cards)
Esempio n. 4
0
def play_blackjack(chips=Account('Chris', 500)):
    """
    Play BlackJack
    :param chips: object
    :return:
    """

    # request a name be entered if one isn't present
    while not len(chips.name):
        try:
            named = input('What\'s your name? ')

            if named.isalpha():
                chips.name = named
                break
            else:
                print(
                    f"{named} is not a valid name, please enter a valid name")
                continue

        except:
            print(
                'Sorry something went wrong, please try and input your name again'
            )
            continue

    # Add fund to account if none is present
    if not chips.has_funds():
        chips.add_funds()
    # Add bet if none has been placed
    while not chips.has_bet():
        chips.make_bet()

    # Build deck and shuffle
    deck = Deck()
    deck.shuffle()

    deal_count = 1
    player = Hand()
    dealer = Hand()
    player.cards = []
    dealer.cards = []
    # Start first phase of the dealing
    while deal_count <= 4:
        deal_count += 1
        if deal_count % 2 == 0:
            if deal_count == 4:
                the_fourth_card = deck.deal()
                the_fourth_card.hide_card()
                dealer.add_card(the_fourth_card)
            else:
                dealer.add_card(deck.deal())

        else:
            player.add_card(deck.deal())

    # Second phase of the dealing
    while True:
        # display cards
        clear()
        print(chips.name + ': ')
        print(player)
        print('Dealers: ')
        print(dealer)

        if player.bust():
            break
        if player.next_move():
            player.add_card(deck.deal())
            continue
        else:
            break

    # change view permissions
    for card in dealer.cards:
        card.show_card()

    # Once player finishes turn continue to deal dealers hand
    while True:
        # display cards
        clear()
        print(chips.name + ': ')
        print(player)
        print('Dealers: ')
        print(dealer)

        if dealer.bust():
            break
        if player.bust():
            break
        if dealer.total() > player.total():
            break
        else:
            dealer.add_card(deck.deal())
            continue

    # display results and finalise transaction
    if player.bust():
        clear()
        chips.subtract()
        print(
            f"{chips.name} you lost this one\n\nYour new Balance {chips.balance()}\n"
            f"{chips.name}: {player}"
            f"Dealers: {dealer}"
            f"\nYour Score {player.total()}\nDealers Score {dealer.total()}")

    elif player.total() < dealer.total() and not dealer.bust():
        clear()
        chips.subtract()
        print(
            f"{chips.name} the dealer beat your score\n\nYour new Balance {chips.balance()}\n"
            f"{chips.name}: {player}"
            f"Dealers: {dealer}"
            f"\nYour Score {player.total()}\nDealers Score {dealer.total()}")

    else:
        clear()
        chips.add()
        print(f"{chips.name} you won!\n\nYour new Balance {chips.balance()}\n"
              f"{chips.name}: {player}"
              f"Dealers: {dealer}"
              f"\nYour Score {player.total()}\nDealers Score {dealer.total()}")

    # Do they want to replay
    while True:
        try:
            replay = input('Do you want to play again? ').upper()

            if replay == 'YES':
                play_blackjack()
                break
            elif replay == 'NO':
                print(
                    f'{chips.name} thank you for playing and we look forward to seeing you again'
                )
                break
            else:
                print(
                    'We didn\'t understand your request, a YES or NO is desired'
                )
                continue
        except ValueError:
            print(
                'Invalid Input: We didn\'t recognise your request please try again YES or No'
            )
            continue
Esempio n. 5
0
class Game:
    deck: Deck

    def __init__(self, players, dealer):
        self.players = players
        self.dealer = dealer

    def clean_cards(self):
        for player in self.players:
            player.cards = []
        self.dealer.cards = []

    def game_loop(self):
        while True:
            self.single_game()

            print('\nGame finished')

            for player in self.players:
                if player.budget < 2:
                    print(f'Out of budget, {player.name}. Bye!')
                    self.players.remove(player)

            if not self.players:
                break

            print('\nContinue?')
            if get_answer() == 'n':
                break

    def single_game(self):
        print_header('Make your bets')
        self.make_bets()

        print_header('Preparing the deck')
        self.prepare_deck(1)

        print_header('Dealing cards')
        self.clean_cards()
        self.deal_start_cards()

        self.print_participants_cards()

        print_header('Make your moves')
        self.each_player_makes_move()

        self.print_participants_cards()

        print_header('Dealer exposes cards')
        self.dealer.expose_cards()

        self.print_participants_cards()

        self.dealer_makes_move()

        print_header('Game end state:')
        self.print_participants_cards()

        print_header('Winners')
        self.determine_winner()

    def prepare_deck(self, count):
        self.deck = Deck(count)
        self.deck.shuffle()

    def make_bets(self):
        for player in self.players:
            player.make_bet()

    def deal_start_cards(self):
        for player in self.players:
            player.cards.extend(self.deck.get(exposed=2))
        self.dealer.cards.extend(self.deck.get(exposed=1, hidden=1))

    def print_participants_cards(self):
        for number, player in enumerate(self.players + [self.dealer]):
            player.print_summary()
            print('\n')

    def each_player_makes_move(self):
        for player in self.players:
            while player.determine_points() <= 21:
                action = player.make_move()
                if action == 'stand':
                    break
                player.cards.extend(self.deck.get(exposed=1))
                player.print_summary()

    def dealer_makes_move(self):
        while True:
            action = self.dealer.make_move()
            if action == 'stand':
                break
            self.dealer.cards.extend(self.deck.get(exposed=1))
            self.dealer.print_summary()

    def _win(self, player, multiplier=1):
        amount = player.current_bet * multiplier
        player.budget += amount
        self.dealer.budget -= amount
        print(f'\n{player.name} wins this time! (${amount})\n')

    def _lose(self, player):
        amount = player.current_bet
        player.budget -= amount
        self.dealer.budget += amount
        print(f'\n{player.name} loses this time. (${amount})\n')

    def determine_winner(self):
        dealer_points = self.dealer.determine_points()
        for player in self.players:
            player_points = player.determine_points()
            if player_points == 21 and dealer_points != 21:
                self._win(player, 2)
            elif dealer_points > 21 and player_points <= 21:
                self._win(player)
            elif player_points > 21:
                self._lose(player)
            elif player_points > dealer_points:
                self._win(player)
            elif player_points < dealer_points:
                self._lose(player)
            else:
                print(f'Push! No loses for {player.name}')
Esempio n. 6
0
class Blackjack:
    shuffle_counter = 0
    max_deals = 50

    def __init__(self, players):
        self.deck = Deck()
        self.deck.shuffle()
        self.dealer = Dealer()
        self.players = players
        self.player_records = {player: PlayerRecord(
            player) for player in players}

    def start_round(self):
        logger.info('[START]')
        logger.info('[CARDS] {0}'.format(
            list(card.value for card in self.deck.cards)))

        self.deal_starting_hands()
        self.pay_out_naturals()
        self.run_main_loop()
        results = self.generate_round_results()
        self.reset_records()
        return results

    def deal_starting_hands(self):
        for player in self.players:
            self.player_records[player].bet = player.get_bet()
            self.deal_card(player)
        self.deal_card(self.dealer)
        for player in self.players + [self.dealer]:
            self.deal_card(player)

    def pay_out_naturals(self):
        dealer = self.dealer
        players = self.players
        players_with_naturals = [
            player for player in players if player.has_natural()]

        if dealer.has_natural():
            for player in players:
                if player not in players_with_naturals:
                    self.end_player_turn(player, 'L')
                else:
                    self.end_player_turn(player, 'D')
        else:
            for player in players_with_naturals:
                self.end_player_turn(player, 'W', True)

    def run_main_loop(self):
        active_players = self.get_active_players()
        dealer = self.dealer
        while len(active_players) > 0:
            for player in active_players:
                if player.will_hit():
                    self.deal_card(player)
                    if player.hand.get_score() > 21:
                        self.end_player_turn(player, 'L')
                else:
                    self.stand(player)
            active_players = self.get_active_players()
            logger.info('[ROUND] {0} active players left'.format(
                len(active_players)))

        while dealer.will_hit():
            self.deal_card(dealer)
        dealer_score = dealer.hand.get_score()

        for player in self.get_standing_players():
            player_score = player.hand.get_score()
            if dealer_score > 21:
                result = 'W'
            else:
                if player_score == dealer_score:
                    result = 'D'
                elif player_score > dealer_score:
                    result = 'W'
                else:
                    result = 'L'
            self.end_player_turn(player, result)

    def generate_round_results(self):
        results = []
        for player in self.players:
            record = self.player_records[player]
            player_score = player.hand.get_score()
            dealer_score = self.dealer.hand.get_score()
            bet = record.bet
            balance = player.balance
            result = record.result
            results.append(Result(
                player, player_score, dealer_score, bet, balance, result))
        return results

    def reset_records(self):
        for player in self.players:
            self.player_records[player].reset()
        self.dealer.reset()

    def get_active_players(self):
        return [player for player in self.players
                if self.player_records[player].is_player_active()]

    def get_standing_players(self):
        return [player for player in self.players
                if self.player_records[player].is_standing]

    def set_player_finished(self, player, result):
        record = self.player_records[player]
        record.in_game = False
        record.result = result

    def end_player_turn(self, player, result, natural=False):
        """
        End turn with provided result and split bets accordingly.

        Arguments:
        player  -- Currently playing
        result  -- ['W', 'L', 'D'] for win, loss or draw
        natural -- Indicates if the player has a natural 21
        """
        logger.info('[RESULT] {0}: {1}'.format(player, result))
        bet = self.player_records[player].bet
        if result == 'W':
            if natural:
                bet = bet * 1.5
            self.dealer.pay(player, bet)
        elif result == 'L':
            player.pay(self.dealer, bet)

        self.set_player_finished(player, result)

    def notify_players(self, card, is_dealer):
        for player in self.players:
            player.on_card_dealt(card, is_dealer)

    def notify_players_shuffle(self):
        for player in self.players:
            player.on_shuffle()

    def deal_card(self, player, face_up=True):
        card = self.deck.deal()
        logger.info('[HIT] ({0}) {1}'.format(player, card))
        player.hand.add_card(card)
        if face_up:
            self.notify_players(card, player == self.dealer)
        if self.shuffle_counter > self.max_deals:
            self.notify_players_shuffle()
            self.deck.shuffle()
            self.shuffle_counter = 0
        self.shuffle_counter += 1

    def stand(self, player):
        self.player_records[player].is_standing = True
        logger.info('[STAND] ({0})'.format(player))
Esempio n. 7
0
class Game:
    def __init__(self, players_file):
        """
        A new game
            - registered players are taken from input file
            - dealer gets 1000
            - a new fresh deck
            - deck is shuffled
        """
        self.players = Players(players_file)
        self.dealer = Dealer(1000)
        self.deck = Deck()
        self.deck.log()
        self.deck.shuffle()
        self.deck.log()
        self.rounds_played = 0
        self.total_bets = 0
        self.__outcome = game_outcome(self)

    def run(self):
        """
        Game main
        """
        # set the bets
        self.__set_bets()
        # deal cards
        self.__deal_first_hand()
        # log current game state
        self.log()
        # ask each player - (h)it or (s)tand?
        self.__players()
        # dealer's turn
        self.__dealer()
        # game's outcome
        self.__outcome.get()
        # see who's broke
        self.__check_players_for_money()
        # show the round's results
        self.__show_outcome()
        # reset for a new game
        self.__reset()

    def __deal_first_hand(self):
        """
        Deals the first hand:
            - player 1, 2, 3, 4 first card
            - dealer           only card
            - player 1, 2, 3, 4 second card
        """
        log_and_print('')
        log_and_print(" > Dealing cards", end='')
        # players first card
        for player in self.players.players:
            delay()
            player.draw_card(self.deck.draw_card())

        # dealer
        delay()
        self.dealer.draw_card(self.deck.draw_card())

        # players second card
        for player in self.players.players:
            delay()
            player.draw_card(self.deck.draw_card())
        log_and_print('')

    def __set_bets(self):
        """
        Ask all the players to place their bets
        """
        log.debug('Setting bets...')
        for player in self.players.players:
            self.total_bets += player.bet()

    def hit(self, player):
        card = self.deck.draw_card()
        player.draw_card(card)

        log_and_print('\t\t>> %s drew a card - [%s]' %
                      (player.nume, str(card)))

        if (player.get_cards_sum() == 21):
            log_and_print('\t\t>> %s ' % (player.display_name()))

        if (player.get_cards_sum() > 21):
            player.lost = True
            log_and_print('\t\t>> %s is done' % (player.display_name()))
            return -1

        return 0

    def stand(self, player):
        log_and_print('\t\t>> %s stands [sum=%d]' %
                      (player.display_name(), player.get_cards_sum()))
        log_and_print('-' * 80)

    def players_in_game(self):
        return len(self.players.get())

    def new_round(self):
        answer = ' '
        while answer != 'y' and answer != 'n':
            if self.rounds_played > 0:
                msg = "\nFancy another round? (Y)es or (N)o: "
            else:
                msg = "\nShall we begin a game?  (Y)es or (N)o: "
            answer = input(msg).lower()
        if answer == 'y':
            self.rounds_played += 1
            # check if we need a new deck
            self.__new_deck()

        return answer == 'y'

    def log(self):
        """
        Log current game state
        """
        # header
        log_and_print('')
        log.debug('-' * 80)
        log.debug('-- GAME STATE')
        log.debug('')

        # deck
        self.deck.log()
        log.debug('')

        fmt = ' %12s[%4d$] : %24s'

        # dealer
        log_and_print(fmt % (self.dealer.nume, self.dealer.jetoane,
                             self.dealer.get_cards_str()))
        # players
        for player in self.players.players:
            log_and_print(
                fmt % (player.nume, player.jetoane, player.get_cards_str()))

        # footer
        log.debug('-' * 80)
        log_and_print('')

    def __everyone_lost(self):
        """
        Return True if everyone lost :(
        """
        return (self.dealer.lost
                and len(self.players.get_losers()) == len(self.players.get()))

    def __all_players_lost(self):
        """
        Return True if all players lost lost :(
        """
        return (len(self.players.get_losers()) == len(self.players.get()))

    def __show_outcome(self):
        """
        Log current round's status
        """
        # header
        log_and_print('')
        log.debug('-' * 80)
        log.debug('-- ROUND RESULT')
        log.debug('')

        # deck
        self.deck.log()
        log.debug('')

        # print format
        # ' name[money] : cards list | cards sum - [WON/LOST] bet_value
        fmt = ' %12s[%4s$] : %24s | %2s | %5s %4s$'
        fmt_l = ' %12s[%4d$] LOST'
        fmt_b = ' %12s[%4d$]'

        # print header
        log_and_print(fmt % ('Name', 'Amt', 'Card list', 'S', 'Stats', ''))
        log_and_print('-' * 66)

        # all lost
        if self.__everyone_lost():
            # dealer
            log_and_print(fmt_l % (self.dealer.nume, self.dealer.jetoane))
            # players
            for player in self.players.players:
                log_and_print(fmt_l % (player.nume, player.jetoane))
        else:
            # dealer
            log_and_print(
                fmt %
                (self.dealer.nume, self.dealer.jetoane,
                 self.dealer.get_cards_str(), self.dealer.get_cards_sum(),
                 "+" if self.dealer.balance >= 0 else "-",
                 str(abs(self.dealer.balance))))
            # players
            for player in self.players.players:
                log_and_print(
                    fmt % (player.nume, player.jetoane, player.get_cards_str(),
                           player.get_cards_sum(), "-" if player.lost else "+",
                           str(player.bet_value)))

        # bankrupts
        if len(self.players.broke_players) > 0:
            log_and_print('')
            log_and_print('Went bankrupt: ')
            for player in self.players.broke_players:
                log_and_print(fmt_b % (player.nume, player.jetoane))

    def __new_deck(self):
        """
        Use a fresh shuffled pack of cards if there aren't enough cards left

        `Enough cards` are defined randomly when each player plus the dealer
        can get 5 cards 5*(np + 1)
        """
        if len(self.deck.card_deck) < (len(self.players.players) + 1) * 5:
            self.deck.__init__()
            self.deck.shuffle()
            self.deck.log()

    def __dealer(self):
        """
        The dealer's turn at the game
        """
        # stop if already won
        if self.__all_players_lost():
            log.debug("Dealer already won! [stands... and drops the mic]")
            self.stand(self.dealer)
            return

        while True:
            time.sleep(0.1)
            s = self.dealer.get_cards_sum()
            # stop only if more than 17
            if s > 17:
                self.stand(self.dealer)
                break
            # hit the dealer
            self.hit(self.dealer)

    def __players(self):
        """
        Ask each player if they want another card or not
        """
        for player in self.players.players:
            log.debug('     player %s turn' % player.nume)
            while True:
                answer = ' '
                while answer != 'h' and answer != 's':
                    answer = input('%s : (h)it or (s)tand? ' %
                                   player.display_name()).lower()
                # hit
                if answer == 'h':
                    if self.hit(player) == -1:
                        break
                    continue
                # stand
                if answer == 's':
                    self.stand(player)
                    break

    def __check_players_for_money(self):
        """
        Remove from the game players with no money left
        """
        for player in self.players.get():
            if player.jetoane == 0:
                self.players.broke(player)
        self.players.remove_broke_players_from_game()

    def __reset(self):
        """
        Reset internal objects state for a new round
        """
        self.players.reset_for_new_game()
        self.dealer.reset_for_new_game()
Esempio n. 8
0
from blackjack.dealer import Dealer
from blackjack.player import Player
from blackjack.util import hand_total

dealer = Dealer()
player = Player()

while True:
    print('*** Starting a new game...')
    playing = True
    player.hand = []
    dealer.hand = []
    dealer.show_hand = False

    deck = Deck()
    deck.shuffle()

    player.place_bet()

    player.get_card(deck.deal())
    dealer.get_card(deck.deal())
    player.get_card(deck.deal())
    dealer.get_card(deck.deal())

    print(dealer)
    print(player)

    while playing:
        hs = input('Hit or stand? (h/s) ')

        if hs == 'h':
Esempio n. 9
0
from blackjack.card import Card  #dont know if needed (deck.py is importhing card and comenting in isn't causing an error)
from blackjack.player import Player
from blackjack.thegame import TheGame

#====================================================
#▒█▀█▀█░▐█░▐█░▐█▀▀     ░▐█▀▀▀──░▄█▀▄─▒▐██▄▒▄██▌░▐█▀▀
#░░▒█░░░▐████░▐█▀▀     ░▐█░▀█▌░▐█▄▄▐█░▒█░▒█░▒█░░▐█▀▀
#░▒▄█▄░░▐█░▐█░▐█▄▄     ░▐██▄█▌░▐█─░▐█▒▐█░░░░▒█▌░▐█▄▄
#====================================================
game = TheGame()
player1 = Player('Player1')  #player 1 is human
player2 = Player('Computer')  #player 2 is a computer

#Before we start, we need to create deck
mydeck = Deck()
mydeck.shuffle()

#THis will be repeated until player decide to stop playing
while True:
    if player1.balance <= 0:
        print('Player have not money anymore. Game is finished!')
        break
    #in case it is not first round we have to discard all cards from hand
    player1.discard_hand()
    player2.discard_hand()

    #Before game each player pick their cards, Human players have to make a bet
    player1_bet = player1.bet()

    #Then, each player have to pick 2 cards
    player1.pick_cards(mydeck)
Esempio n. 10
0
def play():
    print("Welcome to blackjack!\n=====================")

    try:
        num_decks = int(input("Number of decks?: "), 10)
    except ValueError:
        print("You need to give me an integer value!")
        return
    try:
        cash = int(input("Starting cash?: "), 10)
    except ValueError:
        print("You need to give me an integer value!")
        return
    deck = Deck(num_decks)
    deck.shuffle(20)

    times_won = 0
    times_drawn = 0
    times_lost = 0

    print("Let's Play!")
    while cash > 0 and len(deck.cards) > num_decks * 16:
        print(f"Your cash: ${cash}")
        try:
            bet = int(input("Place your bet!: "), 10)
        except ValueError:
            print("You need to give me an integer value!")
            break
        player_hand = Hand()
        dealer_hand = Hand()
        player_hand.add(deck.draw())
        dealer_hand.add(deck.draw())
        player_hand.add(deck.draw())
        player_bust = False
        player_blackjack = False
        player_split = False
        while True:
            print()
            print(f"Dealer shows: {dealer_hand.list()}")
            print(f"Your hand: {player_hand.list()}")
            print(f"Your current value: {player_hand.value()}")
            print()
            if player_hand.is_blackjack():
                player_blackjack = True
                print("B L A C K J A C K !")
                break
            if player_hand.value() > 21:
                player_bust = True
                print("You bust!")
                break
            print("Options")
            print("=======")
            print("- (h)it")
            print("- (s)tay")
            if cash >= bet * 2 and player_hand.can_be_split():
                print("- s(p)lit")
            if cash >= bet * 2 and player_hand.can_double():
                print(" - (d)ouble")
            action = input("Pick an action: ")
            if action == "h":
                player_hand.add(deck.draw())
            elif action == "p" and player_hand.can_be_split(
            ) and cash >= bet * 2:
                second_hand = Hand()
                second_hand.add(player_hand.pop())
                player_split = True
                first_bet = bet
                second_bet = bet
                break
            elif action == "d" and player_hand.can_double(
            ) and cash >= bet * 2:
                bet = bet * 2
                player_hand.add(deck.draw())
                if player_hand.value() > 21:
                    player_bust = True
                break
            elif action == "s":
                break

        if player_split:
            first_bust = False
            second_bust = False
            # First hand
            player_hand.add(deck.draw())
            while True:
                print("Playing first hand...\n")
                print(f"Dealer shows: {dealer_hand.list()}")
                print(f"Your hand: {player_hand.list()}")
                print(f"Your current value: {player_hand.value()}")

                if player_hand.value() > 21:
                    first_bust = True
                    print("Bust!")
                    break

                print("Options")
                print("=======")
                print("- (h)it")
                print("- (s)tay")
                if cash >= (first_bet *
                            2) + second_bet and player_hand.can_double():
                    print(" - (d)ouble")
                action = input("Pick an action: ")
                if action == "h":
                    player_hand.add(deck.draw())
                elif action == "d" and player_hand.can_double(
                ) and cash >= (first_bet * 2) + second_bet:
                    first_bet = first_bet * 2
                    player_hand.add(deck.draw())
                    if player_hand.value() > 21:
                        first_bust = True
                        break
                elif action == "s":
                    break

            # Second hand
            second_hand.add(deck.draw())
            while True:
                print("Playing second hand...\n")
                print(f"Dealer shows: {dealer_hand.list()}")
                print(f"Your hand: {second_hand.list()}")
                print(f"Your current value: {second_hand.value()}")

                if second_hand.value() > 21:
                    second_bust = True
                    print("Bust!")
                    break

                print("Options")
                print("=======")
                print("- (h)it")
                print("- (s)tay")
                if cash >= (second_bet *
                            2) + first_bet and second_hand.can_double():
                    print("- (d)ouble")
                action = input("Pick an action: ")
                if action == "h":
                    second_hand.add(deck.draw())
                elif action == "d" and second_hand.can_double(
                ) and cash >= (second_bet * 2) + first_bet:
                    second_bet = second_bet * 2
                    second_hand.add(deck.draw())
                    if second_hand.value() > 21:
                        second_bust = True
                        break
                elif action == "s":
                    break

        if player_blackjack:
            cash += bet
            print("You win!")
            times_won += 1
            continue

        if player_bust:
            print("Dealer wins!")
            cash -= bet
            times_lost += 1
            continue

        dealer_bust = False
        while True:
            print(f"Dealer: {dealer_hand.list()} Value: {dealer_hand.value()}")
            if dealer_hand.value() < 17:
                print("Dealer hits!")
                dealer_hand.add(deck.draw())
            elif dealer_hand.value() > 21:
                print("Dealer busts!")
                dealer_bust = True
                break
            elif dealer_hand.value() == 17 and dealer_hand.has_ace():
                print("Dealer hits!")
                dealer_hand.add(deck.draw())
            else:
                break
        if player_split:
            print()
            print(
                f"Dealer hand: {dealer_hand.list()}, Value: {dealer_hand.value()}"
            )
            print(f"Your first hand: {player_hand.list()}")
            print(f"Your second hand: {second_hand.list()}")

            if first_bust:
                print("First hand busted...")
                cash -= first_bet
                times_lost += 1
            elif dealer_bust or player_hand.value() > dealer_hand.value():
                print("First hand wins!")
                cash += first_bet
                times_won += 1
            elif player_hand.value() < dealer_hand.value():
                print("First hand loses...")
                cash -= first_bet
                times_lost += 1
            else:
                print("First hand PUSH!")
                times_drawn += 1
            if second_bust:
                print("Second hand busted...")
                cash -= second_bet
                times_lost += 1
            elif dealer_bust or second_hand.value() > second_hand.value():
                print("Second hand wins!")
                cash += second_bet
                times_won += 1
            elif second_hand.value() < dealer_hand.value():
                print("Second hand loses...")
                cash -= second_bet
                times_lost += 1
            else:
                print("Second hand PUSH!")
                times_drawn += 1
        else:
            print()
            print("Result:")
            print(
                f"Dealer hand: {dealer_hand.list()}, Value: {dealer_hand.value()}"
            )
            print(
                f"Your hand: {player_hand.list()}, Value: {player_hand.value()}"
            )

            if dealer_bust or player_hand.value() > dealer_hand.value():
                print(f"You win ${bet}!")
                times_won += 1
                cash += bet
            elif player_hand.value() < dealer_hand.value():
                print("You lose!")
                times_lost += 1
                cash -= bet
            else:
                print("PUSH!")
                times_drawn += 1
    print("Thanks for playing!")
    print(f"You won {times_won} hands.")
    print(f"You lost {times_lost} hands.")
    print(f"You pushed {times_drawn} hands.")
Esempio n. 11
0
class Game():

    def __init__(self, stake, players):
        self.stake = stake
        self.bank = 0
        self.players = players
        self.winner = None
        self.busted_players = []
        self.deck = None

    def start(self, deck=None):
        if self.winner != None:
            raise RuntimeError("Game is over")

        enough_money = True
        for p in self.players:
            enough_money = p.has_enough_money(self.stake)
        if not enough_money:
            raise RuntimeError("One of the players does not have enought money to make a stake!")

        for p in self.players:
            p.make_stake(self.stake)
            p.give_cards(Hand())
            self.bank += self.stake

        if deck == None:
            self.deck = Deck()
            self.deck.shuffle()
        else:
            self.deck = deck

        for _ in range(0, 2):
            for p in self.players:
                p.hand.add(self.deck.pop())

    def next_turn(self):
        if self.winner != None:
            raise RuntimeError("Game is over")
        current_player = self.players[0]

        if current_player.take_turn() == STAY:
            self.__next_player()
        else:
            current_player.hand.add(self.deck.pop())
            self.__update_game_state()

    def finish(self):
        if self.winner == None:
            raise RuntimeError("Game has not finished yet")

        self.winner.game_over()
        self.winner.give_money(self.bank)
        self.bank = 0

        for p in self.players + self.busted_players:
            p.game_over()

    def __next_player(self):
        self.players.append(self.players.pop(0))

    def __update_game_state(self):
        active_players = []

        for p in self.players:
            hand_value = p.hand.best_value()
            if hand_value == 21:
                self.winner = p
                active_players.append(p)
            elif hand_value < 21:
                active_players.append(p)
            else:
                self.busted_players.append(p)

        self.players = active_players
        if len(self.players) == 1:
            self.winner = self.players.pop(0)

    def __str__(self):
        res = f'Game for ${self.bank}\n'
        if self.deck == None:
            return f'{res}  Has not started yet.'

        if self.winner:
            res += f'  {self.winner}\n'

        for p in (self.players + self.busted_players):
            res += f'  {p}\n'

        return res