Advertisement
Guest User

Untitled

a guest
Jul 18th, 2019
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.86 KB | None | 0 0
  1. import random
  2. import typing as t
  3. from enum import Enum
  4. from functools import partial
  5. import os
  6. import attr
  7.  
  8.  
  9. lock = partial(attr.s, auto_attribs=True, slots=True)
  10. State = Enum("State", "IDLE ACTIVE STAND BUST")
  11.  
  12.  
  13. def ask_question(question):
  14.     while True:
  15.         print(f"{question} [y/n]?")
  16.         ans = input("> ").casefold()
  17.         if ans in ("y", "n"):
  18.             return ans == "y"
  19.  
  20.  
  21. def clear_console():
  22.     os.system("cls" if os.name == "nt" else "clear")
  23.  
  24.  
  25. def ask_bet(money):
  26.     clear_console()
  27.     print(f"Money: ${money}")
  28.     print("How much money do you want to bet?")
  29.     while True:
  30.         money_bet = input("> ")
  31.         try:
  32.             cash_bet = int(money_bet)
  33.         except ValueError:
  34.             cash_bet = -1
  35.         if money >= cash_bet > 0:
  36.             return cash_bet
  37.         print("Please input a valid bet.")
  38.  
  39.  
  40. def build_deck():
  41.     suits = ["Hearts", "Clubs", "Diamonds", "Spades"]
  42.     values = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
  43.     cards = [Card(value, suit) for value in values for suit in suits]
  44.     return cards
  45.  
  46.  
  47. @lock
  48. class Card:
  49.  
  50.     value: str
  51.     suit: str
  52.  
  53.     def score(self):
  54.         if self.value in "JQK":
  55.             return 10
  56.         elif self.value == "A":
  57.             return 1
  58.         else:
  59.             return int(self.value)
  60.  
  61.     def __str__(self):
  62.         return f"{self.value} of {self.suit}"
  63.  
  64.  
  65. @lock
  66. class Shoe:
  67.  
  68.     cards: t.List[Card] = attr.ib(factory=build_deck)
  69.  
  70.     def shuffle(self):
  71.         random.shuffle(self.cards)
  72.  
  73.     def draw_card(self):
  74.         if not self.cards:
  75.             raise Exception("No more cards: empty deck!")
  76.         return self.cards.pop()
  77.  
  78.     def __str__(self):
  79.         cards = [str(c) for c in self.cards]
  80.         return str(cards)
  81.  
  82.  
  83. @lock
  84. class Hand:
  85.  
  86.     cards: t.List[Card] = attr.ib(default=[])
  87.  
  88.     def add(self, card):
  89.         self.cards.append(card)
  90.  
  91.     def score(self):
  92.         total = sum(card.score() for card in self.cards)
  93.         if any(card.value == "A" for card in self.cards) and total <= 11:
  94.             total += 10
  95.         return total
  96.  
  97.     def __str__(self):
  98.         return "{} ({})".format(
  99.             "".join("[{}]".format(card) for card in self.cards), self.score()
  100.         )
  101.  
  102.  
  103. @lock
  104. class Player:
  105.  
  106.     money: int
  107.     bet: int = attr.ib(default=None)
  108.     hand: Hand = attr.ib(factory=Hand)
  109.     state: State = attr.ib(default=State.IDLE)
  110.  
  111.     def player_bet(self):
  112.         self.bet = ask_bet(self.money)
  113.  
  114.     def update(self):
  115.         hand_score = self.hand.score()
  116.         if hand_score > 21:
  117.             self.state = State.BUST
  118.         elif hand_score == 21:
  119.             self.state = State.STAND
  120.         else:
  121.             self.state = State.ACTIVE
  122.  
  123.     def is_busted(self):
  124.         return self.state == State.BUST
  125.  
  126.     def is_standing(self):
  127.         return self.state == State.STAND
  128.  
  129.     def is_idle(self):
  130.         return self.state == State.IDLE
  131.  
  132.     def is_broke(self):
  133.         return self.money == 0
  134.  
  135.     def hit(self, dealer):
  136.         card = dealer.draw_card()
  137.         self.hand.add(card)
  138.  
  139.     def play(self, dealer):
  140.         if ask_question("Do you want to hit"):
  141.             self.hit(dealer)
  142.             self.update()
  143.         else:
  144.             self.state = State.STAND
  145.  
  146.     def __str__(self):
  147.         return (
  148.             f"Player Info:\nMoney: {self.money}\nMoney bet: {self.bet}\n"
  149.             f"State: {self.state.name.capitalize()}\nHand: {self.hand}"
  150.         )
  151.  
  152.  
  153. @lock
  154. class Dealer:
  155.  
  156.     shoe: Shoe = attr.ib(factory=Shoe)
  157.     hand: Hand = attr.ib(factory=Hand)
  158.     state: State = attr.ib(default=State.IDLE)
  159.  
  160.     def draw_card(self):
  161.         card = self.shoe.draw_card()
  162.         return card
  163.  
  164.     def hit(self):
  165.         card = self.draw_card()
  166.         self.hand.add(card)
  167.  
  168.     def update(self):
  169.         hand_score = self.hand.score()
  170.         if hand_score > 21:
  171.             self.state = State.BUST
  172.         elif hand_score >= 17:
  173.             self.state = State.STAND
  174.         else:
  175.             self.state = State.ACTIVE
  176.  
  177.     def is_busted(self):
  178.         return self.state == State.BUST
  179.  
  180.     def is_standing(self):
  181.         return self.state == State.STAND
  182.  
  183.     def is_idle(self):
  184.         return self.state == State.IDLE
  185.  
  186.     def play(self):
  187.         if self.hand.score() < 17:
  188.             self.hit()
  189.             self.update()
  190.  
  191.     def deal(self, player, game):
  192.         while True:
  193.             player.play(self)
  194.             game.display_info()
  195.             if player.is_busted():
  196.                 player.money -= player.bet
  197.                 player.hand.cards = []
  198.                 break
  199.             if player.is_standing():
  200.                 break
  201.  
  202.     def show_cards(self, player):
  203.         if player.state == State.ACTIVE:
  204.             print(f"Dealer Info:\nHand: [{self.hand.cards[0]}][?]")
  205.         elif player.state == State.STAND:
  206.             print(f"Dealer Info:\nHand:{self.hand}")
  207.  
  208.  
  209. @lock
  210. class Game:
  211.  
  212.     player: Player
  213.     dealer: Dealer = attr.ib(factory=Dealer)
  214.  
  215.     def open(self):
  216.         if self.player.is_broke():
  217.             raise Exception("Unfortunately you don't have any money.")
  218.         self.player.player_bet()
  219.         self.dealer.shoe.shuffle()
  220.         c1 = self.dealer.draw_card()
  221.         c2 = self.dealer.draw_card()
  222.         self.player.hand = Hand([c1, c2])
  223.         self.player.update()
  224.         c1 = self.dealer.draw_card()
  225.         c2 = self.dealer.draw_card()
  226.         self.dealer.hand = Hand([c1, c2])
  227.         self.dealer.update()
  228.         self.display_info()
  229.  
  230.     def is_finished(self):
  231.         if self.dealer.hand.score() >= 21:
  232.             return True
  233.         if self.player.is_busted() or self.player.is_standing():
  234.             return True
  235.         return False
  236.  
  237.     def close(self):
  238.         dealer_score = self.dealer.hand.score()
  239.         if not self.player.is_busted():
  240.             if dealer_score > 21:
  241.                 self.player.money += self.player.bet * 2
  242.             else:
  243.                 if self.player.hand.score() < dealer_score:
  244.                     self.player.money -= self.player.bet
  245.                 elif self.player.hand.score() > dealer_score:
  246.                     self.player.money += self.player.bet * 2
  247.         self.display_info()
  248.         self.player.hand.cards = []
  249.         self.player.state = State.IDLE
  250.         self.dealer.hand.cards = []
  251.         self.dealer.state = State.IDLE
  252.         self.dealer.shoe = Shoe()
  253.         self.dealer.shoe.shuffle()
  254.  
  255.     def run(self):
  256.         self.open()
  257.         if self.is_finished():
  258.             self.close()
  259.             return
  260.         self.dealer.deal(self.player, self)
  261.         while True:
  262.             self.dealer.play()
  263.             if self.dealer.is_busted() or self.dealer.is_standing():
  264.                 break
  265.         self.close()
  266.  
  267.     def display_info(self):
  268.         clear_console()
  269.         print(f"{self.player}\n")
  270.         self.dealer.show_cards(self.player)
  271.         player_score = self.player.hand.score()
  272.         dealer_score = self.dealer.hand.score()
  273.         if player_score == 21:
  274.             print("Blackjack! You won!")
  275.         elif dealer_score == 21:
  276.             print("Dealer has got a blackjack. You lost!")
  277.         elif self.player.is_busted():
  278.             print("Busted! You lost!")
  279.         elif self.player.is_standing():
  280.             if self.dealer.is_busted():
  281.                 print("Dealer busted! You won!")
  282.             elif player_score > dealer_score:
  283.                 print("You beat the dealer! You won!")
  284.             elif player_score < dealer_score:
  285.                 print("Dealer has beaten you. You lost!")
  286.             else:
  287.                 print("Push. Nobody wins or losses.")
  288.  
  289.  
  290. def main():
  291.     playing = True
  292.     p = Player(1000)
  293.     while playing:
  294.         g = Game(p)
  295.         g.run()
  296.         playing = ask_question("Do you want to play again")
  297.  
  298.  
  299. if __name__ == "__main__":
  300.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement