Blackjack is a state machine

This commit is contained in:
2023-06-12 12:32:36 +10:00
parent 5dbc250a4a
commit 6e80036ba7
4 changed files with 119 additions and 76 deletions

View File

@@ -85,7 +85,7 @@ async def bj(interaction: discord.Interaction):
discinput = lambda m: discordInput(interaction, m) discinput = lambda m: discordInput(interaction, m)
discoutput = lambda m: discordOutput(interaction, m) discoutput = lambda m: discordOutput(interaction, m)
await interaction.response.send_message("Let's play Black Jack!") await interaction.response.send_message("Let's play Black Jack!")
await blackJack.play_game(interaction.user.id, interaction.message, discinput, discoutput) await blackJack.play_game(interaction.user.id, 100, discinput, discoutput)
async def discordInput(interaction: discord.Interaction, message:str): async def discordInput(interaction: discord.Interaction, message:str):
response = HitOrStand() response = HitOrStand()

View File

@@ -1,6 +1,16 @@
import random import random
import Ledger import Ledger
# Game States
INIT = 0
PLAYING = 1
ENDING = 2
FINISHED = 3
OVER = 5
CHECKING = 6
def convertNumberToCard(cardNumber): def convertNumberToCard(cardNumber):
# Cards index from 0 i.e ace is 0, and the highest card value is 51 # Cards index from 0 i.e ace is 0, and the highest card value is 51
if cardNumber <= 12: if cardNumber <= 12:
@@ -49,13 +59,21 @@ def handNumbersToCards(hand):
def getHandTotal(hand): def getHandTotal(hand):
cardValue = lambda c: min(c % 13 + 1, 10) cardValue = lambda c: min(c % 13 + 1, 10)
i = 0 i = 0
aces = 0
for card in hand: for card in hand:
card = cardValue(card) card = cardValue(card)
if (card == 1) and (i < 20): if card == 1:
aces += 1
else:
i += card
while aces > 0:
if i < 20:
card = 11 card = 11
if (i + card) > 21: if (i + card) > 21:
card = 1 card = 1
i += card i += card
aces -= 1
return i return i
def showDeck(deck): def showDeck(deck):
@@ -66,6 +84,7 @@ def showDeck(deck):
class BlackJack: class BlackJack:
def __init__(self): def __init__(self):
self.gameState = INIT
self.playerTurn = True self.playerTurn = True
self.deck = generateDeck() self.deck = generateDeck()
random.shuffle(self.deck) random.shuffle(self.deck)
@@ -118,11 +137,12 @@ class BlackJack:
else: else:
return "c" return "c"
def dealerHitLogic(self, hand): def dealerHitLogic(self):
total = getHandTotal() total = getHandTotal(self.dealerHand)
if total > 17: if total > 17:
self.stand() self.stand()
elif total <= 16: return True
else:
self.hit() self.hit()
@@ -133,78 +153,101 @@ class BlackJack:
elif state == "l": elif state == "l":
gameOver = True gameOver = True
return gameOver 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): async def play_game(self, ID, bet, recv, send):
gameOver = False
playerStats = self.ledger.read(ID)
if playerStats is None:
self.ledger.write(ID)
playerStats = self.ledger.read(ID)
self.deal()
while not gameOver:
play = None
playerStood = False
validInput = False
playerWinState = self.checkHandState(self.playerHand)
dealerWinState = self.checkHandState(self.dealerHand)
gameOver = self.checkGameOver(playerWinState) or self.checkGameOver(dealerWinState)
if gameOver:
continue
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()
validInput = True
playerStood = True
playerWinState = self.checkHandState(self.playerHand)
if self.checkGameOver(playerWinState):
continue
# Dealers turn
if playerStood:
while dealerWinState == 'c':
# Dealer hits
self.hit()
# Player stands
self.stand()
# Loop ends when game is over
dealerWinState = self.checkHandState(self.dealerHand)
else:
self.hit()
dealerWinState = self.checkHandState(self.dealerHand)
if self.checkGameOver(dealerWinState):
continue
await send("Players hand = " + str(getHandTotal(self.playerHand)) + ": " + handNumbersToCards(self.playerHand) + while self.gameState != OVER:
"\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 self.gameState == INIT:
if len(self.deck) < 0.25 * 52:
await send("Shuffling Deck") gameOver = False
self.shuffle() playerStats = self.ledger.read(ID)
if playerStats is None:
self.ledger.write(ID)
playerStats = self.ledger.read(ID)
self.deal()
play = None
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

BIN
ledger.db

Binary file not shown.