diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/blackjack.py b/blackjack.py deleted file mode 100644 index bda3bfd..0000000 --- a/blackjack.py +++ /dev/null @@ -1,220 +0,0 @@ -title = '''\ - - .oPYo. 8 8 o 8 - 8 `8 8 8 8 8 -o8YooP' 8 .oPYo. .oPYo. 8 .o 8 .oPYo. .oPYo. 8 .o - 8 `b 8 .oooo8 8 ' 8oP' 8 .oooo8 8 ' 8oP' - 8 8 8 8 8 8 . 8 `b. 8 8 8 8 . 8 `b. - 8oooP' 8 `YooP8 `YooP' 8 `o. oP' `YooP8 `YooP' 8 `o. -:......:..:.....::.....:..::......::.....::.....:..::... -:::::::::::::::::::::::::::::::::::::::::::::::::::::::: -::::::::::::::::::::::::::::::::::::::::::::::::::::::::''' - -import random - -def make_card(vs, style): - value = vs[0] - - if value == '0': - value = '10' - else: - value += ' ' - - suit = vs[1] + ' ' - - # request text render of preceeding glyph but can break some fonts - # suit += '\uFE0E' - - deck = '''\ -┌────────┐┐┐┐┐┐ -│░░░░░░░░││││││ -│░░░░░░░░││││││ -│░░░░░░░░││││││ -│░░░░░░░░││││││ -│░░░░░░░░││││││ -└────────┘┘┘┘┘┘''' - card_rest = f'''\ -──────┐ - │ - │ - │ - │ - │ -──────┘''' - hidden_part = f'''\ -┌── -│░░ -│░░ -│░░ -│░░ -│░░ -└──''' - hidden_rest = f'''\ -──────┐ -░░░░░░│ -░░░░░░│ -░░░░░░│ -░░░░░░│ -░░░░░░│ -──────┘''' - card_part = f'''\ -┌── -│{value} -│{suit} -│ -│ -│ -└──''' - - if style == 'deck': - return deck - elif style == 'card_rest': - return card_rest - elif style == 'hidden_part': - return hidden_part - elif style == 'hidden_rest': - return hidden_rest - elif style == 'card_part': - return card_part - -def generate_deck(n_decks): - n_decks = int(n_decks) - if n_decks > 8: - n_decks = 8 - suits = '♠♥♦♣' - cards = 'A234567890JQK' - deck = [] - - while n_decks > 0: - deck += [card + suit for card in cards for suit in suits] - n_decks -= 1 - return deck - -def draw_card(player): - players.get(player).append(play_deck.pop(random.choice(range(len(play_deck))))) - -def print_hand(player): - player_cards = [make_card(card,'card_part') for card in players.get(player)] - if player == 'Dealer' and game_active == True: - player_cards[0] = make_card('na','hidden_part') - player_cards.append(make_card('na','card_rest')) - card_slices = [str(card).splitlines() for card in player_cards] - for i in range(7): - clist = [card_slice[i] for card_slice in card_slices] - carriage = '' - for chunk in clist: - carriage += chunk - print(carriage) - -def deal(): - for i in range(2): - for player in players: - draw_card(player) - -def show_board(): - print('\033c', end='') - print(title) - for player in players: - print(' '+player, - '\t\t\t\t Score:',player_score(player)) - print_hand(player) - -def score_hand(player): - hand = [card[0] for card in players.get(player)] - - if hand == ['0','1'] or hand == ['1','0']: - game_active = False - gameover = player, 'has blackjack!' - return [21] - - hand = ['1' if card == 'A' else card for card in hand] - scores = [10 if card in 'JQK0' else int(card) for card in hand] - return scores - -def player_score(player): - card_scores = score_hand(player) - - if sum(card_scores) < 11: - if 1 in card_scores: - index = card_scores.index(1) - card_scores[index] = 11 - - if player == 'Dealer' and game_active == True: - return sum(card_scores[1:]) - - else: - return sum(card_scores) - -def main(): - global players - global play_deck - global game_active - global gameover - - gameover = 'Error' - - if len(play_deck) < 4: - play_deck = generate_deck(num_decks) - - # 5-9 seats - players = {'Dealer': [], - 'Player': []} - - deal() - game_active = True - - while game_active == True: - show_board() - user_input = input(str(len(play_deck)) + ' cards left in deck\n[H]it or [S]tand? ') - - if user_input.lower() == 'q': - gameover = 'q' - game_active = False - - elif user_input.lower() == 'r': - game_active = False - - elif user_input.lower() == 'h': - draw_card('Player') - - elif user_input.lower() == 's': - game_active = False - - if player_score('Dealer') == 21: - gameover = 'Dealer has blackjack!' - break - - while player_score('Dealer') < 17: - draw_card('Dealer') - - if player_score('Dealer') > 21: - gameover = 'Dealer Bust!' - - elif player_score('Dealer') == player_score('Player'): - gameover = 'Push.' - - elif player_score('Dealer') > player_score('Player'): - gameover = 'House wins.' - - elif player_score('Dealer') < player_score('Player'): - gameover = 'You win!' - - if player_score('Player') > 21: - gameover = 'Bust!' - game_active = False - -kill = False -play_deck = [] - -num_decks = input('How many decks? (1-8): ') - -while kill == False: - main() - if gameover == 'q': - kill = True - break - show_board() - user_input = input(gameover + '\nPlay again? [Y/n] ') - if user_input.lower() == 'n': - kill = True - diff --git a/cardprinter.py b/cardprinter.py new file mode 100644 index 0000000..051a0b5 --- /dev/null +++ b/cardprinter.py @@ -0,0 +1,72 @@ +class CardPrinter: + def make_card(self, vs, style): + deck = '''\ +┌────────┐┐┐┐┐┐ +│░░░░░░░░││││││ +│░░░░░░░░││││││ +│░░░░░░░░││││││ +│░░░░░░░░││││││ +│░░░░░░░░││││││ +└────────┘┘┘┘┘┘''' + card_rest = f'''\ +──────┐ + │ + │ + │ + │ + │ +──────┘''' + hidden_part = f'''\ +┌── +│░░ +│░░ +│░░ +│░░ +│░░ +└──''' + hidden_rest = f'''\ +──────┐ +░░░░░░│ +░░░░░░│ +░░░░░░│ +░░░░░░│ +░░░░░░│ +──────┘''' + value = vs[0] + value = '10' if value == '0' else value + ' ' + suit = vs[1] + ' ' + # request text (not emoji) render of preceeding glyph but can break some fonts + # suit += '\uFE0E' + card_part = f'''\ +┌── +│{value} +│{suit} +│ +│ +│ +└──''' + match style: + case 'deck': + return deck + case 'card_rest': + return card_rest + case 'hidden_part': + return hidden_part + case 'hidden_rest': + return hidden_rest + case 'card_part': + return card_part + + def print_hand(self, player): + player_cards = [self.make_card(card,'card_part') for card in player.hand] + if player == 'Dealer' and game_active: + player_cards[0] = self.make_card('na','hidden_part') + player_cards.append(self.make_card('na','card_rest')) + card_slices = [str(card).splitlines() for card in player_cards] + for i in range(7): + clist = [card_slice[i] for card_slice in card_slices] + carriage = '' + for chunk in clist: + carriage += chunk + print(carriage) + diff --git a/deck.py b/deck.py new file mode 100644 index 0000000..64c4ac9 --- /dev/null +++ b/deck.py @@ -0,0 +1,25 @@ +import random + +class Deck: + cards = [] + + def count(self): + return len(self.cards) + + def shuffle(self, n_decks): + n_decks = 1 if not n_decks or n_decks not in '12345678' else n_decks + n_decks = int(n_decks) + n_decks = 8 if n_decks > 8 else n_decks + suits = '♠♥♦♣' + # cards = 'A234567890JQK' + cards = 'A0A0A0A0A0A0A' + while n_decks > 0: + self.cards += [card + suit for card in cards for suit in suits] + n_decks -= 1 + + def count_below(self, n): + if self.count() < n: + return True + + def draw(self): + return self.cards.pop(random.choice(range(self.count()))) diff --git a/gamemaster.py b/gamemaster.py new file mode 100644 index 0000000..13f304c --- /dev/null +++ b/gamemaster.py @@ -0,0 +1,18 @@ +from player import Player + +class GameMaster: + active = True + players = [Player('Dealer'), Player('Player')] # 5-9 seats + dealer = players[0] + player = players[1] + + def score(self): + if self.dealer.score() == self.player.score(): + self.active = False + print('Push.') + elif self.dealer.score() > self.player.score(): + self.active = False + print('House wins.') + elif self.dealer.score() < self.player.score(): + self.active = False + print('You win!') diff --git a/main.py b/main.py new file mode 100644 index 0000000..83a08d4 --- /dev/null +++ b/main.py @@ -0,0 +1,44 @@ +from deck import Deck +from screen import Screen +from gamemaster import GameMaster + +def main(): + screen = Screen() + num_decks = input('How many decks? (1-8): ') + + game = GameMaster() + deck = Deck() + if deck.count_below(4): + deck.shuffle(num_decks) + + for player in game.players: + for _ in range(2): + player.hand.append(deck.draw()) + + dealer = game.players[0] + player = game.players[1] + + + while game.active: + screen.update(game.players) + if game.active: + user_input = input(str(deck.count()) + ' cards left in deck.\n[H]it or [S]tand? ') + else: + user_input = input('Play again? [Y/n] ') + + match user_input.lower(): + case 'q': + game.active = False + case 'n': + game.active = False + case 'h': + player.hand.append(deck.draw()) + if player.bust(): + game.active = False + print('Player Bust!') + case 's': + while dealer.score() < 17: + dealer.hand.append(deck.draw()) + game.score() + +main() diff --git a/player.py b/player.py new file mode 100644 index 0000000..0dab05b --- /dev/null +++ b/player.py @@ -0,0 +1,21 @@ +class Player: + def __init__(self, name): + self.name = name + self.hand = [] + + def tally_hand(self): + cards = [card[0] for card in self.hand] + cards = ['11' if card == 'A' else card for card in cards] + scores = [10 if card in 'JQK0' else int(card) for card in cards] + return scores + + def score(self): + score = sum(self.tally_hand()) + if score > 21 and 11 in self.tally_hand(): + return score - 10 + else: + return score + + def bust(self): + if self.score() > 21: + return True diff --git a/screen.py b/screen.py new file mode 100644 index 0000000..d7674ec --- /dev/null +++ b/screen.py @@ -0,0 +1,38 @@ +from cardprinter import CardPrinter +printer = CardPrinter() + +class Screen: + title = '''\ + + .oPYo. 8 8 o 8 + 8 `8 8 8 8 8 +o8YooP' 8 .oPYo. .oPYo. 8 .o 8 .oPYo. .oPYo. 8 .o + 8 `b 8 .oooo8 8 ' 8oP' 8 .oooo8 8 ' 8oP' + 8 8 8 8 8 8 . 8 `b. 8 8 8 8 . 8 `b. + 8oooP' 8 `YooP8 `YooP' 8 `o. oP' `YooP8 `YooP' 8 `o. +:......:..:.....::.....:..::......::.....::.....:..::... +:::::::::::::::::::::::::::::::::::::::::::::::::::::::: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::''' + + + def update(self, player_list): + print('\033c', end='') + print(title) + for player in player_list: + print(' '+player.name, + '\t\t\t\t Score:',player.score()) + printer.print_hand(player) + + def player_display_score(self, player): + card_scores = player_score(player) + if sum(card_scores) > 21: + if 11 in card_scores: + index = card_scores.index(11) + card_scores[index] = 1 + if player == 'Dealer' and game_active == True: + return sum(card_scores[1:]) + else: + return sum(card_scores) + def intro(): + print('\033c', end='') + print(screen.title)