Base game works but no win logic

This commit is contained in:
2023-07-19 10:45:42 +10:00
parent 72aa847663
commit 33a1fb01f6
5 changed files with 448 additions and 399 deletions

View File

@@ -62,11 +62,11 @@ async def test(interaction:discord.Interaction):
class HitOrStand(discord.ui.View):
def __init__(self, *, timeout=180):
super().__init__(timeout=timeout)
self.content = None
self.content = False
@discord.ui.button(label="Hit", style=discord.ButtonStyle.green)
async def hit(self, interaction: discord.Interaction, button: discord.ui.Button):
self.content = "h"
self.content = True
for child in self.children:
child.disabled = True
await interaction.response.edit_message(content="You Hit!", view=self)
@@ -74,7 +74,7 @@ class HitOrStand(discord.ui.View):
@discord.ui.button(label="Stand", style=discord.ButtonStyle.red)
async def stand(self, interaction: discord.Interaction, button: discord.ui.Button):
self.content = "s"
self.content = False
for child in self.children:
child.disabled = True
await interaction.response.edit_message(content="You stood!", view=self)
@@ -85,7 +85,8 @@ async def bj(interaction: discord.Interaction):
discinput = lambda m: discordInput(interaction, m)
discoutput = lambda m: discordOutput(interaction, m)
await interaction.response.send_message("Let's play Black Jack!")
await blackJack.play_game(interaction.user.id, 100, discinput, discoutput)
await blackJack.play_game(discinput, discoutput)
# await blackJack.play_game(interaction.user.id, 100, discinput, discoutput)
async def discordInput(interaction: discord.Interaction, message:str):
response = HitOrStand()

View File

