import random import json import math import datetime from shutil import copyfile from funcs import logThis, replaceMultiple, getName from . import money, blackjackDraw # Shuffles the blackjack cards def blackjackShuffle(decks,channel): logThis("Shuffling the blackjack deck") with open("resources/games/deckofCards.txt","r") as f: deck = f.read() allDecks = deck.split("\n") * decks random.shuffle(allDecks) data = "\n".join(allDecks) with open("resources/games/blackjackCards/"+channel+".txt","w") as f: f.write(data) # Creates hilo file logThis("creating hilo/"+channel+".txt.") data = "0" with open("resources/games/hilo/"+channel+".txt","w") as f: f.write(data) return # Calculates the value of a blackjack hand def calcHandValue(hand : list): logThis("Calculating hand value") values = [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 logThis("Calculated "+str(hand)+" to be "+str(handValue)) return handValue # Draws a card from the deck def drawCard(channel): logThis("drawing a card") with open("resources/games/blackjackCards/"+channel+".txt","r") as f: cards = f.read().split("\n") with open("resources/games/hilo/"+channel+".txt", "r") as f: data = int(f.read()) drawnCard = cards.pop(0) deck = "\n".join(cards) value = calcHandValue([drawnCard]) if value <= 6: data += 1 elif value >= 10: data -= 1 with open("resources/games/blackjackCards/"+channel+".txt","w") as f: f.write(deck) with open("resources/games/hilo/"+channel+".txt", "w") as f: f.write(str(data)) return drawnCard # Dealer draws a card and checks if they should draw another one def dealerDraw(channel): with open("resources/games/games.json", "r") as f: data = json.load(f) done = False dealerHand = data["blackjack games"][channel]["dealer hand"] if calcHandValue(dealerHand) < 17: data["blackjack games"][channel]["dealer hand"].append(drawCard(channel)) else: done = True if calcHandValue(dealerHand) > 21: data["blackjack games"][channel]["dealer busted"] = True with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) return done # Goes to the next round and calculates some stuff def blackjackContinue(channel): logThis("Continuing blackjack game") with open("resources/games/games.json", "r") as f: data = json.load(f) done = False data["blackjack games"][channel]["round"] += 1 with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) allStanding = True preAllStanding = True message = "All players are standing. The dealer now shows his cards and draws." if data["blackjack games"][channel]["all standing"]: logThis("All are standing") with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) done = dealerDraw(channel) message = "The dealer draws a card." with open("resources/games/games.json", "r") as f: data = json.load(f) logThis("Testing if all are standing") for user in data["blackjack games"][channel]["user hands"]: try: data["blackjack games"][channel]["user hands"][user], allStanding, preAllStanding = testIfStanding(data["blackjack games"][channel]["user hands"][user],allStanding,preAllStanding,True) except: logThis("Error in testing if all are standing (error code 1331)") if allStanding: data["blackjack games"][channel]["all standing"] = True with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) else: with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) try: blackjackDraw.drawImage(channel) except: logThis("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 data["blackjack games"][channel]["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(hand,allStanding,preAllStanding,topLevel): if hand["hit"] == False: hand["standing"] = True if hand["standing"] == False: allStanding = False if 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 = testIfStanding(hand["other hand"],allStanding,preAllStanding,False) if hand["split"] >= 2: hand["third hand"], allstanding, preAllStanding = testIfStanding(hand["third hand"],allStanding,preAllStanding,False) if hand["split"] >= 3: hand["fourth hand"], allstanding, preAllStanding = testIfStanding(hand["fourth hand"],allStanding,preAllStanding,False) return hand, allStanding, preAllStanding # When players try to hit def blackjackHit(channel,user,handNumber = 0): with open("resources/games/games.json", "r") as f: data = json.load(f) if user in data["blackjack games"][channel]["user hands"]: hand, handNumber = getHandNumber(data["blackjack games"][channel]["user hands"][user],handNumber) print(hand) if hand != None: if data["blackjack games"][channel]["round"] > 0: if hand["hit"] == False: if hand["standing"] == False: hand["hand"].append(drawCard(channel)) hand["hit"] = True handValue = calcHandValue(hand["hand"]) if handValue > 21: hand["busted"] = True if handNumber == 2: data["blackjack games"][channel]["user hands"][user]["other hand"] = hand elif handNumber == 3: data["blackjack games"][channel]["user hands"][user]["third hand"] = hand elif handNumber == 4: data["blackjack games"][channel]["user hands"][user]["fourth hand"] = hand else: data["blackjack games"][channel]["user hands"][user] = hand with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) response = "accept" roundDone = isRoundDone(data["blackjack games"][channel]) return response + str(roundDone)[0] + str(data["blackjack games"][channel]["round"]) else: logThis(user+" is already standing") return "You can't hit when you're standing" else: logThis(user+" has already hit this round") return "You've already hit this round" else: logThis(user+" tried to hit on the 0th round") return "You can't hit before you see your cards" else: logThis(user+" didn't specify a hand") return "You need to specify a hand" else: logThis(user+" tried to hit without being in the game") return "You have to enter the game before you can hit" # When players try to double down def blackjackDouble(channel,user,handNumber = 0): with open("resources/games/games.json", "r") as f: data = json.load(f) if user in data["blackjack games"][channel]["user hands"]: hand, handNumber = getHandNumber(data["blackjack games"][channel]["user hands"][user],handNumber) if hand != None: if data["blackjack games"][channel]["round"] > 0: if hand["hit"] == False: if hand["standing"] == False: if len(hand["hand"]) == 2: bet = hand["bet"] if money.checkBalance(user) >= bet: money.addMoney(user,-1 * bet) with open("resources/games/games.json", "r") as f: data = json.load(f) hand["hand"].append(drawCard(channel)) hand["hit"] = True hand["doubled"] = True hand["bet"] += bet handValue = calcHandValue(hand["hand"]) if handValue > 21: hand["busted"] = True if handNumber == 2: data["blackjack games"][channel]["user hands"][user]["other hand"] = hand elif handNumber == 3: data["blackjack games"][channel]["user hands"][user]["third hand"] = hand elif handNumber == 4: data["blackjack games"][channel]["user hands"][user]["fourth hand"] = hand else: data["blackjack games"][channel]["user hands"][user] = hand with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) roundDone = isRoundDone(data["blackjack games"][channel]) return "Adding another "+str(bet)+" GwendoBucks to "+getName(user)+"'s bet and drawing another card.",str(roundDone)[0] + str(data["blackjack games"][channel]["round"]) else: logThis(user+" doesn't have enough GwendoBucks") return "You don't have enough GwendoBucks","" else: logThis(user+" tried to double on round "+str(data["blackjack games"][channel]["round"])) return "You can only double down on the first round","" else: logThis(user+" is already standing") return "You can't double when you're standing","" else: logThis(user+" has already hit this round") return "You've already hit this round","" else: logThis(user+" tried to double on the 0th round") return "You can't double down before you see your cards","" else: logThis(user+" didn't specify a hand") return "You need to specify which hand" else: logThis(user+" tried to double without being in the game") return "You can't double when you're not in the game","" # When players try to stand def blackjackStand(channel,user,handNumber = 0): with open("resources/games/games.json", "r") as f: data = json.load(f) if user in data["blackjack games"][channel]["user hands"]: hand, handNumber = getHandNumber(data["blackjack games"][channel]["user hands"][user],handNumber) if hand != None: if data["blackjack games"][channel]["round"] > 0: if hand["hit"] == False: if hand["standing"] == False: hand["standing"] = True with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) response = "accept" roundDone = isRoundDone(data["blackjack games"][channel]) return response + str(roundDone)[0] + str(data["blackjack games"][channel]["round"]) else: logThis(user+" is already standing") return "You're already standing" else: logThis(user+" has already hit this round") return "You've already hit this round" else: logThis(user+" tried to stand on the first round") return "You can't stand before you see your cards" else: logThis(user+" didn't specify a hand") return "You need to specify which hand" else: logThis(user+" tried to stand without being in the game") return "You have to enter the game before you can stand" # When players try to split def blackjackSplit(channel,user,handNumber = 0): with open("resources/games/games.json", "r") as f: data = json.load(f) if data["blackjack games"][channel]["user hands"][user]["split"] == 0: hand = data["blackjack games"][channel]["user hands"][user] newHand = data["blackjack games"][channel]["user hands"][user]["other hand"] handNumber = 0 otherHand = 2 else: if handNumber != 0: if handNumber == 1: hand = data["blackjack games"][channel]["user hands"][user] elif handNumber == 2: hand = data["blackjack games"][channel]["user hands"][user]["other hand"] elif handNumber == 3: hand = data["blackjack games"][channel]["user hands"][user]["third hand"] else: logThis(user+" tried to hit without specifying which hand") return "You have to specify the hand you're hitting with." if data["blackjack games"][channel]["user hands"][user]["split"] == 1: newHand = data["blackjack games"][channel]["user hands"][user]["third hand"] otherHand = 3 else: newHand = data["blackjack games"][channel]["user hands"][user]["fourth hand"] otherHand = 4 else: logThis(user+" tried to split without specifying which hand") return "You have to specify the hand you're splitting.","" if data["blackjack games"][channel]["user hands"][user]["split"] < 3: if data["blackjack games"][channel]["round"] != 0: if hand["hit"] == False: if hand["standing"] == False: if len(hand["hand"]) == 2: firstCard = calcHandValue([hand["hand"][0]]) secondCard = calcHandValue([hand["hand"][1]]) if firstCard == secondCard: bet = hand["bet"] if money.checkBalance(user) >= bet: money.addMoney(user,-1 * bet) with open("resources/games/games.json", "r") as f: data = json.load(f) 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(drawCard(channel)) hand["hand"].append(drawCard(channel)) handValue = calcHandValue(hand["hand"]) otherHandValue = 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: data["blackjack games"][channel]["user hands"][user]["other hand"] = hand elif handNumber == 3: data["blackjack games"][channel]["user hands"][user]["third hand"] = hand else: data["blackjack games"][channel]["user hands"][user] = hand if otherHand == 3: data["blackjack games"][channel]["user hands"][user]["third hand"] = newHand elif otherHand == 4: data["blackjack games"][channel]["user hands"][user]["fourth hand"] = newHand else: data["blackjack games"][channel]["user hands"][user]["other hand"] = newHand data["blackjack games"][channel]["user hands"][user]["split"] += 1 with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) roundDone = isRoundDone(data["blackjack games"][channel]) return "Splitting "+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.",str(roundDone)[0] + str(data["blackjack games"][channel]["round"]) else: logThis(user+" doesn't have enough GwendoBucks") return "You don't have enough GwendoBucks","" else: logThis(user+" tried to split 2 different cards") return "Your cards need to have the same value to split","" else: logThis(user+" tried to split later than they could") return "You can only split on the first round","" else: logThis(user+" is already standing") return "You can't split when you're standing","" else: logThis(user+" has already hit this round") return "You've already hit this round","" else: logThis(user+" tried to split on the 0th round") return "You can't split before you see your cards","" else: logThis(user+" tried to split more than three times") return "You can only split 3 times","" # Player enters the game and draws a hand def blackjackPlayerDrawHand(channel,user,bet): with open("resources/games/games.json", "r") as f: data = json.load(f) logThis(getName(user)+" is trying to join the game in "+channel) if channel in data["blackjack games"]: if user not in data["blackjack games"][channel]["user hands"]: if len(data["blackjack games"][channel]["user hands"]) < 5: if data["blackjack games"][channel]["round"] == 0: if bet >= 0: if money.checkBalance(user) >= bet: money.addMoney(user,-1 * bet) playerHand = [drawCard(channel),drawCard(channel)] handValue = calcHandValue(playerHand) with open("resources/games/games.json", "r") as f: data = json.load(f) if handValue == 21: data["blackjack games"][channel]["user hands"][user] = {"hand":playerHand, "bet":bet,"standing":False,"busted":False,"blackjack":True,"hit":True, "doubled":False,"split":0,"other hand":{},"third hand":{},"fourth hand":{}} else: data["blackjack games"][channel]["user hands"][user] = {"hand":playerHand, "bet":bet,"standing":False,"busted":False,"blackjack":False,"hit":True, "doubled":False,"split":0,"other hand":{},"third hand":{},"fourth hand":{}} with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) logThis(getName(user)+" entered the game") return getName(user)+" entered the game" else: logThis(user+" doesn't have enough GwendoBucks") return "You don't have enough GwendoBucks to place that bet" else: logThis(user+" tried to bet a negative amount") return "You can't bet a negative amount" else: logThis("The table is no longer open for bets") return "The table is no longer open for bets" else: logThis("There are already 5 players in the game.") return "There's already a maximum of players at the table." else: logThis(user+" is already in the game") return "You've already entered this game" else: logThis("There is no game going on in "+channel) return "There is no game going on in this channel" # Starts a game of blackjack def blackjackStart(channel:str): with open("resources/games/games.json", "r") as f: data = json.load(f) logThis("Trying to start a blackjack game in "+channel) if channel not in data["blackjack games"]: dealerHand = [drawCard(channel),drawCard(channel)] gameID = datetime.datetime.now().strftime('%Y%m%d%H%M%S') data["blackjack games"][channel] = {"dealer hand": dealerHand,"dealer busted":False,"dealer blackjack":False,"user hands": {},"all standing":False,"round":0,"id":gameID} if calcHandValue(dealerHand) == 21: data["blackjack games"][channel]["dealer blackjack"] = True with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) copyfile("resources/games/blackjackTable.png","resources/games/blackjackTables/blackjackTable"+channel+".png") return "started" else: logThis("There is already a blackjack game going on in "+channel) return "There's already a blackjack game going on. Try again in a few minutes." # Ends the game and calculates winnings def blackjackFinish(channel): finalWinnings = "*Final Winnings:*\n" with open("resources/games/games.json", "r") as f: data = json.load(f) dealerValue = calcHandValue(data["blackjack games"][channel]["dealer hand"]) dealerBlackjack = data["blackjack games"][channel]["dealer blackjack"] dealerBusted = data["blackjack games"][channel]["dealer busted"] try: for user in data["blackjack games"][channel]["user hands"]: try: winnings, netWinnings, reason = calcWinnings(data["blackjack games"][channel]["user hands"][user],dealerValue,True,dealerBlackjack,dealerBusted) except: logThis("Error calculating winnings for "+str(user)+" (error code 1312)") if winnings < 0: if winnings == -1: finalWinnings += getName(user)+" lost "+str(-1 * winnings)+" GwendoBuck "+reason+"\n" else: finalWinnings += getName(user)+" lost "+str(-1 * winnings)+" GwendoBucks "+reason+"\n" else: if winnings == 1: finalWinnings += getName(user)+" won "+str(winnings)+" GwendoBuck "+reason+"\n" else: finalWinnings += getName(user)+" won "+str(winnings)+" GwendoBucks "+reason+"\n" money.addMoney(user,netWinnings) except: logThis("Error calculating winnings (error code 1311)") with open("resources/games/games.json", "r") as f: data = json.load(f) del data["blackjack games"][channel] with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) return finalWinnings def calcWinnings(hand, dealerValue, topLevel, dealerBlackjack, dealerBusted): logThis("Calculating winnings") reason = "" bet = hand["bet"] winnings = -1 * bet netWinnings = 0 handValue = 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 = calcWinnings(hand["other hand"],dealerValue,False,dealerBlackjack,dealerBusted) winnings += winningsTemp netWinnings += netWinningsTemp reason += reasonTemp if hand["split"] >= 2: winningsTemp, netWinningsTemp, reasonTemp = calcWinnings(hand["third hand"],dealerValue,False,dealerBlackjack,dealerBusted) winnings += winningsTemp netWinnings += netWinningsTemp reason += reasonTemp if hand["split"] >= 3: winningsTemp, netWinningsTemp, reasonTemp = calcWinnings(hand["fourth hand"],dealerValue,False,dealerBlackjack,dealerBusted) winnings += winningsTemp netWinnings += netWinningsTemp reason += reasonTemp return winnings, netWinnings, reason def getHandNumber(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: logThis("Problem with getHandNumber() (error code 1322)") def isRoundDone(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