import random import Ledger # Game States INIT = 0 PLAYING = 1 ENDING = 2 FINISHED = 3 OVER = 5 CHECKING = 6 def convertNumberToCard(cardNumber): # Cards index from 0 i.e ace is 0, and the highest card value is 51 if cardNumber <= 12: cardSuit = "♣" elif cardNumber <= 25: cardSuit = "♦" elif cardNumber <= 38: cardSuit = "♥" elif cardNumber <= 51: cardSuit = "♠" cardNumber = cardNumber % 13 if cardNumber == 0: cardNumber = "A" elif cardNumber == 10: cardNumber = "J" elif cardNumber == 11: cardNumber = "Q" elif cardNumber == 12: cardNumber = "K" else: cardNumber += 1 return "{value}{suit} ".format(value=str(cardNumber), suit=cardSuit) def generateDeck(): return [x for x in range(0, 51)] def addCardToHand(hand, deck): card = deck.pop(0) hand.append(card) def generateHand(hand, deck, handSize = 2): i = 0 while i < handSize: addCardToHand(hand, deck) i += 1 def handNumbersToCards(hand): cards = "" for card in hand: cards += convertNumberToCard(card) return cards def getHandTotal(hand): cardValue = lambda c: min(c % 13 + 1, 10) i = 0 aces = 0 for card in hand: card = cardValue(card) if card == 1: aces += 1 else: i += card while aces > 0: if i < 20: card = 11 if (i + card) > 21: card = 1 i += card aces -= 1 return i def showDeck(deck): string = "" for card in deck: string += convertNumberToCard(card) return string class BlackJack: def __init__(self): self.gameState = INIT self.playerTurn = True self.deck = generateDeck() random.shuffle(self.deck) self.discard = [] self.playerHand = [] self.dealerHand = [] self.ledger = Ledger.Ledger() def getPH(self): return self.playerHand def getDH(self): return self.dealerHand def returnCards(self): self.discard.extend(self.playerHand) self.playerHand.clear() self.discard.extend(self.dealerHand) self.dealerHand.clear() def deal(self): generateHand(self.playerHand, self.deck) generateHand(self.dealerHand, self.deck) def shuffle(self): self.deck.extend(self.discard) self.discard.clear() random.shuffle(self.deck) def stand(self): if self.playerTurn: self.playerTurn = False def hit(self): if self.playerTurn: addCardToHand(self.playerHand, self.deck) self.playerTurn = False else: addCardToHand(self.dealerHand, self.deck) self.playerTurn = True def checkHandState(self, hand): # Check the hand state and return w if game is won, l if lost and c for continue total = getHandTotal(hand) if total == 21: return "w" elif total > 21: return "l" else: return "c" def dealerHitLogic(self): total = getHandTotal(self.dealerHand) if total > 17: self.stand() return True else: self.hit() def checkGameOver(self, state): gameOver = False if state == "w": gameOver = True elif state == "l": gameOver = True return gameOver def compareHands(self): dealerTotal = getHandTotal(self.dealerHand) playerTotal = getHandTotal(self.playerHand) if dealerTotal < playerTotal: return "l" else: return "w" async def play_game(self, ID, bet, recv, send): self.gameState = INIT while self.gameState != OVER: if self.gameState == INIT: playerStats = self.ledger.read(ID) if playerStats is None: self.ledger.write(ID) playerStats = self.ledger.read(ID) self.deal() play = None self.playerTurn = True playerStood = False dealerStood = False validInput = False self.gameState = PLAYING elif self.gameState == PLAYING: await send("Players hand = " + str(getHandTotal(self.playerHand)) + ": " + handNumbersToCards( self.playerHand) + "\n" + "Dealers hand = ??: " + convertNumberToCard(self.dealerHand[0]) + "??") play = await recv("Hit or Stand? (h/s)") while not validInput: if play == "h": self.hit() validInput = True elif play == "s": self.stand() playerStood = True validInput = True self.dealerHitLogic() playerWinState = self.checkHandState(self.playerHand) dealerWinState = self.checkHandState(self.dealerHand) self.gameState = CHECKING elif self.gameState == ENDING: # Players turn self.stand() # Dealers turn dealerStood = self.dealerHitLogic() # Loop ends when game is over dealerWinState = self.checkHandState(self.dealerHand) if dealerStood: if dealerWinState == "c": dealerWinState = self.compareHands() self.gameState = CHECKING elif self.gameState == CHECKING: if self.checkGameOver(playerWinState) or self.checkGameOver(dealerWinState): self.gameState = FINISHED elif playerStood: self.gameState = ENDING else: self.gameState = PLAYING elif self.gameState == FINISHED: await send("Players hand = " + str(getHandTotal(self.playerHand)) + ": " + handNumbersToCards(self.playerHand) + "\n" + "Dealers hand = " + str(getHandTotal(self.dealerHand)) + ": " + handNumbersToCards(self.dealerHand)) if playerWinState == "w": await send("You won!") win = (2*bet, 1, 0, ID) self.ledger.update(ID, win) elif playerWinState == "l": await send("You busted!") loss = (-bet, 0, 1, ID) self.ledger.update(ID, loss) elif dealerWinState == "w": await send("The Dealer reached 21 before you!") loss = (-bet, 0, 1, ID) self.ledger.update(ID, loss) elif dealerWinState == "l": await send("The Dealer busted before you!") win = (2*bet, 1, 0, ID) self.ledger.update(ID, win) self.returnCards() if len(self.deck) < 0.25 * 52: await send("Shuffling Deck") self.shuffle() self.gameState = OVER