Files
Gwendolyn/funcs/games/blackjack.py
2021-04-13 18:46:57 +02:00

967 lines
43 KiB
Python

import random
import math
import datetime
import asyncio
import discord
from PIL import Image, ImageDraw, ImageFont
from shutil import copyfile
from utils import replaceMultiple
class Blackjack():
def __init__(self,bot):
self.bot = bot
self.draw = DrawBlackjack(bot)
# Shuffles the blackjack cards
def blackjackShuffle(self, decks, channel):
self.bot.log("Shuffling the blackjack deck")
with open("resources/games/deckOfCards.txt","r") as f:
deck = f.read()
allDecks = deck.split("\n") * decks
random.shuffle(allDecks)
self.bot.database["blackjack cards"].update_one({"_id":channel},{"$set":{"_id":channel,"cards":allDecks}},upsert=True)
# Creates hilo file
self.bot.log("creating hilo doc for "+channel)
data = 0
self.bot.database["hilo"].update_one({"_id":channel},{"$set":{"_id":channel,"hilo":data}},upsert=True)
return
# Calculates the value of a blackjack hand
def calcHandValue(self, hand : list):
self.bot.log("Calculating hand value")
values = []
values.append(0)
for card in hand:
cardValue = card[0]
cardValue = replaceMultiple(cardValue,["0","k","q","j"],"10")
if cardValue == "a":
length = len(values)
for x in range(length):
values.append(values[x] + 11)
values[x] += 1
else:
for x in range(len(values)):
values[x] += int(cardValue)
values.sort()
handValue = values[0]
for value in values:
if value <= 21:
handValue = value
self.bot.log("Calculated "+str(hand)+" to be "+str(handValue))
return handValue
# Draws a card from the deck
def drawCard(self, channel):
self.bot.log("drawing a card")
drawnCard = self.bot.database["blackjack cards"].find_one({"_id":channel})["cards"][0]
self.bot.database["blackjack cards"].update_one({"_id":channel},{"$pop":{"cards":-1}})
value = self.calcHandValue([drawnCard])
if value <= 6:
self.bot.database["hilo"].update_one({"_id":channel},{"$inc":{"hilo":1}})
elif value >= 10:
self.bot.database["hilo"].update_one({"_id":channel},{"$inc":{"hilo":-1}})
return drawnCard
# Dealer draws a card and checks if they should draw another one
def dealerDraw(self,channel):
game = self.bot.database["blackjack games"].find_one({"_id":channel})
done = False
dealerHand = game["dealer hand"]
if self.calcHandValue(dealerHand) < 17:
dealerHand.append(self.drawCard(channel))
self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"dealer hand":dealerHand}})
else:
done = True
if self.calcHandValue(dealerHand) > 21:
self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"dealer busted":True}})
return done
# Goes to the next round and calculates some stuff
def blackjackContinue(self, channel):
self.bot.log("Continuing blackjack game")
game = self.bot.database["blackjack games"].find_one({"_id":channel})
done = False
self.bot.database["blackjack games"].update_one({"_id":channel},{"$inc":{"round":1}})
allStanding = True
preAllStanding = True
message = "All players are standing. The dealer now shows his cards and draws."
if game["all standing"]:
self.bot.log("All are standing")
done = self.dealerDraw(channel)
message = "The dealer draws a card."
game = self.bot.database["blackjack games"].find_one({"_id":channel})
self.bot.log("Testing if all are standing")
for user in game["user hands"]:
try:
newUser, allStanding, preAllStanding = self.testIfStanding(game["user hands"][user],allStanding,preAllStanding,True)
self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"user hands."+user:newUser}})
except:
self.bot.log("Error in testing if all are standing (error code 1331)")
if allStanding:
self.bot.database["blackjack games"].update_one({"_id":channel},{"$set":{"all standing":True}})
try:
self.draw.drawImage(channel)
except:
self.bot.log("Error drawing blackjack table (error code 1340)")
if allStanding:
if done == False:
return message, True, done
else:
return "The dealer is done drawing cards", True, done
elif preAllStanding:
return "", True, done
else:
if game["round"] == 1:
firstRoundMessage = ". You can also double down with \"/blackjack double\" or split with \"/blackjack split\""
else:
firstRoundMessage = ""
return "You have 2 minutes to either hit or stand with \"/blackjack hit\" or \"/blackjack stand\""+firstRoundMessage+". It's assumed you're standing if you don't make a choice.", False, done
def testIfStanding(self, hand,allStanding,preAllStanding,topLevel):
if hand["hit"] == False:
hand["standing"] = True
if hand["standing"] == False:
allStanding = False
if self.calcHandValue(hand["hand"]) >= 21 or hand["doubled"]:
hand["standing"] = True
else:
preAllStanding = False
hand["hit"] = False
if topLevel:
if hand["split"] >= 1:
hand["other hand"], allStanding, preAllStanding = self.testIfStanding(hand["other hand"],allStanding,preAllStanding,False)
if hand["split"] >= 2:
hand["third hand"], allStanding, preAllStanding = self.testIfStanding(hand["third hand"],allStanding,preAllStanding,False)
if hand["split"] >= 3:
hand["fourth hand"], allStanding, preAllStanding = self.testIfStanding(hand["fourth hand"],allStanding,preAllStanding,False)
return hand, allStanding, preAllStanding
# When players try to hit
async def hit(self, ctx, handNumber = 0):
await self.bot.defer(ctx)
channel = str(ctx.channel_id)
user = f"#{ctx.author.id}"
roundDone = False
game = self.bot.database["blackjack games"].find_one({"_id":channel})
if user in game["user hands"]:
userHands = game["user hands"][user]
hand, handNumber = self.getHandNumber(userHands, handNumber)
if hand == None:
logMessage = "They didn't specify a hand"
sendMessage = "You need to specify a hand"
elif game["round"] <= 0:
logMessage = "They tried to hit on the 0th round"
sendMessage = "You can't hit before you see your cards"
elif hand["hit"]:
logMessage = "They've already hit this round"
sendMessage = "You've already hit this round"
elif hand["standing"]:
logMessage = "They're already standing"
sendMessage = "You can't hit when you're standing"
else:
hand["hand"].append(self.drawCard(channel))
hand["hit"] = True
handValue = self.calcHandValue(hand["hand"])
if handValue > 21:
hand["busted"] = True
if handNumber == 2:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".other hand":hand}})
elif handNumber == 3:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".third hand":hand}})
elif handNumber == 4:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".fourth hand":hand}})
else:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user:hand}})
roundDone = self.isRoundDone(self.bot.database["blackjack games"].find_one({"_id":channel}))
sendMessage = f"{ctx.author.display_name} hit"
logMessage = "They succeeded"
else:
logMessage = "They tried to hit without being in the game"
sendMessage = "You have to enter the game before you can hit"
await ctx.send(sendMessage)
self.bot.log(logMessage)
if roundDone:
gameID = game["gameID"]
self.bot.log("Hit calling self.blackjackLoop()", channel)
await self.blackjackLoop(ctx.channel, game["round"]+1, gameID)
# When players try to double down
async def double(self, ctx, handNumber = 0):
await self.bot.defer(ctx)
channel = str(ctx.channel_id)
user = f"#{ctx.author.id}"
roundDone = False
game = self.bot.database["blackjack games"].find_one({"_id":channel})
if user in game["user hands"]:
hand, handNumber = self.getHandNumber(game["user hands"][user],handNumber)
if hand == None:
logMessage = "They didn't specify a hand"
sendMessage = "You need to specify a hand"
elif game["round"] <= 0:
logMessage = "They tried to hit on the 0th round"
sendMessage = "You can't hit before you see your cards"
elif hand["hit"]:
logMessage = "They've already hit this round"
sendMessage = "You've already hit this round"
elif hand["standing"]:
logMessage = "They're already standing"
sendMessage = "You can't hit when you're standing"
elif len(hand["hand"]) != 2:
logMessage = "They tried to double after round 1"
sendMessage = "You can only double on the first round"
else:
bet = hand["bet"]
if self.bot.money.checkBalance(user) < bet:
logMessage = "They tried to double without being in the game"
sendMessage = "You can't double when you're not in the game"
else:
self.bot.money.addMoney(user,-1 * bet)
hand["hand"].append(self.drawCard(channel))
hand["hit"] = True
hand["doubled"] = True
hand["bet"] += bet
handValue = self.calcHandValue(hand["hand"])
if handValue > 21:
hand["busted"] = True
if handNumber == 2:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".other hand":hand}})
elif handNumber == 3:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".third hand":hand}})
elif handNumber == 4:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".fourth hand":hand}})
else:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user:hand}})
roundDone = self.isRoundDone(self.bot.database["blackjack games"].find_one({"_id":channel}))
sendMessage = f"Adding another {bet} GwendoBucks to {self.bot.databaseFuncs.getName(user)}'s bet and drawing another card."
logMessage = "They succeeded"
else:
logMessage = "They tried to double without being in the game"
sendMessage = "You can't double when you're not in the game"
await ctx.send(sendMessage)
self.bot.log(logMessage)
if roundDone:
gameID = game["gameID"]
self.bot.log("Double calling self.blackjackLoop()", channel)
await self.blackjackLoop(ctx.channel, game["round"]+1, gameID)
# When players try to stand
async def stand(self, ctx, handNumber = 0):
await self.bot.defer(ctx)
channel = str(ctx.channel_id)
user = f"#{ctx.author.id}"
roundDone = False
game = self.bot.database["blackjack games"].find_one({"_id":channel})
if user in game["user hands"]:
hand, handNumber = self.getHandNumber(game["user hands"][user],handNumber)
if hand == None:
sendMessage = "You need to specify which hand"
logMessage = "They didn't specify a hand"
elif game["round"] <= 0:
sendMessage = "You can't stand before you see your cards"
logMessage = "They tried to stand on round 0"
elif hand["hit"]:
sendMessage = "You've already hit this round"
logMessage = "They'd already hit this round"
elif hand["standing"]:
sendMessage = "You're already standing"
logMessage = "They're already standing"
else:
hand["standing"] = True
if handNumber == 2:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".other hand":hand}})
elif handNumber == 3:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".third hand":hand}})
elif handNumber == 4:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".fourth hand":hand}})
else:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user:hand}})
roundDone = self.isRoundDone(self.bot.database["blackjack games"].find_one({"_id":channel}))
sendMessage = f"{ctx.author.display_name} is standing"
logMessage = "They succeeded"
else:
logMessage = "They tried to stand without being in the game"
sendMessage = "You have to enter the game before you can stand"
await ctx.send(sendMessage)
self.bot.log(logMessage)
if roundDone:
gameID = game["gameID"]
self.bot.log("Stand calling self.blackjackLoop()", channel)
await self.blackjackLoop(ctx.channel, game["round"]+1, gameID)
# When players try to split
async def split(self, ctx, handNumber = 0):
await self.bot.defer(ctx)
channel = str(ctx.channel_id)
user = f"#{ctx.author.id}"
roundDone = False
handNumberError = False
game = self.bot.database["blackjack games"].find_one({"_id":channel})
if game["user hands"][user]["split"] == 0:
hand = game["user hands"][user]
newHand = game["user hands"][user]["other hand"]
handNumber = 0
otherHand = 2
else:
if handNumber == 1:
hand = game["user hands"][user]
elif handNumber == 2:
hand = game["user hands"][user]["other hand"]
elif handNumber == 3:
hand = game["user hands"][user]["third hand"]
else:
handNumberError = True
if game["user hands"][user]["split"] == 1:
newHand = game["user hands"][user]["third hand"]
otherHand = 3
else:
newHand = game["user hands"][user]["fourth hand"]
otherHand = 4
if handNumberError:
logMessage = "They didn't specify a hand"
sendMessage = "You have to specify the hand you're hitting with"
elif game["round"] == 0:
logMessage = "They tried to split on round 0"
sendMessage = "You can't split before you see your cards"
elif game["user hands"][user]["split"] > 3:
logMessage = "They tried to split more than three times"
sendMessage = "You can only split 3 times"
elif hand["hit"]:
logMessage = "They've already hit"
sendMessage = "You've already hit"
elif hand["standing"]:
logMessage = "They're already standing"
sendMessage = "You're already standing"
elif len(hand["hand"]) != 2:
logMessage = "They tried to split after the first round"
sendMessage = "You can only split on the first round"
else:
firstCard = self.calcHandValue([hand["hand"][0]])
secondCard = self.calcHandValue([hand["hand"][1]])
if firstCard != secondCard:
logMessage = "They tried to split two different cards"
sendMessage = "You can only split if your cards have the same value"
else:
bet = hand["bet"]
if self.bot.money.checkBalance(user) < bet:
logMessage = "They didn't have enough GwendoBucks"
sendMessage = "You don't have enough GwendoBucks"
else:
self.bot.money.addMoney(user,-1 * bet)
hand["hit"] = True
newHand["hit"] = True
newHand = {
"hand":[],"bet":0,"standing":False,"busted":False,
"blackjack":False,"hit":True,"doubled":False}
newHand["bet"] = hand["bet"]
newHand["hand"].append(hand["hand"].pop(1))
newHand["hand"].append(self.drawCard(channel))
hand["hand"].append(self.drawCard(channel))
handValue = self.calcHandValue(hand["hand"])
otherHandValue = self.calcHandValue(newHand["hand"])
if handValue > 21:
hand["busted"] = True
elif handValue == 21:
hand["blackjack"] = True
if otherHandValue > 21:
newHand["busted"] = True
elif otherHandValue == 21:
newHand["blackjack"] = True
if handNumber == 2:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".other hand":hand}})
elif handNumber == 3:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".third hand":hand}})
else:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user:hand}})
if otherHand == 3:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".third hand":newHand}})
elif otherHand == 4:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".fourth hand":newHand}})
else:
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$set":{"user hands."+user+".other hand":newHand}})
self.bot.database["blackjack games"].update_one({"_id":channel},
{"$inc":{"user hands."+user+".split":1}})
roundDone = self.isRoundDone(self.bot.database["blackjack games"].find_one({"_id":channel}))
sendMessage = f"Splitting {self.bot.databaseFuncs.getName(user)}'s hand into 2. Adding their original bet to the second hand. You can use \"/blackjack hit/stand/double 1\" and \"/blackjack hit/stand/double 2\" to play the different hands."
logMessage = "They succeeded"
await ctx.send(sendMessage)
self.bot.log(logMessage)
if roundDone:
gameID = game["gameID"]
self.bot.log("Stand calling self.blackjackLoop()", channel)
await self.blackjackLoop(ctx.channel, game["round"]+1, gameID)
# Player enters the game and draws a hand
async def playerDrawHand(self, ctx, bet : int):
await self.bot.defer(ctx)
channel = str(ctx.channel_id)
user = f"#{ctx.author.id}"
collection = self.bot.database["blackjack games"]
game = collection.find_one({"_id":channel})
userName = self.bot.databaseFuncs.getName(user)
self.bot.log(f"{userName} is trying to join the Blackjack game")
if game == None:
sendMessage = "There is no game going on in this channel"
logMessage = sendMessage
elif user in game["user hands"]:
sendMessage = "You're already in the game!"
logMessage = "They're already in the game"
elif len(game["user hands"]) >= 5:
sendMessage = "There can't be more than 5 players in a game"
logMessage = "There were already 5 players in the game"
elif game["round"] != 0:
sendMessage = "The table is no longer taking bets"
logMessage = "They tried to join after the game begun"
elif bet < 0:
sendMessage = "You can't bet a negative amount"
logMessage = "They tried to bet a negative amount"
elif self.bot.money.checkBalance(user) < bet:
sendMessage = "You don't have enough GwendoBucks"
logMessage = "They didn't have enough GwendoBucks"
else:
self.bot.money.addMoney(user,-1 * bet)
playerHand = [self.drawCard(channel) for _ in range(2)]
handValue = self.calcHandValue(playerHand)
if handValue == 21:
blackjackHand = True
else:
blackjackHand = False
newHand = {"hand":playerHand, "bet":bet, "standing":False,
"busted":False, "blackjack":blackjackHand, "hit":True,
"doubled":False, "split":0, "other hand":{},
"third hand":{}, "fourth hand":{}}
function = {"$set":{f"user hands.{user}":newHand}}
collection.update_one({"_id":channel}, function)
enterGameText = "entered the game with a bet of"
betText = f"{bet} GwendoBucks"
sendMessage = f"{userName} {enterGameText} {betText}"
logMessage = sendMessage
self.bot.log(sendMessage)
await ctx.send(logMessage)
# Starts a game of blackjack
async def start(self, ctx):
await self.bot.defer(ctx)
channel = str(ctx.channel_id)
blackjackMinCards = 50
blackjackDecks = 4
await ctx.send("Starting a new game of blackjack")
cardsLeft = 0
cards = self.bot.database["blackjack cards"].find_one({"_id":channel})
if cards != None:
cardsLeft = len(cards["cards"])
# Shuffles if not enough cards
if cardsLeft < blackjackMinCards:
self.blackjackShuffle(blackjackDecks, channel)
self.bot.log("Shuffling the blackjack deck...", channel)
await ctx.channel.send("Shuffling the deck...")
game = self.bot.database["blackjack games"].find_one({"_id":channel})
self.bot.log("Trying to start a blackjack game in "+channel)
gameStarted = False
if game == None:
dealerHand = [self.drawCard(channel),self.drawCard(channel)]
gameID = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
newGame = {"_id":channel,"dealer hand": dealerHand,"dealer busted":False,"dealer blackjack":False,"user hands": {},"all standing":False,"round":0,"gameID":gameID}
if self.calcHandValue(dealerHand) == 21:
newGame["dealer blackjack"] = True
self.bot.database["blackjack games"].insert_one(newGame)
copyfile("resources/games/blackjackTable.png","resources/games/blackjackTables/blackjackTable"+channel+".png")
gameStarted = True
if gameStarted:
sendMessage = "Blackjack game started. Use \"/blackjack bet [amount]\" to enter the game within the next 30 seconds."
await ctx.channel.send(sendMessage)
filePath = f"resources/games/blackjackTables/blackjackTable{channel}.png"
oldImage = await ctx.channel.send(file = discord.File(filePath))
with open("resources/games/oldImages/blackjack"+channel, "w") as f:
f.write(str(oldImage.id))
await asyncio.sleep(30)
gamedone = False
game = self.bot.database["blackjack games"].find_one({"_id":str(channel)})
if len(game["user hands"]) == 0:
gamedone = True
await ctx.channel.send("No one entered the game. Ending the game.")
gameID = game["gameID"]
# Loop of game rounds
if gamedone == False:
self.bot.log("start() calling blackjackLoop()", channel)
await self.blackjackLoop(ctx.channel,1,gameID)
else:
new_message = self.blackjackFinish(channel)
await ctx.channel.send(new_message)
else:
await ctx.channel.send("There's already a blackjack game going on. Try again in a few minutes.")
self.bot.log("There was already a game going on")
# Ends the game and calculates winnings
def blackjackFinish(self,channel):
finalWinnings = "*Final Winnings:*\n"
game = self.bot.database["blackjack games"].find_one({"_id":channel})
dealerValue = self.calcHandValue(game["dealer hand"])
dealerBlackjack = game["dealer blackjack"]
dealerBusted = game["dealer busted"]
try:
for user in game["user hands"]:
winnings, netWinnings, reason = self.calcWinnings(game["user hands"][user],dealerValue,True,dealerBlackjack,dealerBusted)
if winnings < 0:
if winnings == -1:
finalWinnings += self.bot.databaseFuncs.getName(user)+" lost "+str(-1 * winnings)+" GwendoBuck "+reason+"\n"
else:
finalWinnings += self.bot.databaseFuncs.getName(user)+" lost "+str(-1 * winnings)+" GwendoBucks "+reason+"\n"
else:
if winnings == 1:
finalWinnings += self.bot.databaseFuncs.getName(user)+" won "+str(winnings)+" GwendoBuck "+reason+"\n"
else:
finalWinnings += self.bot.databaseFuncs.getName(user)+" won "+str(winnings)+" GwendoBucks "+reason+"\n"
self.bot.money.addMoney(user,netWinnings)
except:
self.bot.log("Error calculating winnings (error code 1311)")
self.bot.database["blackjack games"].delete_one({"_id":channel})
return finalWinnings
def calcWinnings(self,hand, dealerValue, topLevel, dealerBlackjack, dealerBusted):
self.bot.log("Calculating winnings")
reason = ""
bet = hand["bet"]
winnings = -1 * bet
netWinnings = 0
handValue = self.calcHandValue(hand["hand"])
if hand["blackjack"] and dealerBlackjack == False:
reason += "(blackjack)"
winnings += math.floor(2.5 * bet)
netWinnings += math.floor(2.5 * bet)
elif dealerBlackjack:
reason += "(dealer blackjack)"
elif hand["busted"]:
reason += "(busted)"
else:
if dealerBusted:
reason = "(dealer busted)"
winnings += 2 * bet
netWinnings += 2 * bet
elif handValue > dealerValue:
winnings += 2 * bet
netWinnings += 2 * bet
reason = "(highest value)"
elif handValue == dealerValue:
reason = "(pushed)"
winnings += bet
netWinnings += bet
else:
reason = "(highest value)"
if topLevel:
if hand["split"] >= 1:
winningsTemp, netWinningsTemp, reasonTemp = self.calcWinnings(hand["other hand"],dealerValue,False,dealerBlackjack,dealerBusted)
winnings += winningsTemp
netWinnings += netWinningsTemp
reason += reasonTemp
if hand["split"] >= 2:
winningsTemp, netWinningsTemp, reasonTemp = self.calcWinnings(hand["third hand"],dealerValue,False,dealerBlackjack,dealerBusted)
winnings += winningsTemp
netWinnings += netWinningsTemp
reason += reasonTemp
if hand["split"] >= 3:
winningsTemp, netWinningsTemp, reasonTemp = self.calcWinnings(hand["fourth hand"],dealerValue,False,dealerBlackjack,dealerBusted)
winnings += winningsTemp
netWinnings += netWinningsTemp
reason += reasonTemp
return winnings, netWinnings, reason
def getHandNumber(self, user,handNumber):
try:
hand = None
if user["split"] == 0:
hand = user
handNumber = 0
else:
if handNumber != 0:
if handNumber == 1:
hand = user
elif handNumber == 2:
hand = user["other hand"]
elif handNumber == 3:
hand = user["third hand"]
elif handNumber == 4:
hand = user["fourth hand"]
return hand, handNumber
except:
self.bot.log("Problem with getHandNumber() (error code 1322)")
def isRoundDone(self,game):
roundDone = True
for person in game["user hands"].values():
if person["hit"] == False and person["standing"] == False:
roundDone = False
if person["split"] > 0:
if person["other hand"]["hit"] == False and person["other hand"]["standing"] == False:
roundDone = False
if person["split"] > 1:
if person["third hand"]["hit"] == False and person["third hand"]["standing"] == False:
roundDone = False
if person["split"] > 2:
if person["fourth hand"]["hit"] == False and person["fourth hand"]["standing"] == False:
roundDone = False
return roundDone
# Loop of blackjack game rounds
async def blackjackLoop(self,channel,gameRound,gameID):
self.bot.log("Loop "+str(gameRound),str(channel.id))
with open("resources/games/oldImages/blackjack"+str(channel.id), "r") as f:
oldImage = await channel.fetch_message(int(f.read()))
new_message, allStanding, gamedone = self.blackjackContinue(str(channel.id))
if new_message != "":
self.bot.log(new_message,str(channel.id))
await channel.send(new_message)
if gamedone == False:
await oldImage.delete()
oldImage = await channel.send(file = discord.File("resources/games/blackjackTables/blackjackTable"+str(channel.id)+".png"))
with open("resources/games/oldImages/blackjack"+str(channel.id), "w") as f:
f.write(str(oldImage.id))
try:
if allStanding:
await asyncio.sleep(5)
else:
await asyncio.sleep(120)
except:
self.bot.log("Loop "+str(gameRound)+" interrupted (error code 1321)")
game = self.bot.database["blackjack games"].find_one({"_id":str(channel.id)})
if game != None:
realRound = game["round"]
realGameID = game["gameID"]
if gameRound == realRound and realGameID == gameID:
if gamedone == False:
self.bot.log("Loop "+str(gameRound)+" calling self.blackjackLoop()",str(channel.id))
await self.blackjackLoop(channel,gameRound+1,gameID)
else:
try:
new_message = self.blackjackFinish(str(channel.id))
except:
self.bot.log("Something fucked up (error code 1310)")
await channel.send(new_message)
else:
self.bot.log("Ending loop on round "+str(gameRound),str(channel.id))
else:
self.bot.log("Ending loop on round "+str(gameRound),str(channel.id))
# Returning current hi-lo value
async def hilo(self, ctx):
channel = ctx.channel_id
data = self.bot.database["hilo"].find_one({"_id":str(channel)})
if data != None:
hilo = str(data["hilo"])
else:
hilo = "0"
await ctx.send(f"Hi-lo value: {hilo}", hidden=True)
# Shuffles the blackjack deck
async def shuffle(self, ctx):
blackjackDecks = 4
channel = ctx.channel_id
self.blackjackShuffle(blackjackDecks,str(channel))
self.bot.log("Shuffling the blackjack deck...",str(channel))
await ctx.send("Shuffling the deck...")
# Tells you the amount of cards left
async def cards(self, ctx):
channel = ctx.channel_id
cardsLeft = 0
cards = self.bot.database["blackjack cards"].find_one({"_id":str(channel)})
if cards != None:
cardsLeft = len(cards["cards"])
decksLeft = round(cardsLeft/52,1)
await ctx.send(f"Cards left:\n{cardsLeft} cards, {decksLeft} decks", hidden=True)
class DrawBlackjack():
def __init__(self,bot):
self.bot = bot
self.BORDER = 100
self.PLACEMENT = [0,0]
self.ROTATION = 0
def drawImage(self,channel):
self.bot.log("Drawing blackjack table",channel)
game = self.bot.database["blackjack games"].find_one({"_id":channel})
fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', 50)
fntSmol = ImageFont.truetype('resources/fonts/futura-bold.ttf', 40)
self.BORDERSmol = int(self.BORDER/3.5)
table = Image.open("resources/games/blackjackTable.png")
self.PLACEMENT = [2,1,3,0,4]
textImage = ImageDraw.Draw(table)
hands = game["user hands"]
dealerBusted = game["dealer busted"]
dealerBlackjack = game["dealer blackjack"]
try:
if game["all standing"] == False:
dealerHand = self.drawHand(game["dealer hand"],True,False,False)
else:
dealerHand = self.drawHand(game["dealer hand"],False,dealerBusted,dealerBlackjack)
except:
self.bot.log("Error drawing dealer hand (error code 1341a)")
table.paste(dealerHand,(800-self.BORDERSmol,20-self.BORDERSmol),dealerHand)
for x in range(len(hands)):
key, value = list(hands.items())[x]
key = self.bot.databaseFuncs.getName(key)
#self.bot.log("Drawing "+key+"'s hand")
userHand = self.drawHand(value["hand"],False,value["busted"],value["blackjack"])
try:
if value["split"] == 3:
table.paste(userHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),280-self.BORDERSmol),userHand)
userOtherHand = self.drawHand(value["other hand"]["hand"],False,value["other hand"]["busted"],value["other hand"]["blackjack"])
table.paste(userOtherHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),420-self.BORDERSmol),userOtherHand)
userThirdHand = self.drawHand(value["third hand"]["hand"],False,value["third hand"]["busted"],value["third hand"]["blackjack"])
table.paste(userThirdHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),560-self.BORDERSmol),userThirdHand)
userFourthHand = self.drawHand(value["fourth hand"]["hand"],False,value["fourth hand"]["busted"],value["fourth hand"]["blackjack"])
table.paste(userFourthHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),700-self.BORDERSmol),userFourthHand)
elif value["split"] == 2:
table.paste(userHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),420-self.BORDERSmol),userHand)
userOtherHand = self.drawHand(value["other hand"]["hand"],False,value["other hand"]["busted"],value["other hand"]["blackjack"])
table.paste(userOtherHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),560-self.BORDERSmol),userOtherHand)
userThirdHand = self.drawHand(value["third hand"]["hand"],False,value["third hand"]["busted"],value["third hand"]["blackjack"])
table.paste(userThirdHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),700-self.BORDERSmol),userThirdHand)
elif value["split"] == 1:
table.paste(userHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),560-self.BORDERSmol),userHand)
userOtherHand = self.drawHand(value["other hand"]["hand"],False,value["other hand"]["busted"],value["other hand"]["blackjack"])
table.paste(userOtherHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),700-self.BORDERSmol),userOtherHand)
else:
table.paste(userHand,(32-self.BORDERSmol+(384*self.PLACEMENT[x]),680-self.BORDERSmol),userHand)
except:
self.bot.log("Error drawing player hands (error code 1341b)")
textWidth = fnt.getsize(key)[0]
if textWidth < 360:
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2)-3,1010-3),key,fill=(0,0,0), font=fnt)
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2)+3,1010-3),key,fill=(0,0,0), font=fnt)
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2)-3,1010+3),key,fill=(0,0,0), font=fnt)
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2)+3,1010+3),key,fill=(0,0,0), font=fnt)
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2),1005),key,fill=(255,255,255), font=fnt)
else:
textWidth = fntSmol.getsize(key)[0]
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2)-2,1020-2),key,fill=(0,0,0), font=fntSmol)
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2)+2,1020-2),key,fill=(0,0,0), font=fntSmol)
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2)-2,1020+2),key,fill=(0,0,0), font=fntSmol)
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2)+2,1020+2),key,fill=(0,0,0), font=fntSmol)
textImage.text((32+(384*self.PLACEMENT[x])+117-int(textWidth/2),1015),key,fill=(255,255,255), font=fntSmol)
self.bot.log("Saving table image")
table.save("resources/games/blackjackTables/blackjackTable"+channel+".png")
return
def drawHand(self, hand, dealer, busted, blackjack):
self.bot.log("Drawing hand "+str(hand)+", "+str(busted)+", "+str(blackjack))
fnt = ImageFont.truetype('resources/fonts/futura-bold.ttf', 200)
fnt2 = ImageFont.truetype('resources/fonts/futura-bold.ttf', 120)
length = len(hand)
background = Image.new("RGBA", ((self.BORDER*2)+691+(125*(length-1)),(self.BORDER*2)+1065),(0,0,0,0))
textImage = ImageDraw.Draw(background)
if dealer:
img = Image.open("resources/games/cards/"+hand[0].upper()+".png")
#self.ROTATION = (random.randint(-20,20)/10.0)
img = img.rotate(self.ROTATION,expand = 1)
#self.PLACEMENT = [random.randint(-20,20),random.randint(-20,20)]
background.paste(img,(self.BORDER+self.PLACEMENT[0],self.BORDER+self.PLACEMENT[1]),img)
img = Image.open("resources/games/cards/red_back.png")
#self.ROTATION = (random.randint(-20,20)/10.0)
img = img.rotate(self.ROTATION,expand = 1)
#self.PLACEMENT = [random.randint(-20,20),random.randint(-20,20)]
background.paste(img,(125+self.BORDER+self.PLACEMENT[0],self.BORDER+self.PLACEMENT[1]),img)
else:
for x in range(length):
img = Image.open("resources/games/cards/"+hand[x].upper()+".png")
#self.ROTATION = (random.randint(-20,20)/10.0)
img = img.rotate(self.ROTATION,expand = 1)
#self.PLACEMENT = [random.randint(-20,20),random.randint(-20,20)]
background.paste(img,(self.BORDER+(x*125)+self.PLACEMENT[0],self.BORDER+self.PLACEMENT[1]),img)
w, h = background.size
textHeight = 290+self.BORDER
#self.bot.log("Drawing busted/blackjack")
if busted:
textWidth = fnt.getsize("BUSTED")[0]
textImage.text((int(w/2)-int(textWidth/2)-10,textHeight+20-10),"BUSTED",fill=(0,0,0), font=fnt)
textImage.text((int(w/2)-int(textWidth/2)+10,textHeight+20-10),"BUSTED",fill=(0,0,0), font=fnt)
textImage.text((int(w/2)-int(textWidth/2)-10,textHeight+20+10),"BUSTED",fill=(0,0,0), font=fnt)
textImage.text((int(w/2)-int(textWidth/2)+10,textHeight+20+10),"BUSTED",fill=(0,0,0), font=fnt)
textImage.text((int(w/2)-int(textWidth/2)-5,textHeight-5),"BUSTED",fill=(255,255,255), font=fnt)
textImage.text((int(w/2)-int(textWidth/2)+5,textHeight-5),"BUSTED",fill=(255,255,255), font=fnt)
textImage.text((int(w/2)-int(textWidth/2)-5,textHeight+5),"BUSTED",fill=(255,255,225), font=fnt)
textImage.text((int(w/2)-int(textWidth/2)+5,textHeight+5),"BUSTED",fill=(255,255,255), font=fnt)
textImage.text((int(w/2)-int(textWidth/2),textHeight),"BUSTED",fill=(255,50,50), font=fnt)
elif blackjack:
textWidth = fnt2.getsize("BLACKJACK")[0]
textImage.text((int(w/2)-int(textWidth/2)-6,textHeight+20-6),"BLACKJACK",fill=(0,0,0), font=fnt2)
textImage.text((int(w/2)-int(textWidth/2)+6,textHeight+20-6),"BLACKJACK",fill=(0,0,0), font=fnt2)
textImage.text((int(w/2)-int(textWidth/2)-6,textHeight+20+6),"BLACKJACK",fill=(0,0,0), font=fnt2)
textImage.text((int(w/2)-int(textWidth/2)+6,textHeight+20+6),"BLACKJACK",fill=(0,0,0), font=fnt2)
textImage.text((int(w/2)-int(textWidth/2)-3,textHeight-3),"BLACKJACK",fill=(255,255,255), font=fnt2)
textImage.text((int(w/2)-int(textWidth/2)+3,textHeight-3),"BLACKJACK",fill=(255,255,255), font=fnt2)
textImage.text((int(w/2)-int(textWidth/2)-3,textHeight+3),"BLACKJACK",fill=(255,255,255), font=fnt2)
textImage.text((int(w/2)-int(textWidth/2)+3,textHeight+3),"BLACKJACK",fill=(255,255,255), font=fnt2)
textImage.text((int(w/2)-int(textWidth/2),textHeight),"BLACKJACK",fill=(155,123,0), font=fnt2)
#self.bot.log("Returning resized image")
return background.resize((int(w/3.5),int(h/3.5)),resample=Image.BILINEAR)