@@ -1,258 +1,215 @@
import random
import Ledger
from Ledger import Ledger
# Game States
INIT = 0
PLAYING = 1
ENDING = 2
PLAYERTURN = 1
DEALERTURN = 2
FINISHED = 3
OVER = 5
CHECKING = 6
"""
Class which describes playing cards
"""
class Card():
"""
A joker card has value 0 and suit 0
"""
HEARTS = 1
DIAMONDS = 2
SPADES = 3
CLUBS = 4
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 = ""
def __init__(self, value, suit) -> None:
self.value = value
self.suit = suit
self.hidden = False
cardNumber = cardNumber % 13
def turn_card(self):
# XOR to flip hidden element
self.hidden = self.hidden != True
if cardNumber == 0:
cardNumber = "A"
elif cardNumber == 10:
cardNumber = "J"
elif cardNumber == 11:
cardNumber = "Q"
elif cardNumber == 12:
cardNumber = "K"
else:
cardNumber += 1
def get_value(self):
return self.value
return "{value}{suit} ".format(value=str(cardNumber), suit=cardSuit)
def get_suit(self):
return self.suit
def generateDeck():
return [x for x in range(0, 51)]
def __str__(self) -> str:
suits = ["J", "", "", "", ""]
special_cards = {1: "A", 11: "J", 12: "Q", 13: "K"}
strValue = ""
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
if self.value in special_cards.keys():
strValue = special_cards[self.value]
else:
i += card
strValue = str(self.value)
while aces > 0:
if i < 20:
card = 11
if (i + card) > 21:
card = 1
i += card
aces -= 1
return i
string = ""
string = f"{suits[self.suit]}{strValue}"
if self.hidden:
string = "??"
return string
def showDeck(deck):
string = ""
for card in deck:
string += convertNumberToCard(card)
return string
class BlackJack:
def __init__(self):
self.gameInSession = False
self.playerTurn = True
self.deck = generateDeck()
random.shuffle(self.deck)
def __repr__(self) -> str:
return str(self)
"""
Class for interacting with a deck of cards
"""
class Deck():
def __init__(self, joker = False) -> None:
self.deck = []
self.discard = []
self.playerHand = []
self.dealerHand = []
self.ledger = Ledger.Ledger()
self.joker = joker
def returnCards(self):
self.discard.extend(self.playerHand)
self.playerHand.clear()
self.discard.extend(self.dealerHand)
self.dealerHand.clear()
self.deck.extend([Card(x, Card.HEARTS) for x in range(1, 13)])
self.deck.extend([Card(x, Card.DIAMONDS) for x in range(1, 13)])
self.deck.extend([Card(x, Card.SPADES) for x in range(1, 13)])
self.deck.extend([Card(x, Card.CLUBS) for x in range(1, 13)])
def deal(self):
generateHand(self.playerHand, self.deck)
generateHand(self.dealerHand, self.deck)
if joker:
self.deck.append(Card(0, 0))
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 sort(self):
self.deck.sort()
def hit(self):
if self.playerTurn:
addCardToHand(self.playerHand, self.deck)
self.playerTurn = False
else:
addCardToHand(self.dealerHand, self.deck)
self.playerTurn = True
def take_from_deck(self):
card = self.deck.pop()
return card
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)
def return_to_deck_top(self, card):
self.deck.insert(0, card)
if total == 21:
return "w"
elif total > 21:
return "l"
else:
return "c"
def returnToDeckBottom(self, card):
self.deck.append(card)
def dealerHitLogic(self):
total = getHandTotal(self.dealerHand)
if total >= 17:
self.stand()
return True
else:
self.hit()
def addToDiscard(self, card):
self.discard.insert(0, card)
def returnFromDiscard(self):
self.returnToDeckTop(self.discard.pop())
def __str__(self) -> str:
string = ""
for card in self.deck:
string += str(card)
return string
class Hand():
def __init__(self) -> None:
self.hand = []
def sortHand(self):
self.hand.sort()
def add_to_hand(self, card):
self.hand.append(card)
def remove_from_hand(self, index):
return self.hand.pop(index)
def hide_card(self, index):
card = self.remove_from_hand(index)
card.turn_card()
self.add_to_hand(card)
def __str__(self) -> str:
string = ""
for card in self.hand:
string += str(card)
string += " "
return string
def __repr__(self) -> str:
value = 0
for card in self.hand:
value += card.value
return str(value)
def __iter__(self):
self.iter = iter(self.hand)
return self.iter
def __next__(self):
return next(self.iter)
def checkGameOver(self, state):
gameOver = False
if state == "w":
gameOver = True
elif state == "l":
gameOver = True
return gameOver
class BlackJack:
def __init__(self) -> None:
self.deck = Deck()
self.playerHand = Hand()
self.dealerHand = Hand()
self.ledger = Ledger()
def compareHands(self):
dealerTotal = getHandTotal(self.dealerHand)
playerTotal = getHandTotal(self.playerHand)
if dealerTotal < playerTotal:
return "l"
else:
return "w"
def deal_card(self, hand):
hand.add_to_hand(self.deck.take_from_deck())
async def play_game(self, ID, bet, recv, send):
def game_setup(self):
# Deal cards in alternate order
self.deck.shuffle()
for _ in range(2):
self.deal_card(self.playerHand)
self.deal_card(self.dealerHand)
if self.gameInSession:
await send("Fuck you")
return
else:
self.gameInSession = True
# Hide one of the dealers cards
self.dealerHand.hide_card(1)
async def show_cards(self, send, displayDealerScore=False):
# Show Cards to player
string = f"Player Hand = {repr(self.playerHand)}: {self.playerHand}\nDealer Hand = ??: {self.dealerHand}"
if displayDealerScore:
string = f"Player Hand = {repr(self.playerHand)}: {self.playerHand}\nDealer Hand = {repr(self.dealerHand)}: {self.dealerHand}"
await send(string)
async def play_game(self, recv, send):
gameState = INIT
while gameState != OVER:
if gameState == INIT:
# TODO: Load player statistics
self.game_setup()
gameState = PLAYERTURN
self.returnCards()
playerStats = self.ledger.read(ID)
if playerStats is None:
self.ledger.write(ID)
playerStats = self.ledger.read(ID)
self.deal()
playerWinState = self.checkHandState(self.playerHand)
dealerWinState = self.checkHandState(self.dealerHand)
if gameState == PLAYERTURN:
play = None
playerStood = False
dealerStood = False
validInput = False
gameState = CHECKING
elif 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?")
while not validInput:
if play == "h":
self.hit()
validInput = True
elif play == "s":
self.stand()
playerStood = True
validInput = True
dealerStood = self.dealerHitLogic()
playerWinState = self.checkHandState(self.playerHand)
dealerWinState = self.checkHandState(self.dealerHand)
gameState = CHECKING
elif 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()
gameState = CHECKING
elif gameState == CHECKING:
if self.checkGameOver(playerWinState) or self.checkGameOver(dealerWinState):
gameState = FINISHED
elif playerStood:
gameState = ENDING
await self.show_cards(send)
playerHit = await recv("Hit or Stand?")
if playerHit:
self.deal_card(self.playerHand)
else:
gameState = PLAYING
gameState = DEALERTURN
elif gameState == FINISHED:
if int(repr(self.playerHand)) >= 21:
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.dealerHand.hide_card(1)
gameState = FINISHED
self.returnCards()
if len(self.deck) < 0.25 * 52:
await send("Shuffling Deck")
self.shuffle()
if gameState == DEALERTURN:
self.dealerHand.hide_card(1)
self.deal_card(self.dealerHand)
if int(repr(self.dealerHand)) >= 17:
gameState = FINISHED
if gameState == FINISHED:
await self.show_cards(send, True)
await send("You won or lost idk lmao")
gameState = OVER
self.gameInSession = False
def main():
game = BlackJack()
trueFalseInput = lambda x: input(x) == "h"
game.play_game(recv=trueFalseInput, send=print)
if __name__ == "__main__":
main()

View File

