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)