@@ -1,167 +0,0 @@
import random
from Ledger import Ledger
"""
Class which describes playing cards
"""
class Card():
"""
A joker card has value 0 and suit 0
"""
HEARTS = 1
DIAMONDS = 2
SPADES = 3
CLUBS = 4
def __init__(self, value, suit) -> None:
self.value = value
self.suit = suit
self.hidden = False
def turn_card(self):
# XOR to flip hidden element
self.hidden = self.hidden != True
def get_value(self):
return self.value
def get_suit(self):
return self.suit
def __str__(self) -> str:
suits = ["J", "", "", "", ""]
special_cards = {1: "A", 11: "J", 12: "Q", 13: "K"}
strValue = ""
if self.value in special_cards.keys():
strValue = special_cards[self.value]
else:
strValue = str(self.value)
string = ""
string = f"{suits[self.suit]}{strValue}"
if self.hidden:
string = "??"
return string
def __repr__(self) -> str:
return str(self)
"""
Class for interacting with a deck of cards
"""
class Deck():
def __init__(self, joker = False) -> None:
self.deck = []
self.discard = []
self.joker = joker
self.deck.extend([Card(x, Card.HEARTS) for x in range(1, 13)])
self.deck.extend([Card(x, Card.DIAMONDS) for x in range(1, 13)])
self.deck.extend([Card(x, Card.SPADES) for x in range(1, 13)])
self.deck.extend([Card(x, Card.CLUBS) for x in range(1, 13)])
if joker:
self.deck.append(Card(0, 0))
def shuffle(self):
random.shuffle(self.deck)
def sort(self):
self.deck.sort()
def take_from_deck(self):
card = self.deck.pop()
return card
def return_to_deck_top(self, card):
self.deck.insert(0, card)
def returnToDeckBottom(self, card):
self.deck.append(card)
def addToDiscard(self, card):
self.discard.insert(0, card)
def returnFromDiscard(self):
self.returnToDeckTop(self.discard.pop())
def __str__(self) -> str:
string = ""
for card in self.deck:
string += str(card)
return string
class Hand():
def __init__(self) -> None:
self.hand = []
def sortHand(self):
self.hand.sort()
def add_to_hand(self, card):
self.hand.append(card)
def remove_from_hand(self, index):
return self.hand.pop(index)
def hide_card(self, index):
card = self.remove_from_hand(0)
card.turn_card()
self.add_to_hand(card)
def __str__(self) -> str:
string = ""
for card in self.hand:
string += str(card)
string += " "
return string
def __iter__(self):
self.iter = iter(self.hand)
return self.iter
def __next__(self):
return next(self.iter)
class BlackJack:
def __init__(self) -> None:
self.deck = Deck()
self.playerHand = Hand()
self.dealerHand = Hand()
self.ledger = Ledger()
def deal_card(self, hand):
hand.add_to_hand(self.deck.take_from_deck())
def game_setup(self):
# Deal cards in alternate order
self.deck.shuffle()
for _ in range(2):
self.deal_card(self.playerHand)
self.deal_card(self.dealerHand)
# Hide one of the dealers cards
self.dealerHand.hide_card(1)
def play_game(self):
# Load player statistics
self.game_setup()
# Show Cards to player
print("Player Hand:", end=" ")
print(self.playerHand)
print("Dealer Hand:", end=" ")
print(self.dealerHand)
def main():
game = BlackJack()
game.play_game()
if __name__ == "__main__":
main()

258
BlackJackOld.py Normal file
View File

@@ -0,0 +1,258 @@
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.gameInSession = False
self.playerTurn = True
self.deck = generateDeck()
random.shuffle(self.deck)
self.discard = []
self.playerHand = []
self.dealerHand = []
self.ledger = Ledger.Ledger()
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):
if self.gameInSession:
await send("Fuck you")
return
else:
self.gameInSession = True
gameState = INIT
while gameState != OVER:
if gameState == INIT:
self.returnCards()
playerStats = self.ledger.read(ID)
if playerStats is None:
self.ledger.write(ID)
playerStats = self.ledger.read(ID)
self.deal()
playerWinState = self.checkHandState(self.playerHand)
dealerWinState = self.checkHandState(self.dealerHand)
play = None
playerStood = False
dealerStood = False
validInput = False
gameState = CHECKING
elif 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?")
while not validInput:
if play == "h":
self.hit()
validInput = True
elif play == "s":
self.stand()
playerStood = True
validInput = True
dealerStood = self.dealerHitLogic()
playerWinState = self.checkHandState(self.playerHand)
dealerWinState = self.checkHandState(self.dealerHand)
gameState = CHECKING
elif 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()
gameState = CHECKING
elif gameState == CHECKING:
if self.checkGameOver(playerWinState) or self.checkGameOver(dealerWinState):
gameState = FINISHED
elif playerStood:
gameState = ENDING
else:
gameState = PLAYING
elif 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()
gameState = OVER
self.gameInSession = False