From 089791c3baedeb87390eddccb0d9ec10ea8aca97 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Wed, 5 Aug 2020 10:48:12 +0200 Subject: [PATCH 01/26] :bug: --- funcs/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/funcs/__init__.py b/funcs/__init__.py index d770dbd..581b835 100644 --- a/funcs/__init__.py +++ b/funcs/__init__.py @@ -1,6 +1,6 @@ """A collection of all Gwendolyn functions.""" -__all__ = ["helloFunc", "cap", "imageFunc", "logThis", "findWikiPage", "makeFiles", "emojiToNumber", "fiarReactionTest", "deleteGame", "stopServer", "checkBalance", "giveMoney", "addMoney", "triviaCountPoints", "triviaStart", "triviaAnswer", "blackjackShuffle", "blackjackStart", "blackjackPlayerDrawHand", "blackjackContinue", "blackjackFinish", "blackjackHit", "blackjackStand", "blackjackDouble", "blackjackSplit", "parseFourInARow", "fourInARowAI", "spellFunc", "monsterFunc", "nameGen", "tavernGen", "movieFunc", "roll_dice", "parseChar", "parseRoll", "critRoll", "parseDestiny", "parseHex", "addToDict", "getName", "getID"] +__all__ = ["helloFunc", "cap", "imageFunc", "logThis", "findWikiPage", "makeFiles", "emojiToNumber", "fiarReactionTest", "deleteGame", "stopServer", "checkBalance", "giveMoney", "addMoney", "triviaCountPoints", "triviaStart", "triviaAnswer", "blackjackShuffle", "blackjackStart", "blackjackPlayerDrawHand", "blackjackContinue", "blackjackFinish", "blackjackHit", "blackjackStand", "blackjackDouble", "blackjackSplit", "parseFourInARow", "fourInARowAI", "spellFunc", "monsterFunc", "nameGen", "tavernGen", "movieFunc", "roll_dice", "parseChar", "parseRoll", "critRoll", "parseDestiny", "parseHex", "addToDict", "getName", "getID","replaceMultiple","hexAI"] from .miscFuncs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, replaceMultiple, emojiToNumber, fiarReactionTest, deleteGame, stopServer, addToDict, getName, getID From b241dc13a8ac1c208460f0bd92b890f954310079 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Wed, 5 Aug 2020 11:19:24 +0200 Subject: [PATCH 02/26] :zap: Improving blackjack --- funcs/games/blackjack.py | 364 +++++++++++++++-------------------- funcs/games/blackjackDraw.py | 2 +- resources/errorCodes.txt | 3 +- 3 files changed, 156 insertions(+), 213 deletions(-) diff --git a/funcs/games/blackjack.py b/funcs/games/blackjack.py index 719bbd8..11e5647 100644 --- a/funcs/games/blackjack.py +++ b/funcs/games/blackjack.py @@ -197,126 +197,18 @@ def blackjackHit(channel,user,handNumber = 0): data = json.load(f) if user in data["blackjack games"][channel]["user hands"]: - if data["blackjack games"][channel]["user hands"][user]["split"] == 0: - hand = data["blackjack games"][channel]["user hands"][user] - handNumber = 0 - 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"] - elif handNumber == 4: - hand = data["blackjack games"][channel]["user hands"][user]["fourth hand"] - else: - logThis(user+" tried to hit without specifying which hand") - return "You have to specify the hand you're hitting with." - 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]["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 = True - - for person in data["blackjack games"][channel]["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 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+" 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 data["blackjack games"][channel]["user hands"][user]["split"] == 0: - hand = data["blackjack games"][channel]["user hands"][user] - handNumber = 0 - 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"] - elif handNumber == 4: - hand = data["blackjack games"][channel]["user hands"][user]["fourth hand"] - else: - logThis(user+" tried to double without specifying which hand") - return "You have to specify the hand you're doubling down.","" - else: - logThis(user+" tried to double without specifying which hand") - return "You have to specify the hand you're doubling down.","" - - - 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, 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 - hand["doubled"] = True - hand["bet"] += bet handValue = calcHandValue(hand["hand"]) - if handValue > 21: hand["busted"] = True @@ -333,41 +225,93 @@ def blackjackDouble(channel,user,handNumber = 0): with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) - roundDone = True + response = "accept" + roundDone = isRoundDone(data["blackjack games"][channel]) - for person in data["blackjack games"][channel]["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 "Adding another "+str(bet)+" GwendoBucks to "+getName(user)+"'s bet and drawing another card.",str(roundDone)[0] + str(data["blackjack games"][channel]["round"]) + return response + str(roundDone)[0] + str(data["blackjack games"][channel]["round"]) else: - logThis(user+" doesn't have enough GwendoBucks") - return "You don't have enough GwendoBucks","" + logThis(user+" is already standing") + return "You can't hit when you're standing" else: - logThis(user+" tried to double on round "+str(data["blackjack games"][channel]["round"])) - return "You can only double down on the first round","" + logThis(user+" has already hit this round") + return "You've already hit this round" else: - logThis(user+" is already standing") - return "You can't double when you're standing","" + logThis(user+" tried to hit on the 0th round") + return "You can't hit before you see your cards" else: - logThis(user+" has already hit this round") - return "You've already hit this round","" + logThis(user+" didn't specify a hand") + return "You need to specify a hand" else: - logThis(user+" tried to double on the 0th round") - return "You can't double down before you see your cards","" + 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): @@ -375,62 +319,33 @@ def blackjackStand(channel,user,handNumber = 0): data = json.load(f) if user in data["blackjack games"][channel]["user hands"]: - if data["blackjack games"][channel]["user hands"][user]["split"] == 0: - hand = data["blackjack games"][channel]["user hands"][user] - handNumber = 0 - 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"] - elif handNumber == 4: - hand = data["blackjack games"][channel]["user hands"][user]["fourth hand"] - else: - logThis(user+" tried to hit without specifying which hand") - return "You have to specify the hand you're hitting with." - 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]["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) + hand, handNumber = getHandNumber(data["blackjack games"][channel]["user hands"][user],handNumber) - response = "accept" - roundDone = True + 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) - for person in data["blackjack games"][channel]["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 + response = "accept" + roundDone = isRoundDone(data["blackjack games"][channel]) - 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 response + str(roundDone)[0] + str(data["blackjack games"][channel]["round"]) + 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+" is already standing") - return "You're already standing" + logThis(user+" has already hit this round") + return "You've already hit this round" else: - logThis(user+" has already hit this round") - return "You've already hit this round" + logThis(user+" tried to stand on the first round") + return "You can't stand before you see your cards" else: - logThis(user+" tried to stand on the first round") - return "You can't stand before you see your cards" + 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" @@ -526,23 +441,7 @@ def blackjackSplit(channel,user,handNumber = 0): with open("resources/games/games.json", "w") as f: json.dump(data,f,indent=4) - roundDone = True - - for person in data["blackjack games"][channel]["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 + 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: @@ -744,4 +643,47 @@ def calcWinnings(hand, dealerValue, topLevel, dealerBlackjack, dealerBusted): netWinnings += netWinningsTemp reason += reasonTemp - return winnings, netWinnings, reason \ No newline at end of file + 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 diff --git a/funcs/games/blackjackDraw.py b/funcs/games/blackjackDraw.py index 12e0a47..46c1eb4 100644 --- a/funcs/games/blackjackDraw.py +++ b/funcs/games/blackjackDraw.py @@ -36,7 +36,7 @@ def drawImage(channel): for x in range(len(hands)): key, value = list(hands.items())[x] key = getName(key) - logThis("drawing "+key+"'s hand") + #logThis("Drawing "+key+"'s hand") userHand = drawHand(value["hand"],False,value["busted"],value["blackjack"]) try: if value["split"] == 3: diff --git a/resources/errorCodes.txt b/resources/errorCodes.txt index 4876893..adde8e4 100644 --- a/resources/errorCodes.txt +++ b/resources/errorCodes.txt @@ -92,7 +92,8 @@ 1311 - Error calculating winnings 1312 - Error in calcWinnings function 1320 - Unspecified loop error -1321 - Loop interrupted while waiting +1321 - Loop interrupted while waiting +1322 - Error with getHandNumber() 1330 - Unspecified continue error 1331 - Error in testIfStanding() 1340 - Error in drawing blackjack table From e799eb792e016f10c1c8c601c449f99ace899e62 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Wed, 5 Aug 2020 11:50:29 +0200 Subject: [PATCH 03/26] :zap: Better makeFiles() --- funcs/miscFuncs.py | 174 ++++++--------------------- resources/lookup/lookupExamples.json | 56 --------- resources/startingFiles.json | 80 ++++++++++++ 3 files changed, 117 insertions(+), 193 deletions(-) delete mode 100644 resources/lookup/lookupExamples.json create mode 100644 resources/startingFiles.json diff --git a/funcs/miscFuncs.py b/funcs/miscFuncs.py index 90fe08a..b7fbf78 100644 --- a/funcs/miscFuncs.py +++ b/funcs/miscFuncs.py @@ -13,6 +13,7 @@ logging.basicConfig(filename="gwendolyn.log", level=logging.INFO) # Capitalizes all words except some of them no_caps_list = ["of","the"] def cap(s): + # Capitalizes a strink like a movie title word_number = 0 lst = s.split() res = '' @@ -25,7 +26,7 @@ def cap(s): return res def time_in_range(start, end, x): - """Return true if x is in the range [start, end]""" + # Return true if x is in the range [start, end] if start <= end: return start <= x <= end else: @@ -134,146 +135,45 @@ def findWikiPage(search : str): logThis("Couldn't find the page (error code 1002)") return "", "Couldn't find page (error code 1002)", "" +def makeJsonFile(path,content): + # Creates json file if it doesn't exist + try: + f = open(path,"r") + except: + logThis(path.split("/")[-1]+" didn't exist. Making it now.") + with open(path,"w") as f: + json.dump(content,f,indent = 4) + finally: + f.close() + +def makeTxtFile(path,content): + # Creates txt file if it doesn't exist + try: + f = open(path,"r") + except: + logThis(path.split("/")[-1]+" didn't exist. Making it now.") + with open(path,"w") as f: + f.write(content) + finally: + f.close() + +def makeFolder(path): + if os.path.isdir(path) == False: + os.makedirs(path) + logThis("The "+path.split("/")[-1]+" directory didn't exist") + def makeFiles(): - # Creates swcharacters.json if it doesn't exist - try: - f = open("resources/starWars/swcharacters.json","r") - except: - logThis("swcharacters.json didn't exist. Making it now.") - emptyDict = {} - with open("resources/starWars/swcharacters.json","w") as f: - json.dump(emptyDict,f,indent = 4) - finally: - f.close() - - # Creates games.json if it doesn't exist - try: - f = open("resources/games/games.json","r") - except: - logThis("games.json didn't exist. Making it now.") - data = {"trivia questions":{},"blackjack games":{},"4 in a row games": {},"users":{}} - with open("resources/games/games.json","w") as f: - json.dump(data,f,indent = 4) - finally: - f.close() + with open("resources/startingFiles.json") as f: + data = json.load(f) - # Creates hexGames.json if it doesn't exist - try: - f = open("resources/games/hexGames.json","r") - except: - logThis("hexGames.json didn't exist. Making it now.") - data = {} - with open("resources/games/hexGames.json","w") as f: - json.dump(data,f,indent = 4) - finally: - f.close() - - # Creates monsters.json if it doesn't exist - try: - f = open("resources/lookup/monsters.json","r") - except: - logThis("monsters.json didn't exist. Making it now.") - with open("resources/lookup/lookupExamples.json") as f: - data = json.load(f)["monster"] - with open("resources/lookup/monsters.json","w") as f: - json.dump(data,f,indent = 4) - finally: - f.close() - - # Creates spells.json if it doesn't exist - try: - f = open("resources/lookup/spells.json","r") - except: - logThis("spells.json didn't exist. Making it now.") - with open("resources/lookup/lookupExamples.json") as f: - data = json.load(f)["spell"] - with open("resources/lookup/spells.json","w") as f: - json.dump(data,f,indent = 4) - finally: - f.close() + for path, content in data["json"].items(): + makeJsonFile(path,content) - # Creates users.json if it doesn't exist - try: - f = open("resources/users.json","r") - except: - logThis("users.json didn't exist. Making it now.") - data = {} - with open("resources/users.json","w") as f: - json.dump(data,f,indent = 4) - finally: - f.close() - - # Creates destinyPoints.txt if it doesn't exist - try: - f = open("resources/starWars/destinyPoints.txt","r") - except: - logThis("destinyPoints.txt didn't exist. Making it now.") - with open("resources/starWars/destinyPoints.txt","w") as f: - f.write("") - finally: - f.close() + for path, content in data["txt"].items(): + makeTxtFile(path,content) - # Creates movies.txt if it doesn't exist - try: - f = open("resources/movies.txt","r") - except: - logThis("movies.txt didn't exist. Making it now.") - with open("resources/movies.txt","w") as f: - f.write("The Room") - finally: - f.close() - - # Creates names.txt if it doesn't exist - try: - f = open("resources/names.txt","r") - except: - logThis("names.txt didn't exist. Making it now.") - with open("resources/names.txt","w") as f: - f.write("Gandalf") - finally: - f.close() - - # Creates token.txt if it doesn't exist - try: - f = open("token.txt","r") - except: - logThis("token.txt didn't exist. Write your bot token below, or in token.txt later.") - token = input() - with open("token.txt","w") as f: - f.write(token) - - finally: - f.close() - - # Creates the blackjacktables foulder if it doesn't exist - if os.path.isdir("resources/games/blackjackTables") == False: - os.makedirs("resources/games/blackjackTables") - logThis("The tables directory didn't exist") - - # Creates the 4InARowBoards foulder if it doesn't exist - if os.path.isdir("resources/games/4InARowBoards") == False: - os.makedirs("resources/games/4InARowBoards") - logThis("The 4 in a row boards directory didn't exist") - - # Creates the hexBoards foulder if it doesn't exist - if os.path.isdir("resources/games/hexBoards") == False: - os.makedirs("resources/games/hexBoards") - logThis("The Hex boards directory didn't exist") - - # Creates the oldImages foulder if it doesn't exist - if os.path.isdir("resources/games/oldImages") == False: - os.makedirs("resources/games/oldImages") - logThis("The old images directory didn't exist") - - # Creates the blackjackCards foulder if it doesn't exist - if os.path.isdir("resources/games/blackjackCards") == False: - os.makedirs("resources/games/blackjackCards") - logThis("The blackjack cards directory didn't exist") - - # Creates the hilo foulder if it doesn't exist - if os.path.isdir("resources/games/hilo") == False: - os.makedirs("resources/games/hilo") - logThis("The hi-lo directory didn't exist") + for path in data["folder"]: + makeFolder(path) # Replaces multiple things with the same thing def replaceMultiple(mainString, toBeReplaces, newString): diff --git a/resources/lookup/lookupExamples.json b/resources/lookup/lookupExamples.json deleted file mode 100644 index 0e6f0d4..0000000 --- a/resources/lookup/lookupExamples.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "monster" : [ - { - "name": "Bandit", - "size": "Medium", - "type": "humanoid", - "subtype": "any race", - "alignment": "any non-lawful alignment", - "armor_class": 12, - "hit_points": 11, - "hit_dice": "2d8", - "speed": "30 ft.", - "strength": 11, - "dexterity": 12, - "constitution": 12, - "intelligence": 10, - "wisdom": 10, - "charisma": 10, - "damage_vulnerabilities": "", - "damage_resistances": "", - "damage_immunities": "", - "condition_immunities": "", - "senses": "passive Perception 10", - "languages": "any one language (usually Common)", - "challenge_rating": "1/8", - "actions": [ - { - "name": "Scimitar", - "desc": "Melee Weapon Attack: +3 to hit, reach 5 ft., one target. Hit: 4 (1d6 + 1) slashing damage.", - "attack_bonus": 3, - "damage_dice": "1d6", - "damage_bonus": 1 - }, - { - "name": "Light Crossbow", - "desc": "Ranged Weapon Attack: +3 to hit, range 80 ft./320 ft., one target. Hit: 5 (1d8 + 1) piercing damage.", - "attack_bonus": 3, - "damage_dice": "1d8", - "damage_bonus": 1 - } - ] - } - ], - "spell": { - "Fireball" : { - "casting_time" : "1 action", - "components" : "V, S, M (a tiny ball of bat guano and sulfur)", - "description" : "A bright streak flashes from your pointing finger to a point you choose within range and then blossoms with a low roar into an explosion of flame. Each creature in a 20-foot-radius sphere centered on that point must make a Dexterity saving throw. A target takes 8d6 fire damage on a failed save, or half as much damage on a successful one. The fire spreads around corners. It ignites flammable objects in the area that aren’t being worn or carried. At Higher Levels. When you cast this spell using a spell slot of 4th level or higher, the damage increases by 1d6 for each slot level above 3rd.", - "duration" : "Instantaneous", - "level" : "3rd", - "range" : "150 feet", - "school" : "Evocation", - "ritual" : false - } - } -} \ No newline at end of file diff --git a/resources/startingFiles.json b/resources/startingFiles.json new file mode 100644 index 0000000..8846a9d --- /dev/null +++ b/resources/startingFiles.json @@ -0,0 +1,80 @@ +{ + "json":{ + "resources/starWars/swcharacters.json" : {}, + "resources/games/hexGames.json": {}, + "resources/users.json" : {}, + "resources/games/games.json" : { + "trivia questions":{}, + "blackjack games":{}, + "4 in a row games": {} + }, + "resources/lookup/spells.json" : { + "Fireball" : { + "casting_time" : "1 action", + "components" : "V, S, M (a tiny ball of bat guano and sulfur)", + "description" : "A bright streak flashes from your pointing finger to a point you choose within range and then blossoms with a low roar into an explosion of flame. Each creature in a 20-foot-radius sphere centered on that point must make a Dexterity saving throw. A target takes 8d6 fire damage on a failed save, or half as much damage on a successful one. The fire spreads around corners. It ignites flammable objects in the area that aren’t being worn or carried. At Higher Levels. When you cast this spell using a spell slot of 4th level or higher, the damage increases by 1d6 for each slot level above 3rd.", + "duration" : "Instantaneous", + "level" : "3rd", + "range" : "150 feet", + "school" : "Evocation", + "ritual" : false + } + }, + "resources/lookup/monsters.json" : [ + { + "name": "Bandit", + "size": "Medium", + "type": "humanoid", + "subtype": "any race", + "alignment": "any non-lawful alignment", + "armor_class": 12, + "hit_points": 11, + "hit_dice": "2d8", + "speed": "30 ft.", + "strength": 11, + "dexterity": 12, + "constitution": 12, + "intelligence": 10, + "wisdom": 10, + "charisma": 10, + "damage_vulnerabilities": "", + "damage_resistances": "", + "damage_immunities": "", + "condition_immunities": "", + "senses": "passive Perception 10", + "languages": "any one language (usually Common)", + "challenge_rating": "1/8", + "actions": [ + { + "name": "Scimitar", + "desc": "Melee Weapon Attack: +3 to hit, reach 5 ft., one target. Hit: 4 (1d6 + 1) slashing damage.", + "attack_bonus": 3, + "damage_dice": "1d6", + "damage_bonus": 1 + }, + { + "name": "Light Crossbow", + "desc": "Ranged Weapon Attack: +3 to hit, range 80 ft./320 ft., one target. Hit: 5 (1d8 + 1) piercing damage.", + "attack_bonus": 3, + "damage_dice": "1d8", + "damage_bonus": 1 + } + ] + } + ] + }, + "txt": { + "resources/starWars/destinyPoints.txt": "", + "resources/movies.txt": "The Room", + "resources/names.txt": "Gandalf", + "token.txt" : "Write token here" + }, + "folder" : [ + "resources/games/blackjackTables", + "resources/games/4InARowBoards", + "resources/games/hexBoards", + "resources/games/oldImages", + "resources/games/blackjackCards", + "resources/games/hilo" + ] +} \ No newline at end of file From f9c9bcef1b81237e559bd813812893234152fbb7 Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Wed, 5 Aug 2020 14:04:19 +0200 Subject: [PATCH 04/26] :art: --- funcs/games/fourInARowDraw.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/funcs/games/fourInARowDraw.py b/funcs/games/fourInARowDraw.py index ddbbc9e..fddef65 100644 --- a/funcs/games/fourInARowDraw.py +++ b/funcs/games/fourInARowDraw.py @@ -20,6 +20,9 @@ def drawImage(channel): exampleCircles = 100 w, h = 2800,2000 backgroundColor = (128,128,128,255) + outlineColor = (0,0,0) + player1Color = (200,0,0) + player2Color = (255,255,0) boardColor = (0,0,170) placeSize = 285 white = (255,255,255,160) @@ -48,35 +51,33 @@ def drawImage(channel): # This whole part was the easiest way to make a rectangle with rounded corners and an outline # - Corners: - d.ellipse([(border,border),(border+cornerSize,border+cornerSize)],fill=boardColor,outline=(0,0,0),width=outlineSize) - d.ellipse([(w-(border+cornerSize),h-(border+cornerSize)),(w-border,h-border)],fill=boardColor,outline=(0,0,0),width=outlineSize) - d.ellipse([(border,h-(border+cornerSize)),(border+cornerSize,h-border)],fill=boardColor,outline=(0,0,0),width=outlineSize) - d.ellipse([(w-(border+cornerSize),border),(w-border,border+cornerSize)],fill=boardColor,outline=(0,0,0),width=outlineSize) + d.ellipse([(border,border),(border+cornerSize,border+cornerSize)],fill=boardColor,outline=outlineColor,width=outlineSize) + d.ellipse([(w-(border+cornerSize),h-(border+cornerSize)),(w-border,h-border)],fill=boardColor,outline=outlineColor,width=outlineSize) + d.ellipse([(border,h-(border+cornerSize)),(border+cornerSize,h-border)],fill=boardColor,outline=outlineColor,width=outlineSize) + d.ellipse([(w-(border+cornerSize),border),(w-border,border+cornerSize)],fill=boardColor,outline=outlineColor,width=outlineSize) # - Rectangle: - d.rectangle([(border+math.floor(cornerSize/2),border),(w-(border+math.floor(cornerSize/2)),h-border)],fill=boardColor,outline=(0,0,0),width=outlineSize) - d.rectangle([(border,border+math.floor(cornerSize/2)),(w-border,h-(border+math.floor(cornerSize/2)))],fill=boardColor,outline=(0,0,0),width=outlineSize) + d.rectangle([(border+math.floor(cornerSize/2),border),(w-(border+math.floor(cornerSize/2)),h-border)],fill=boardColor,outline=outlineColor,width=outlineSize) + d.rectangle([(border,border+math.floor(cornerSize/2)),(w-border,h-(border+math.floor(cornerSize/2)))],fill=boardColor,outline=outlineColor,width=outlineSize) # - Removing outline on the inside: d.rectangle([(border+math.floor(cornerSize/2),border+math.floor(cornerSize/2)),(w-(border+math.floor(cornerSize/2)),h-(border+math.floor(cornerSize/2)))],fill=boardColor) - d.ellipse([(border+outlineSize,border+outlineSize),(border+cornerSize-outlineSize,border+cornerSize-outlineSize)],fill=boardColor) - d.ellipse([(w-(border+cornerSize)+outlineSize,h-(border+cornerSize)+outlineSize),(w-border-outlineSize,h-border-outlineSize)],fill=boardColor) - d.ellipse([(border+outlineSize,h-(border+cornerSize)+outlineSize),(border+cornerSize-outlineSize,h-border-outlineSize)],fill=boardColor) - d.ellipse([(w-(border+cornerSize)+outlineSize,border+outlineSize),(w-border-outlineSize,border+cornerSize-outlineSize)],fill=boardColor) + d.rectangle([(border+math.floor(cornerSize/2),border+outlineSize),(w-(border+math.floor(cornerSize/2)),h-(border+outlineSize))],fill=boardColor) + d.rectangle([(border+outlineSize,border+math.floor(cornerSize/2)),(w-(border+outlineSize),h-(border+math.floor(cornerSize/2)))],fill=boardColor) for line in range(len(board)): for place in range(len(board[line])): piece = board[line][place] if piece == 1: - pieceColor = (255,255,0) + pieceColor = player1Color elif piece == 2: - pieceColor = (200,0,0) + pieceColor = player2Color else: pieceColor = backgroundColor startx = pieceStartx + placeGridSize[0]*place starty = pieceStarty + placeGridSize[1]*line - d.ellipse([(startx,starty),(startx+placeSize,starty+placeSize)],fill=pieceColor,outline=(0,0,0),width=outlineSize) + d.ellipse([(startx,starty),(startx+placeSize,starty+placeSize)],fill=pieceColor,outline=outlineColor,width=outlineSize) if data["4 in a row games"][channel]["winner"] != 0: coordinates = data["4 in a row games"][channel]["win coordinates"] @@ -133,11 +134,11 @@ def drawImage(channel): textPadding = 20 exampleHeight = h - border + int((bottomBorder+border)/2) - int(exampleCircles/2) - d.ellipse([(border,exampleHeight),(border+exampleCircles),(exampleHeight+exampleCircles)],fill=(255,255,0),outline=(0,0,0),width=3) + d.ellipse([(border,exampleHeight),(border+exampleCircles),(exampleHeight+exampleCircles)],fill=player1Color,outline=outlineColor,width=3) d.text((border+exampleCircles+textPadding,exampleHeight),player1,font=fnt,fill=(0,0,0)) textWidth = fnt.getsize(player2)[0] - d.ellipse([(w-border-exampleCircles-textWidth-textPadding,exampleHeight),(w-border-textWidth-textPadding),(exampleHeight+exampleCircles)],fill=(255,0,0),outline=(0,0,0),width=3) + d.ellipse([(w-border-exampleCircles-textWidth-textPadding,exampleHeight),(w-border-textWidth-textPadding),(exampleHeight+exampleCircles)],fill=player2Color,outline=outlineColor,width=3) d.text((w-border-textWidth,exampleHeight),player2,font=fnt,fill=(0,0,0)) From eaabb6d43f72fee07918db4b5629090099447c8c Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Wed, 5 Aug 2020 18:15:45 +0200 Subject: [PATCH 05/26] :game_die: monopoly framework --- .gitignore | 1 + Gwendolyn.py | 21 ++- funcs/__init__.py | 6 +- funcs/games/__init__.py | 5 +- funcs/games/monopoly.py | 124 ++++++++++++++++++ funcs/games/monopolyDraw.py | 57 ++++++++ funcs/miscFuncs.py | 29 +++- gameLoops.py | 47 ++++++- resources/errorCodes.txt | 11 ++ resources/games/monopolyBoard.png | Bin 0 -> 23558 bytes .../monopolyBoards/monopolyBoardtest.png | Bin 0 -> 23921 bytes resources/startingFiles.json | 4 +- 12 files changed, 285 insertions(+), 20 deletions(-) create mode 100644 funcs/games/monopoly.py create mode 100644 funcs/games/monopolyDraw.py create mode 100644 resources/games/monopolyBoard.png create mode 100644 resources/games/monopolyBoards/monopolyBoardtest.png diff --git a/.gitignore b/.gitignore index e09e81f..76cf4ae 100644 --- a/.gitignore +++ b/.gitignore @@ -153,6 +153,7 @@ token.txt resources/starWars/swcharacters.json resources/games/games.json resources/games/hexGames.json +resources/games/monopolyGames.json resources/games/blackjackCards/ resources/games/hilo/ resources/starWars/destinyPoints.txt diff --git a/Gwendolyn.py b/Gwendolyn.py index 96bc45b..ce549b1 100644 --- a/Gwendolyn.py +++ b/Gwendolyn.py @@ -10,9 +10,9 @@ import random #import math import os -from funcs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, emojiToNumber, fiarReactionTest, deleteGame, stopServer, checkBalance, giveMoney, triviaCountPoints, triviaStart, triviaAnswer, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackContinue, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit, parseFourInARow, fourInARowAI, spellFunc, monsterFunc, nameGen, tavernGen, movieFunc, roll_dice, parseChar, parseRoll, critRoll, parseDestiny, parseHex, addToDict +from funcs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, emojiToCommand, fiarReactionTest, deleteGame, stopServer, checkBalance, giveMoney, triviaCountPoints, triviaStart, triviaAnswer, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackContinue, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit, parseFourInARow, fourInARowAI, spellFunc, monsterFunc, nameGen, tavernGen, movieFunc, roll_dice, parseChar, parseRoll, critRoll, parseDestiny, parseHex, addToDict, monopolyReactionTest -from gameLoops import fiar, blackjackLoop, runHex +from gameLoops import fiar, blackjackLoop, runHex, runMonopoly commandPrefix = "!" @@ -569,6 +569,14 @@ async def parseCommands(message,content): except: logThis("Something went wrong (error code 1500)") + # Runs a game of monopoly + elif content.startswith("monopoly"): + try: + command = content.replace("monopoly","",1) + await runMonopoly(message.channel,command,"#"+str(message.author.id)) + except: + logThis("Something went wrong (error code 1600)") + # Not a command else: logThis("That's not a command (error code 001)",str(message.channel)) @@ -615,11 +623,16 @@ async def on_reaction_add(reaction,user): message = reaction.message channel = message.channel logThis(user.display_name+" reacted to a message",str(channel)) - fourInARowTheirTurn, piece = fiarReactionTest(channel,message,"#"+str(user.id)) + try: + fourInARowTheirTurn, piece = fiarReactionTest(channel,message,"#"+str(user.id)) + except: + fourInARowTheirTurn = False if fourInARowTheirTurn: - place = emojiToNumber(reaction.emoji) + place = emojiToCommand(reaction.emoji) await fiar(channel," place "+str(piece)+" "+str(place),user.id) + elif monopolyReactionTest(channel,message): + await runMonopoly(channel,"roll","#"+str(user.id)) # Runs the whole shabang client.run(token) diff --git a/funcs/__init__.py b/funcs/__init__.py index 581b835..c9aff3d 100644 --- a/funcs/__init__.py +++ b/funcs/__init__.py @@ -1,10 +1,10 @@ """A collection of all Gwendolyn functions.""" -__all__ = ["helloFunc", "cap", "imageFunc", "logThis", "findWikiPage", "makeFiles", "emojiToNumber", "fiarReactionTest", "deleteGame", "stopServer", "checkBalance", "giveMoney", "addMoney", "triviaCountPoints", "triviaStart", "triviaAnswer", "blackjackShuffle", "blackjackStart", "blackjackPlayerDrawHand", "blackjackContinue", "blackjackFinish", "blackjackHit", "blackjackStand", "blackjackDouble", "blackjackSplit", "parseFourInARow", "fourInARowAI", "spellFunc", "monsterFunc", "nameGen", "tavernGen", "movieFunc", "roll_dice", "parseChar", "parseRoll", "critRoll", "parseDestiny", "parseHex", "addToDict", "getName", "getID","replaceMultiple","hexAI"] +__all__ = ["helloFunc", "cap", "imageFunc", "logThis", "findWikiPage", "makeFiles", "emojiToCommand", "fiarReactionTest", "deleteGame", "stopServer", "checkBalance", "giveMoney", "addMoney", "triviaCountPoints", "triviaStart", "triviaAnswer", "blackjackShuffle", "blackjackStart", "blackjackPlayerDrawHand", "blackjackContinue", "blackjackFinish", "blackjackHit", "blackjackStand", "blackjackDouble", "blackjackSplit", "parseFourInARow", "fourInARowAI", "spellFunc", "monsterFunc", "nameGen", "tavernGen", "movieFunc", "roll_dice", "parseChar", "parseRoll", "critRoll", "parseDestiny", "parseHex", "addToDict", "getName", "getID", "replaceMultiple", "hexAI", "parseMonopoly", "monopolyContinue", "monopolyReactionTest"] -from .miscFuncs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, replaceMultiple, emojiToNumber, fiarReactionTest, deleteGame, stopServer, addToDict, getName, getID +from .miscFuncs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, replaceMultiple, emojiToCommand, fiarReactionTest, deleteGame, stopServer, addToDict, getName, getID, monopolyReactionTest -from .games import checkBalance, giveMoney, addMoney, triviaCountPoints, triviaStart, triviaAnswer, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackContinue, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit, parseFourInARow, fourInARowAI, parseHex, hexAI +from .games import checkBalance, giveMoney, addMoney, triviaCountPoints, triviaStart, triviaAnswer, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackContinue, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit, parseFourInARow, fourInARowAI, parseHex, hexAI, parseMonopoly, monopolyContinue from .lookup import spellFunc, monsterFunc diff --git a/funcs/games/__init__.py b/funcs/games/__init__.py index e577d3e..38b3487 100644 --- a/funcs/games/__init__.py +++ b/funcs/games/__init__.py @@ -1,9 +1,10 @@ """Functions for games Gwendolyn can play.""" -__all__ = ["checkBalance", "giveMoney", "addMoney","triviaCountPoints", "triviaStart", "triviaAnswer", "blackjackShuffle", "blackjackStart", "blackjackPlayerDrawHand", "blackjackContinue", "blackjackFinish", "blackjackHit", "blackjackStand", "blackjackDouble", "blackjackSplit", "parseFourInARow", "fourInARowAI", "parseHex"] +__all__ = ["checkBalance", "giveMoney", "addMoney","triviaCountPoints", "triviaStart", "triviaAnswer", "blackjackShuffle", "blackjackStart", "blackjackPlayerDrawHand", "blackjackContinue", "blackjackFinish", "blackjackHit", "blackjackStand", "blackjackDouble", "blackjackSplit", "parseFourInARow", "fourInARowAI", "parseHex", "parseMonopoly", "monopolyContinue"] from .money import checkBalance, giveMoney, addMoney from .trivia import triviaCountPoints, triviaStart, triviaAnswer from .blackjack import blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackContinue, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit from .fourInARow import parseFourInARow, fourInARowAI -from .hex import parseHex, hexAI \ No newline at end of file +from .hex import parseHex, hexAI +from .monopoly import parseMonopoly, monopolyContinue \ No newline at end of file diff --git a/funcs/games/monopoly.py b/funcs/games/monopoly.py new file mode 100644 index 0000000..4990add --- /dev/null +++ b/funcs/games/monopoly.py @@ -0,0 +1,124 @@ +import json, random + +from funcs import getName, logThis +from . import monopolyDraw + +def monopolyStart(channel): + logThis("Starting a monopoly game") + with open("resources/games/monopolyGames.json", "r") as f: + data = json.load(f) + + if channel not in data: + buildings = [0] * 40 + + data[channel] = {"players" : {}, "player list" : [],"turn" : 0, "buildings" : buildings, "last roll" : [0,0], "started" : False} + + with open("resources/games/monopolyGames.json", "w") as f: + json.dump(data,f,indent=4) + + try: + monopolyDraw.drawImage(channel) + except: + logThis("Error drawing board (error code 1640)") + + return "Started a monopoly game. Use \"!monopoly join\" to join within the next minute.", True, False, True, True + else: + return "There's already a monopoly game going on.", False, False, False, False + +def monopolyJoin(channel,user): + with open("resources/games/monopolyGames.json", "r") as f: + data = json.load(f) + + if channel in data: + if not data[channel]["started"]: + if user not in data[channel]["players"]: + if len(data[channel]["players"]) < 6: + + data[channel]["players"][user] = {"position" : 0, "properties" : [], "money" : 1500, "doubles" : 0} + + with open("resources/games/monopolyGames.json", "w") as f: + json.dump(data,f,indent=4) + + return getName(user)+" has joined the game.", False, False, False, False + else: + return "There are already 6 players in the game.", False, False, False, False + else: + return "You're already in the game!", False, False, False, False + else: + return "It's too late to join.", False, False, False, False + else: + return "There's no game going on.", False, False, False, False + +def parseMonopoly(command, channel, user): + logThis("Parsing "+command) + commands = command.split() + if command in [" ", ""] or commands[0] == "start": + try: + return monopolyStart(channel) + except: + logThis("Error starting game (error code 1620)") + elif commands[0] == "join": + try: + return monopolyJoin(channel,user) + except: + logThis("Error joining game (error code 1630)") + elif commands[0] == "roll": + try: + return monopolyRoll(channel,user) + except: + logThis("Error rolling (error code 1650)") + else: + return "I didn't understand that (error code 1602)", False, False, False, False + +def monopolyContinue(channel): + with open("resources/games/monopolyGames.json", "r") as f: + data = json.load(f) + + if channel in data: + if data[channel]["started"] == False: + data[channel]["started"] = True + playerList = list(data[channel]["players"].keys()) + random.shuffle(playerList) + data[channel]["player list"] = playerList + turn = 0 + + else: + turn = (data[channel]["turn"])%len(data[channel]["player list"]) + data[channel]["turn"] = turn + playerList = list(data[channel]["players"].keys()) + + with open("resources/games/monopolyGames.json", "w") as f: + json.dump(data,f,indent=4) + + try: + monopolyDraw.drawImage(channel) + except: + logThis("Error drawing board (error code 1640)") + + message = "It's "+getName(playerList[turn])+"'s turn. Use the 🎲 reaction to roll. You can also use \"!monopoly trade\" at any time." + return message, True, True, False + +def monopolyRoll(channel,user): + with open("resources/games/monopolyGames.json", "r") as f: + data = json.load(f) + + turn = data[channel]["turn"] + currentPlayer = data[channel]["player list"][turn] + + if user == currentPlayer: + rolls = [random.randint(1,6),random.randint(1,6)] + roll = rolls[0] + rolls[1] + newPosition = (data[channel]["players"][user]["position"] + roll)%40 + data[channel]["players"][user]["position"] = newPosition + data[channel]["last roll"] = rolls + + with open("resources/games/monopolyGames.json", "w") as f: + json.dump(data,f,indent=4) + + try: + monopolyDraw.drawImage(channel) + except: + logThis("Error drawing board (error code 1640)") + + return "Rolled a "+str(rolls[0])+" and a "+str(rolls[1])+".", True, True, False, True + else: return "", False, False, False, False diff --git a/funcs/games/monopolyDraw.py b/funcs/games/monopolyDraw.py new file mode 100644 index 0000000..598cc8c --- /dev/null +++ b/funcs/games/monopolyDraw.py @@ -0,0 +1,57 @@ +import math, json + +from funcs import logThis + +from PIL import Image, ImageDraw + +w, h = 1440, 1440 +largeSpace = 191 +smallSpace = math.floor((w - 2*largeSpace)/9) +avatarSize = 50 +avatarHalf = math.floor(avatarSize/2) + +def drawImage(channel): + logThis("Drawing monopoly board for "+channel) + with open("resources/games/monopolyGames.json", "r") as f: + data = json.load(f) + + board = Image.open("resources/games/monopolyBoard.png") + d = ImageDraw.Draw(board,"RGBA") + + for key, value in list(data[channel]["players"].items()): + logThis("Drawing "+key) + try: + x, y = getPosition(value["position"]) + except: + logThis("Error getting position (error code 1641)") + print(str(x)+", "+str(y)) + d.ellipse([(x-avatarHalf,y-avatarHalf),(x+avatarHalf,y+avatarHalf)],fill=(255,0,0)) + + board.save("resources/games/monopolyBoards/monopolyBoard"+channel+".png") + + +def getPosition(positionNumber): + print(positionNumber) + + x, y = 0, 0 + if positionNumber == 0 or positionNumber >= 30: + x = math.floor(largeSpace/2) + elif positionNumber > 0 and positionNumber < 10: + x = math.floor(largeSpace - (smallSpace/2)) + (smallSpace*positionNumber) + elif positionNumber >= 10 and positionNumber <= 20: + x = w - math.floor(largeSpace/2) + elif positionNumber > 20 and positionNumber < 30: + x = w - math.floor(largeSpace - (smallSpace/2)) - (smallSpace*(positionNumber - 20)) + + if positionNumber >= 0 and positionNumber <= 9: + y = math.floor(largeSpace/2) + elif positionNumber > 10 and positionNumber < 19: + y = math.floor(largeSpace - (smallSpace/2)) + (smallSpace*(positionNumber-10)) + elif positionNumber >= 20 and positionNumber <= 30: + y = h - math.floor(largeSpace/2) + elif positionNumber > 30: + y = h - math.floor(largeSpace - (smallSpace/2)) - (smallSpace*(positionNumber - 30)) + + return x, y + + diff --git a/funcs/miscFuncs.py b/funcs/miscFuncs.py index b7fbf78..6e17e5d 100644 --- a/funcs/miscFuncs.py +++ b/funcs/miscFuncs.py @@ -186,7 +186,7 @@ def replaceMultiple(mainString, toBeReplaces, newString): return mainString -def emojiToNumber(emoji): +def emojiToCommand(emoji): if emoji == "1️⃣": return 1 elif emoji == "2️⃣": @@ -201,6 +201,8 @@ def emojiToNumber(emoji): return 6 elif emoji == "7️⃣": return 7 + elif emoji == "🎲": + return "roll" else: return "" def fiarReactionTest(channel,message,user): @@ -223,16 +225,31 @@ def fiarReactionTest(channel,message,user): else: return False, 0 +def monopolyReactionTest(channel,message): + with open("resources/games/oldImages/monopoly"+str(channel), "r") as f: + oldImage = int(f.read()) + + if message.id == oldImage: + logThis("They reacted to the monopoly game") + return True + else: + return False + def stopServer(): with open("resources/games/games.json","r") as f: - data = json.load(f) + games = json.load(f) - data["trivia questions"] = {} - data["blackjack games"] = {} - data["4 in a row games"] = {} + games["trivia questions"] = {} + games["blackjack games"] = {} + games["4 in a row games"] = {} with open("resources/games/games.json","w") as f: - json.dump(data,f,indent=4) + json.dump(games,f,indent=4) + + emptyDict = {} + + with open("resources/games/monopolyGames.json", "w") as f: + json.dump(emptyDict,f,indent=4) def deleteGame(gameType,channel): with open("resources/games/games.json", "r") as f: diff --git a/gameLoops.py b/gameLoops.py index e8ef39f..058f033 100644 --- a/gameLoops.py +++ b/gameLoops.py @@ -2,7 +2,7 @@ import asyncio import discord import json -from funcs import logThis, addMoney, deleteGame, parseFourInARow, fourInARowAI, blackjackContinue, blackjackFinish, parseHex, hexAI +from funcs import logThis, addMoney, deleteGame, parseFourInARow, fourInARowAI, blackjackContinue, blackjackFinish, parseHex, hexAI, parseMonopoly, monopolyContinue # Deletes a message async def deleteMessage(imageLocation,channel): @@ -119,9 +119,6 @@ async def fiar(channel,command,user): await oldImage.add_reaction(reaction) except: logThis("Image deleted before I could react to all of them") -# else: -# with open("resources/games/oldImages/fourInARow"+str(channel), "w") as f: -# f.write(str(oldImage.id)) if gameDone: with open("resources/games/games.json", "r") as f: @@ -192,3 +189,45 @@ async def blackjackLoop(channel,gameRound,gameID): logThis("Ending loop on round "+str(gameRound),str(channel)) else: logThis("Ending loop on round "+str(gameRound),str(channel)) + +async def runMonopoly(channel, command, user): + try: + response, showImage, deleteImage, gameStarted, gameContinue = parseMonopoly(command,str(channel),user) + except: + logThis("Error parsing command (error code 1610)") + if response != "": + await channel.send(response) + logThis(response,str(channel)) + if showImage: + if deleteImage: + try: + oldImage = await deleteMessage("monopoly"+str(channel),channel) + except: + logThis("Error deleting message (error code 1601)") + oldImage = await channel.send(file = discord.File("resources/games/monopolyBoards/monopolyBoard"+str(channel)+".png")) + with open("resources/games/oldImages/monopoly"+str(channel), "w") as f: + f.write(str(oldImage.id)) + + if gameContinue: + if gameStarted: + await asyncio.sleep(60) + else: + await asyncio.sleep(5) + response, showImage, deleteImage, gameDone = monopolyContinue(str(channel)) + em = discord.Embed(description=response,colour = 0x59f442) + await channel.send(embed=em) + if showImage: + if deleteImage: + try: + oldImage = await deleteMessage("monopoly"+str(channel),channel) + except: + logThis("Error deleting message (error code 1601)") + oldImage = await channel.send(file = discord.File("resources/games/monopolyBoards/monopolyBoard"+str(channel)+".png")) + with open("resources/games/oldImages/monopoly"+str(channel), "w") as f: + f.write(str(oldImage.id)) + if gameDone == False: + try: + await oldImage.add_reaction("🎲") + except: + logThis("Image deleted before I could react to all of them") + \ No newline at end of file diff --git a/resources/errorCodes.txt b/resources/errorCodes.txt index adde8e4..1e08b02 100644 --- a/resources/errorCodes.txt +++ b/resources/errorCodes.txt @@ -113,3 +113,14 @@ 1531 - Invalid position 1532 - Cannot place on existing piece 1533 - Position out of bounds + +16 - Monopoly +1600 - Unspecified error +1601 - Error deleting old image +1602 - Not a command +1610 - Unspecified parsing error +1620 - Unspecified monopolyStart() error +1630 - Unspecified monopolyJoin() error +1640 - Unspecified monopolyDraw error +1641 - Error in getPosition() +1650 - Error in monopolyRoll() diff --git a/resources/games/monopolyBoard.png b/resources/games/monopolyBoard.png new file mode 100644 index 0000000000000000000000000000000000000000..a7cb5c8eb03f7fd0236155b361b09e89bf381873 GIT binary patch literal 23558 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 E0M$H#m;e9( literal 0 HcmV?d00001 diff --git a/resources/games/monopolyBoards/monopolyBoardtest.png b/resources/games/monopolyBoards/monopolyBoardtest.png new file mode 100644 index 0000000000000000000000000000000000000000..50d8787946f2373e839a28ad49e99eb6bc35f2e9 GIT binary patch literal 23921 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 Date: Wed, 5 Aug 2020 18:39:37 +0200 Subject: [PATCH 06/26] :pencil: Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 76cf4ae..f1f852f 100644 --- a/.gitignore +++ b/.gitignore @@ -160,6 +160,7 @@ resources/starWars/destinyPoints.txt resources/games/blackjackTables/ resources/games/oldImages/ resources/games/4InARowBoards/ +resources/games/monopolyBoards/ resources/lookup/monsters.json resources/lookup/spells.json resources/movies.txt From 591a3744cc00a2e2361596bf6128700032c788c3 Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Wed, 5 Aug 2020 18:49:22 +0200 Subject: [PATCH 07/26] :bug: --- funcs/miscFuncs.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/funcs/miscFuncs.py b/funcs/miscFuncs.py index 6e17e5d..0546f0a 100644 --- a/funcs/miscFuncs.py +++ b/funcs/miscFuncs.py @@ -215,8 +215,6 @@ def fiarReactionTest(channel,message,user): if message.id == oldImage: logThis("They reacted to the fourinarow game") turn = data["4 in a row games"][str(channel)]["turn"] - print(user) - print(data["4 in a row games"][str(channel)]["players"][turn]) if user == data["4 in a row games"][str(channel)]["players"][turn]: return True, turn+1 else: From 517f0bb90a955e190029bec30b05dbab713419ef Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Wed, 5 Aug 2020 19:41:09 +0200 Subject: [PATCH 08/26] :bug: --- funcs/games/__init__.py | 4 ++-- funcs/roll/errors.py | 30 +++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/funcs/games/__init__.py b/funcs/games/__init__.py index 38b3487..aac0119 100644 --- a/funcs/games/__init__.py +++ b/funcs/games/__init__.py @@ -1,10 +1,10 @@ """Functions for games Gwendolyn can play.""" -__all__ = ["checkBalance", "giveMoney", "addMoney","triviaCountPoints", "triviaStart", "triviaAnswer", "blackjackShuffle", "blackjackStart", "blackjackPlayerDrawHand", "blackjackContinue", "blackjackFinish", "blackjackHit", "blackjackStand", "blackjackDouble", "blackjackSplit", "parseFourInARow", "fourInARowAI", "parseHex", "parseMonopoly", "monopolyContinue"] +__all__ = ["checkBalance", "giveMoney", "addMoney","triviaCountPoints", "triviaStart", "triviaAnswer", "blackjackShuffle", "blackjackStart", "blackjackPlayerDrawHand", "blackjackContinue", "blackjackFinish", "blackjackHit", "blackjackStand", "blackjackDouble", "blackjackSplit", "parseFourInARow", "fourInARowAI", "parseHex", "hexAI", "parseMonopoly", "monopolyContinue"] from .money import checkBalance, giveMoney, addMoney from .trivia import triviaCountPoints, triviaStart, triviaAnswer from .blackjack import blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackContinue, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit from .fourInARow import parseFourInARow, fourInARowAI from .hex import parseHex, hexAI -from .monopoly import parseMonopoly, monopolyContinue \ No newline at end of file +from .monopoly import parseMonopoly, monopo;lyContinue \ No newline at end of file diff --git a/funcs/roll/errors.py b/funcs/roll/errors.py index 3c7d488..0f78629 100644 --- a/funcs/roll/errors.py +++ b/funcs/roll/errors.py @@ -1,18 +1,25 @@ class AvraeException(Exception): + """A base exception class.""" def __init__(self, msg): + + """A.""" super().__init__(msg) class NoCharacter(AvraeException): + """Raised when a user has no active character.""" def __init__(self): + + """A.""" super().__init__("You have no character active.") class NoActiveBrew(AvraeException): + """Raised when a user has no active homebrew of a certain type.""" def __init__(self): @@ -20,6 +27,7 @@ class NoActiveBrew(AvraeException): class ExternalImportError(AvraeException): + """Raised when something fails to import.""" def __init__(self, msg): @@ -27,11 +35,13 @@ class ExternalImportError(AvraeException): class InvalidArgument(AvraeException): + """Raised when an argument is invalid.""" pass class EvaluationError(AvraeException): + """Raised when a cvar evaluation causes an error.""" def __init__(self, original): @@ -40,15 +50,15 @@ class EvaluationError(AvraeException): class FunctionRequiresCharacter(AvraeException): - """ - Raised when a function that requires a character is called without one. - """ + + """Raised when a function that requires a character is called without one.""" def __init__(self, msg=None): super().__init__(msg or "This alias requires an active character.") class OutdatedSheet(AvraeException): + """Raised when a feature is used that requires an updated sheet.""" def __init__(self, msg=None): @@ -71,11 +81,13 @@ class InvalidSaveType(AvraeException): class ConsumableException(AvraeException): + """A base exception for consumable exceptions to stem from.""" pass class ConsumableNotFound(ConsumableException): + """Raised when a consumable is not found.""" def __init__(self): @@ -83,6 +95,7 @@ class ConsumableNotFound(ConsumableException): class CounterOutOfBounds(ConsumableException): + """Raised when a counter is set to a value out of bounds.""" def __init__(self): @@ -90,6 +103,7 @@ class CounterOutOfBounds(ConsumableException): class NoReset(ConsumableException): + """Raised when a consumable without a reset is reset.""" def __init__(self): @@ -97,6 +111,7 @@ class NoReset(ConsumableException): class InvalidSpellLevel(ConsumableException): + """Raised when a spell level is invalid.""" def __init__(self): @@ -104,11 +119,13 @@ class InvalidSpellLevel(ConsumableException): class SelectionException(AvraeException): + """A base exception for message awaiting exceptions to stem from.""" pass class NoSelectionElements(SelectionException): + """Raised when get_selection() is called with no choices.""" def __init__(self, msg=None): @@ -116,6 +133,7 @@ class NoSelectionElements(SelectionException): class SelectionCancelled(SelectionException): + """Raised when get_selection() is cancelled or times out.""" def __init__(self): @@ -123,11 +141,13 @@ class SelectionCancelled(SelectionException): class CombatException(AvraeException): + """A base exception for combat-related exceptions to stem from.""" pass class CombatNotFound(CombatException): + """Raised when a channel is not in combat.""" def __init__(self): @@ -135,6 +155,7 @@ class CombatNotFound(CombatException): class RequiresContext(CombatException): + """Raised when a combat is committed without context.""" def __init__(self): @@ -142,6 +163,7 @@ class RequiresContext(CombatException): class ChannelInCombat(CombatException): + """Raised when a combat is started with an already active combat.""" def __init__(self): @@ -149,6 +171,7 @@ class ChannelInCombat(CombatException): class CombatChannelNotFound(CombatException): + """Raised when a combat's channel is not in the channel list.""" def __init__(self): @@ -156,6 +179,7 @@ class CombatChannelNotFound(CombatException): class NoCombatants(CombatException): + """Raised when a combat tries to advance turn with no combatants.""" def __init__(self): From 59df6f2edddab8cc2021093ceca46e4e29f19c6d Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Wed, 5 Aug 2020 22:10:21 +0200 Subject: [PATCH 09/26] :game_die: Better !roll command --- Gwendolyn.py | 2 +- funcs/games/__init__.py | 2 +- funcs/roll/__init__.py | 2 +- funcs/roll/dice.py | 562 +--------------------------------------- funcs/roll/errors.py | 186 ------------- 5 files changed, 14 insertions(+), 740 deletions(-) delete mode 100644 funcs/roll/errors.py diff --git a/Gwendolyn.py b/Gwendolyn.py index ce549b1..03e7b37 100644 --- a/Gwendolyn.py +++ b/Gwendolyn.py @@ -88,7 +88,7 @@ async def parseCommands(message,content): await message.channel.send(roll_dice(message.author.display_name, content.replace("roll",""))) except: logThis("Something fucked up (error code 400)",str(message.channel)) - await message.channel.send("Something fucked up (error code 400)") + await message.channel.send("Not a valid command (error code 400)") # Looks up a spell with the spellFunc function from funcs/lookup/lookuppy elif content.startswith("spell "): diff --git a/funcs/games/__init__.py b/funcs/games/__init__.py index aac0119..49deac1 100644 --- a/funcs/games/__init__.py +++ b/funcs/games/__init__.py @@ -7,4 +7,4 @@ from .trivia import triviaCountPoints, triviaStart, triviaAnswer from .blackjack import blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackContinue, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit from .fourInARow import parseFourInARow, fourInARowAI from .hex import parseHex, hexAI -from .monopoly import parseMonopoly, monopo;lyContinue \ No newline at end of file +from .monopoly import parseMonopoly, monopolyContinue \ No newline at end of file diff --git a/funcs/roll/__init__.py b/funcs/roll/__init__.py index 243ed83..e356957 100644 --- a/funcs/roll/__init__.py +++ b/funcs/roll/__init__.py @@ -1,4 +1,4 @@ -"""I stole this.""" +"""Rolling dice.""" __all__ = ["roll_dice"] diff --git a/funcs/roll/dice.py b/funcs/roll/dice.py index 4b331eb..9fe7761 100644 --- a/funcs/roll/dice.py +++ b/funcs/roll/dice.py @@ -1,560 +1,20 @@ -import random -import re -import traceback -from heapq import nlargest, nsmallest -from math import floor -from re import IGNORECASE +import d20 -import numexpr +class MyStringifier(d20.MarkdownStringifier): -from . import errors -#from funcs import logThis + def _str_expression(self, node): -VALID_OPERATORS = 'k|rr|ro|mi|ma|ra|e|p' -VALID_OPERATORS_ARRAY = VALID_OPERATORS.split('|') -VALID_OPERATORS_2 = re.compile('|'.join(["({})".format(i) for i in VALID_OPERATORS_ARRAY])) -DICE_PATTERN = re.compile( - r'^\s*(?:(?:(\d*d\d+)(?:(?:' + VALID_OPERATORS + r')(?:[lh<>]?\d+))*|(\d+)|([-+*/().=])?)\s*(\[.*\])?)(.*?)\s*$', - IGNORECASE) - - -def roll_dice(author : str, rollStr : str = "1d20"): - if rollStr == '0/0': # easter eggs - return("What do you expect me to do, destroy the universe?") - - adv = 0 - if re.search('(^|\s+)(adv|dis)(\s+|$)', rollStr) is not None: - adv = 1 if re.search('(^|\s+)adv(\s+|$)', rollStr) is not None else -1 - rollStr = re.sub('(adv|dis)(\s+|$)', '', rollStr) - res = roll(rollStr, adv=adv) - out = res.result - outStr = author + ' :game_die:\n' + out - if len(outStr) > 1999: - outputs = author + ' :game_die:\n[Output truncated due to length]\n**Result:** ' + str(res.plain) - else: - outputs = outStr - return(outputs) - -def list_get(index, default, l): - try: - a = l[index] - except IndexError: - a = default - return a - - -def roll(rollStr, adv: int = 0, rollFor='', inline=False, double=False, show_blurbs=True, **kwargs): - roller = Roll() - result = roller.roll(rollStr, adv, rollFor, inline, double, show_blurbs, **kwargs) - return result - - -def get_roll_comment(rollStr): - """Returns: A two-tuple (dice without comment, comment)""" - try: - comment = '' - no_comment = '' - dice_set = re.split('([-+*/().=])', rollStr) - dice_set = [d for d in dice_set if not d in (None, '')] - #logThis("Found dice set: " + str(dice_set)) - for index, dice in enumerate(dice_set): - match = DICE_PATTERN.match(dice) - #logThis("Found dice group: " + str(match.groups())) - no_comment += dice.replace(match.group(5), '') - if match.group(5): - comment = match.group(5) + ''.join(dice_set[index + 1:]) - break - - return no_comment, comment - except: - pass - return rollStr, '' - - -class Roll(object): - def __init__(self, parts=None): - if parts ==None: - parts = [] - self.parts = parts - - def get_crit(self): - """Returns: 0 for no crit, 1 for 20, 2 for 1.""" - try: - crit = next(p.get_crit() for p in self.parts if isinstance(p, SingleDiceGroup)) - except StopIteration: - crit = 0 - return crit - - def get_total(self): - """Returns: int""" - return numexpr.evaluate(''.join(p.get_eval() for p in self.parts if not isinstance(p, Comment))) - - # # Dice Roller - def roll(self, rollStr, adv: int = 0, rollFor='', inline=False, double=False, show_blurbs=True, **kwargs): - try: - if '**' in rollStr: - raise errors.InvalidArgument("Exponents are currently disabled.") - self.parts = [] - # split roll string into XdYoptsSel [comment] or Op - # set remainder to comment - # parse each, returning a SingleDiceResult - dice_set = re.split('([-+*/().=])', rollStr) - dice_set = [d for d in dice_set if not d in (None, '')] - #logThis("Found dice set: " + str(dice_set)) - for index, dice in enumerate(dice_set): - match = DICE_PATTERN.match(dice) - #logThis("Found dice group: " + str(match.groups())) - # check if it's dice - if match.group(1): - roll = self.roll_one(dice.replace(match.group(5), ''), adv) - self.parts.append(roll) - # or a constant - elif match.group(2): - self.parts.append(Constant(value=int(match.group(2)), annotation=match.group(4))) - # or an operator - elif not match.group(5): - self.parts.append(Operator(op=match.group(3), annotation=match.group(4))) - - if match.group(5): - self.parts.append(Comment(match.group(5) + ''.join(dice_set[index + 1:]))) - break - - # calculate total - crit = self.get_crit() - try: - total = self.get_total() - except SyntaxError: - raise errors.InvalidArgument("No dice found to roll.") - rolled = ' '.join(str(res) for res in self.parts if not isinstance(res, Comment)) - if rollFor =='': - rollFor = ''.join(str(c) for c in self.parts if isinstance(c, Comment)) - # return final solution - if not inline: - # Builds end result while showing rolls - reply = ' '.join( - str(res) for res in self.parts if not isinstance(res, Comment)) + '\n**Total:** ' + str( - floor(total)) - skeletonReply = reply - rollFor = rollFor if rollFor != '' else 'Result' - reply = '**{}:** '.format(rollFor) + reply - if show_blurbs: - if adv == 1: - reply += '\n**Rolled with Advantage**' - elif adv == -1: - reply += '\n**Rolled with Disadvantage**' - if crit == 1: - critStr = "\n_**Critical Hit!**_ " - reply += critStr - elif crit == 2: - critStr = "\n_**Critical Fail!**_ " - reply += critStr - else: - # Builds end result while showing rolls - reply = ' '.join(str(res) for res in self.parts if not isinstance(res, Comment)) + ' = `' + str( - floor(total)) + '`' - skeletonReply = reply - rollFor = rollFor if rollFor != '' else 'Result' - reply = '**{}:** '.format(rollFor) + reply - if show_blurbs: - if adv == 1: - reply += '\n**Rolled with Advantage**' - elif adv == -1: - reply += '\n**Rolled with Disadvantage**' - if crit == 1: - critStr = "\n_**Critical Hit!**_ " - reply += critStr - elif crit == 2: - critStr = "\n_**Critical Fail!**_ " - reply += critStr - reply = re.sub(' +', ' ', reply) - skeletonReply = re.sub(' +', ' ', str(skeletonReply)) - return DiceResult(result=int(floor(total)), verbose_result=reply, crit=crit, rolled=rolled, - skeleton=skeletonReply, raw_dice=self) - except Exception as ex: - if not isinstance(ex, (SyntaxError, KeyError, errors.AvraeException)): - #logThis('Error in roll() caused by roll {}:'.format(rollStr)) - traceback.print_exc() - return DiceResult(verbose_result="Invalid input: {}".format(ex)) - - def roll_one(self, dice, adv: int = 0): - result = SingleDiceGroup() - result.rolled = [] - # splits dice and comments - split = re.match(r'^([^\[\]]*?)\s*(\[.*\])?\s*$', dice) - dice = split.group(1).strip() - annotation = split.group(2) - result.annotation = annotation if annotation != None else '' - # Recognizes dice - obj = re.findall('\d+', dice) - obj = [int(x) for x in obj] - numArgs = len(obj) - - ops = [] - if numArgs == 1: - if not dice.startswith('d'): - raise errors.InvalidArgument('Please pass in the value of the dice.') - numDice = 1 - diceVal = obj[0] - if adv != 0 and diceVal == 20: - numDice = 2 - ops = ['k', 'h1'] if adv ==1 else ['k', 'l1'] - elif numArgs == 2: - numDice = obj[0] - diceVal = obj[-1] - if adv != 0 and diceVal == 20: - ops = ['k', 'h' + str(numDice)] if adv ==1 else ['k', 'l' + str(numDice)] - numDice = numDice * 2 - else: # split into xdy and operators - numDice = obj[0] - diceVal = obj[1] - dice = re.split('(\d+d\d+)', dice)[-1] - ops = VALID_OPERATORS_2.split(dice) - ops = [a for a in ops if a != None] - - # dice repair/modification - if numDice > 300 or diceVal < 1: - raise errors.InvalidArgument('Too many dice rolled.') - - result.max_value = diceVal - result.num_dice = numDice - result.operators = ops - - for _ in range(numDice): - try: - tempdice = SingleDice() - tempdice.value = random.randint(1, diceVal) - tempdice.rolls = [tempdice.value] - tempdice.max_value = diceVal - tempdice.kept = True - result.rolled.append(tempdice) - except: - result.rolled.append(SingleDice()) - - if ops != None: - - rerollList = [] - reroll_once = [] - keep = None - to_explode = [] - to_reroll_add = [] - - valid_operators = VALID_OPERATORS_ARRAY - last_operator = None - for index, op in enumerate(ops): - if last_operator != None and op in valid_operators and not op == last_operator: - result.reroll(reroll_once, 1) - reroll_once = [] - result.reroll(rerollList, greedy=True) - rerollList = [] - result.keep(keep) - keep = None - result.reroll(to_reroll_add, 1, keep_rerolled=True, unique=True) - to_reroll_add = [] - result.reroll(to_explode, greedy=True, keep_rerolled=True) - to_explode = [] - if op == 'rr': - rerollList += parse_selectors([list_get(index + 1, 0, ops)], result, greedy=True) - if op == 'k': - keep = [] if keep ==None else keep - keep += parse_selectors([list_get(index + 1, 0, ops)], result) - if op == 'p': - keep = [] if keep ==None else keep - keep += parse_selectors([list_get(index + 1, 0, ops)], result, inverse=True) - if op == 'ro': - reroll_once += parse_selectors([list_get(index + 1, 0, ops)], result) - if op == 'mi': - _min = list_get(index + 1, 0, ops) - for r in result.rolled: - if r.value < int(_min): - r.update(int(_min)) - if op == 'ma': - _max = list_get(index + 1, 0, ops) - for r in result.rolled: - if r.value > int(_max): - r.update(int(_max)) - if op == 'ra': - to_reroll_add += parse_selectors([list_get(index + 1, 0, ops)], result) - if op == 'e': - to_explode += parse_selectors([list_get(index + 1, 0, ops)], result, greedy=True) - if op in valid_operators: - last_operator = op - result.reroll(reroll_once, 1) - result.reroll(rerollList, greedy=True) - result.keep(keep) - result.reroll(to_reroll_add, 1, keep_rerolled=True, unique=True) - result.reroll(to_explode, greedy=True, keep_rerolled=True) - - return result - - -class Part: - """Class to hold one part of the roll string.""" - pass - - -class SingleDiceGroup(Part): - def __init__(self, num_dice: int = 0, max_value: int = 0, rolled=None, annotation: str = "", result: str = "", - operators=None): - if operators ==None: - operators = [] - if rolled ==None: - rolled = [] - self.num_dice = num_dice - self.max_value = max_value - self.rolled = rolled # list of SingleDice - self.annotation = annotation - self.result = result - self.operators = operators - - def keep(self, rolls_to_keep): - if rolls_to_keep ==None: return - for _roll in self.rolled: - if not _roll.value in rolls_to_keep: - _roll.kept = False - elif _roll.kept: - rolls_to_keep.remove(_roll.value) - - def reroll(self, rerollList, max_iterations=1000, greedy=False, keep_rerolled=False, unique=False): - if not rerollList: return # don't reroll nothing - minor optimization - if unique: - rerollList = list(set(rerollList)) # remove duplicates - if len(rerollList) > 100: - raise OverflowError("Too many dice to reroll (max 100)") - last_index = 0 - count = 0 - should_continue = True - while should_continue: # let's only iterate 250 times for sanity - should_continue = False - if any(d.value in set(rerollList) for d in self.rolled[last_index:] if d.kept and not d.exploded): - should_continue = True - to_extend = [] - for r in self.rolled[last_index:]: # no need to recheck everything - count += 1 - if count > max_iterations: - should_continue = False - if r.value in rerollList and r.kept and not r.exploded: - try: - tempdice = SingleDice() - tempdice.value = random.randint(1, self.max_value) - tempdice.rolls = [tempdice.value] - tempdice.max_value = self.max_value - tempdice.kept = True - to_extend.append(tempdice) - if not keep_rerolled: - r.drop() - else: - r.explode() - except: - to_extend.append(SingleDice()) - if not keep_rerolled: - r.drop() - else: - r.explode() - if not greedy: - rerollList.remove(r.value) - last_index = len(self.rolled) - self.rolled.extend(to_extend) - - def get_total(self): - """Returns: - int - The total value of the dice.""" - return sum(r.value for r in self.rolled if r.kept) - - def get_eval(self): - return str(self.get_total()) - - def get_num_kept(self): - return sum(1 for r in self.rolled if r.kept) - - def get_crit(self): - """Returns: - int - 0 for no crit, 1 for crit, 2 for crit fail.""" - if self.get_num_kept() == 1 and self.max_value == 20: - if self.get_total() == 20: - return 1 - elif self.get_total() == 1: - return 2 - return 0 - - def __str__(self): - return "{0.num_dice}d{0.max_value}{1} ({2}) {0.annotation}".format( - self, ''.join(self.operators), ', '.join(str(r) for r in self.rolled)) - - def to_dict(self): - return {'type': 'dice', 'dice': [d.to_dict() for d in self.rolled], 'annotation': self.annotation, - 'value': self.get_total(), 'is_crit': self.get_crit(), 'num_kept': self.get_num_kept(), - 'text': str(self), 'num_dice': self.num_dice, 'dice_size': self.max_value, 'operators': self.operators} - - -class SingleDice: - def __init__(self, value: int = 0, max_value: int = 0, kept: bool = True, exploded: bool = False): - self.value = value - self.max_value = max_value - self.kept = kept - self.rolls = [value] # list of ints (for X -> Y -> Z) - self.exploded = exploded - - def drop(self): - self.kept = False - - def explode(self): - self.exploded = True - - def update(self, new_value): - self.value = new_value - self.rolls.append(new_value) - - def __str__(self): - formatted_rolls = [str(r) for r in self.rolls] - if int(formatted_rolls[-1]) == self.max_value or int(formatted_rolls[-1]) == 1: - formatted_rolls[-1] = '**' + formatted_rolls[-1] + '**' - if self.exploded: - formatted_rolls[-1] = '__' + formatted_rolls[-1] + '__' - if self.kept: - return ' -> '.join(formatted_rolls) + if node.comment == None: + resultText = "Result" else: - return '~~' + ' -> '.join(formatted_rolls) + '~~' + resultText = node.comment.capitalize() - def __repr__(self): - return "".format( - self) + return f"**{resultText}**: {self._stringify(node.roll)}\n**Total**: {int(node.total)}" - def to_dict(self): - return {'type': 'single_dice', 'value': self.value, 'size': self.max_value, 'is_kept': self.kept, - 'rolls': self.rolls, 'exploded': self.exploded} +def roll_dice(user,rollString = "1d20"): + while len(rollString) > 1 and rollString[0] == " ": + rollString = rollString[1:] + return user+" :game_die:\n"+str(d20.roll(rollString, allow_comments=True,stringifier=MyStringifier())) -class Constant(Part): - def __init__(self, value: int = 0, annotation: str = ""): - self.value = value - self.annotation = annotation if annotation != None else '' - def __str__(self): - return "{0.value} {0.annotation}".format(self) - - def get_eval(self): - return str(self.value) - - def to_dict(self): - return {'type': 'constant', 'value': self.value, 'annotation': self.annotation} - - -class Operator(Part): - def __init__(self, op: str = "+", annotation: str = ""): - self.op = op if op != None else '' - self.annotation = annotation if annotation != None else '' - - def __str__(self): - return "{0.op} {0.annotation}".format(self) - - def get_eval(self): - return self.op - - def to_dict(self): - return {'type': 'operator', 'value': self.op, 'annotation': self.annotation} - - -class Comment(Part): - def __init__(self, comment: str = ""): - self.comment = comment - - def __str__(self): - return self.comment.strip() - - def to_dict(self): - return {'type': 'comment', 'value': self.comment} - - -def parse_selectors(opts, res, greedy=False, inverse=False): - """Returns a list of ints.""" - for o in range(len(opts)): - if opts[o][0] =='h': - opts[o] = nlargest(int(opts[o].split('h')[1]), (d.value for d in res.rolled if d.kept)) - elif opts[o][0] =='l': - opts[o] = nsmallest(int(opts[o].split('l')[1]), (d.value for d in res.rolled if d.kept)) - elif opts[o][0] =='>': - if greedy: - opts[o] = list(range(int(opts[o].split('>')[1]) + 1, res.max_value + 1)) - else: - opts[o] = [d.value for d in res.rolled if d.value > int(opts[o].split('>')[1])] - elif opts[o][0] =='<': - if greedy: - opts[o] = list(range(1, int(opts[o].split('<')[1]))) - else: - opts[o] = [d.value for d in res.rolled if d.value < int(opts[o].split('<')[1])] - out = [] - for o in opts: - if isinstance(o, list): - out.extend(int(l) for l in o) - elif not greedy: - out.extend(int(o) for a in res.rolled if a.value ==int(o) and a.kept) - else: - out.append(int(o)) - - if not inverse: - return out - - inverse_out = [] - for rolled in res.rolled: - if rolled.kept and rolled.value in out: - out.remove(rolled.value) - elif rolled.kept: - inverse_out.append(rolled.value) - return inverse_out - - -class DiceResult: - """Class to hold the output of a dice roll.""" - - def __init__(self, result: int = 0, verbose_result: str = '', crit: int = 0, rolled: str = '', skeleton: str = '', - raw_dice: Roll = None): - self.plain = result - self.total = result - self.result = verbose_result - self.crit = crit - self.rolled = rolled - self.skeleton = skeleton if skeleton != '' else verbose_result - self.raw_dice = raw_dice # Roll - - def __str__(self): - return self.result - - def __repr__(self): - return ''.format(self.total) - - def consolidated(self): - """Gets the most simplified version of the roll string.""" - if self.raw_dice ==None: - return "0" - parts = [] # list of (part, annotation) - last_part = "" - for p in self.raw_dice.parts: - if isinstance(p, SingleDiceGroup): - last_part += str(p.get_total()) - else: - last_part += str(p) - if not isinstance(p, Comment) and p.annotation: - parts.append((last_part, p.annotation)) - last_part = "" - if last_part: - parts.append((last_part, "")) - - to_roll = "" - last_annotation = "" - out = "" - for numbers, annotation in parts: - if annotation and annotation != last_annotation and to_roll: - out += f"{roll(to_roll).total:+} {last_annotation}" - to_roll = "" - if annotation: - last_annotation = annotation - to_roll += numbers - if to_roll: - out += f"{roll(to_roll).total:+} {last_annotation}" - out = out.strip('+ ') - return out - - -if __name__ == '__main__': - while True: - print(roll(input().strip())) diff --git a/funcs/roll/errors.py b/funcs/roll/errors.py deleted file mode 100644 index 0f78629..0000000 --- a/funcs/roll/errors.py +++ /dev/null @@ -1,186 +0,0 @@ -class AvraeException(Exception): - - """A base exception class.""" - - def __init__(self, msg): - - """A.""" - super().__init__(msg) - - -class NoCharacter(AvraeException): - - """Raised when a user has no active character.""" - - def __init__(self): - - """A.""" - super().__init__("You have no character active.") - - -class NoActiveBrew(AvraeException): - - """Raised when a user has no active homebrew of a certain type.""" - - def __init__(self): - super().__init__("You have no homebrew of this type active.") - - -class ExternalImportError(AvraeException): - - """Raised when something fails to import.""" - - def __init__(self, msg): - super().__init__(msg) - - -class InvalidArgument(AvraeException): - - """Raised when an argument is invalid.""" - pass - - -class EvaluationError(AvraeException): - - """Raised when a cvar evaluation causes an error.""" - - def __init__(self, original): - super().__init__(f"Error evaluating expression: {original}") - self.original = original - - -class FunctionRequiresCharacter(AvraeException): - - """Raised when a function that requires a character is called without one.""" - - def __init__(self, msg=None): - super().__init__(msg or "This alias requires an active character.") - - -class OutdatedSheet(AvraeException): - - """Raised when a feature is used that requires an updated sheet.""" - - def __init__(self, msg=None): - super().__init__(msg or "This command requires an updated character sheet. Try running `!update`.") - - -class NoSpellDC(AvraeException): - def __init__(self): - super().__init__("No spell save DC found.") - - -class NoSpellAB(AvraeException): - def __init__(self): - super().__init__("No spell attack bonus found.") - - -class InvalidSaveType(AvraeException): - def __init__(self): - super().__init__("Invalid save type.") - - -class ConsumableException(AvraeException): - - """A base exception for consumable exceptions to stem from.""" - pass - - -class ConsumableNotFound(ConsumableException): - - """Raised when a consumable is not found.""" - - def __init__(self): - super().__init__("The requested counter does not exist.") - - -class CounterOutOfBounds(ConsumableException): - - """Raised when a counter is set to a value out of bounds.""" - - def __init__(self): - super().__init__("The new value is out of bounds.") - - -class NoReset(ConsumableException): - - """Raised when a consumable without a reset is reset.""" - - def __init__(self): - super().__init__("The counter does not have a reset value.") - - -class InvalidSpellLevel(ConsumableException): - - """Raised when a spell level is invalid.""" - - def __init__(self): - super().__init__("The spell level is invalid.") - - -class SelectionException(AvraeException): - - """A base exception for message awaiting exceptions to stem from.""" - pass - - -class NoSelectionElements(SelectionException): - - """Raised when get_selection() is called with no choices.""" - - def __init__(self, msg=None): - super().__init__(msg or "There are no choices to select from.") - - -class SelectionCancelled(SelectionException): - - """Raised when get_selection() is cancelled or times out.""" - - def __init__(self): - super().__init__("Selection timed out or was cancelled.") - - -class CombatException(AvraeException): - - """A base exception for combat-related exceptions to stem from.""" - pass - - -class CombatNotFound(CombatException): - - """Raised when a channel is not in combat.""" - - def __init__(self): - super().__init__("This channel is not in combat.") - - -class RequiresContext(CombatException): - - """Raised when a combat is committed without context.""" - - def __init__(self): - super().__init__("Combat not contextualized.") - - -class ChannelInCombat(CombatException): - - """Raised when a combat is started with an already active combat.""" - - def __init__(self): - super().__init__("Channel already in combat.") - - -class CombatChannelNotFound(CombatException): - - """Raised when a combat's channel is not in the channel list.""" - - def __init__(self): - super().__init__("Combat channel does not exist.") - - -class NoCombatants(CombatException): - - """Raised when a combat tries to advance turn with no combatants.""" - - def __init__(self): - super().__init__("There are no combatants.") From c913e657d60e748e863fe56e1f7bb96aabdcd237 Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Wed, 5 Aug 2020 22:24:54 +0200 Subject: [PATCH 10/26] :broom: Cleanup in help files --- resources/help/help-blackjack.txt | 2 +- resources/help/help-fourinarow.txt | 2 +- resources/help/help-give.txt | 2 +- resources/help/help-hello.txt | 2 +- resources/help/help-hex.txt | 2 +- resources/help/help-monster.txt | 2 +- resources/help/help-roll.txt | 14 ++++++------ resources/help/help-spell.txt | 2 +- resources/help/help-swchar.txt | 2 +- resources/help/help-trivia.txt | 4 ++-- resources/help/help.txt | 34 +++++++++++++++--------------- 11 files changed, 34 insertions(+), 34 deletions(-) diff --git a/resources/help/help-blackjack.txt b/resources/help/help-blackjack.txt index 379fe8e..45f5c43 100644 --- a/resources/help/help-blackjack.txt +++ b/resources/help/help-blackjack.txt @@ -1 +1 @@ -Kommandoen "!blackjack" starter et spil blackjack. "!blackjack bet [beløb]" lader dig vædde en mængde af dine GwendoBucks. Du bruger "!blackjack hit", "!blackjack stand", "!blackjack split" og "!blackjack double" i løbet af spillet. \ No newline at end of file +Kommandoen `!blackjack` starter et spil blackjack. `!blackjack bet [beløb]` lader dig vædde en mængde af dine GwendoBucks. Du bruger `!blackjack hit`, `!blackjack stand`, `!blackjack split` og `!blackjack double` i løbet af spillet. \ No newline at end of file diff --git a/resources/help/help-fourinarow.txt b/resources/help/help-fourinarow.txt index fdd43ad..c191230 100644 --- a/resources/help/help-fourinarow.txt +++ b/resources/help/help-fourinarow.txt @@ -1 +1 @@ -Brug "!fourinarow start" til at starte et spil imod Gwendolyn. Brug "!fourinarow start [modstander]" for at spille imod en anden person. \ No newline at end of file +Brug `!fourinarow start` til at starte et spil imod Gwendolyn. Brug `!fourinarow start [modstander]` for at spille imod en anden person. Du kan også bruge `!fourinarow start [1-5]`, hvor tallet er sværhedsgraden af Gwendolyn du gerne vil spille imod. \ No newline at end of file diff --git a/resources/help/help-give.txt b/resources/help/help-give.txt index 1ad44e0..5fbb27f 100644 --- a/resources/help/help-give.txt +++ b/resources/help/help-give.txt @@ -1 +1 @@ -Du kan give GwendoBucks til andre med "!give [modtager] [antal]", hvor [modtager] er den der skal modtage GwendoBucks og [antal] er hvor mange GwendoBucks du giver dem. \ No newline at end of file +Du kan give GwendoBucks til andre med `!give [modtager] [antal]`, hvor [modtager] er den der skal modtage GwendoBucks og [antal] er hvor mange GwendoBucks du giver dem. \ No newline at end of file diff --git a/resources/help/help-hello.txt b/resources/help/help-hello.txt index b55ca49..deee19f 100644 --- a/resources/help/help-hello.txt +++ b/resources/help/help-hello.txt @@ -1 +1 @@ -Hvis du bruger kommandoen "!hello", sender Gwendolyn en venlig hilsen. \ No newline at end of file +Hvis du bruger kommandoen `!hello`, sender Gwendolyn en venlig hilsen. \ No newline at end of file diff --git a/resources/help/help-hex.txt b/resources/help/help-hex.txt index 9dce68d..99d5b96 100644 --- a/resources/help/help-hex.txt +++ b/resources/help/help-hex.txt @@ -1 +1 @@ -Brug "!hex start" til at starte et spil imod Gwendolyn. Brug "!hex start [modstander]" for at spille imod en anden person. \ No newline at end of file +Brug `!hex start` til at starte et spil imod Gwendolyn. Brug "!hex start [modstander]" for at spille imod en anden person. \ No newline at end of file diff --git a/resources/help/help-monster.txt b/resources/help/help-monster.txt index d8b207b..4c7a22f 100644 --- a/resources/help/help-monster.txt +++ b/resources/help/help-monster.txt @@ -1,2 +1,2 @@ -Søg efter et monster i D&D med "!monster [monster]", hvor [monster] er navnet på det monster du søger efter. +Søg efter et monster i D&D med `!monster [monster]`, hvor [monster] er navnet på det monster du søger efter. Hvis Gwendolyn ikke kan finde det, er det ofte fordi du har skrevet navnet forkert. \ No newline at end of file diff --git a/resources/help/help-roll.txt b/resources/help/help-roll.txt index 5291d99..6cef66e 100644 --- a/resources/help/help-roll.txt +++ b/resources/help/help-roll.txt @@ -1,8 +1,8 @@ Rul terninger i xdy format. Kan udføre matematik udover rullende. Kan også gøre følgende: -kx: Beholder kun rul med værdien x. -rox: Genrul rul med værdien x første gang. -rrx: Genrul alle rul med værdien x -mix: Gør alle rul under x til x. -max: Gør alle rul over x til x. -rax: Genruller og tilføjer rul med værdien x. -l/h før x: For de laveste/højeste x rul. \ No newline at end of file +`kx` - Beholder kun rul med værdien x. +`rox` - Genrul rul med værdien x første gang. +`rrx` - Genrul alle rul med værdien x +`mix` - Gør alle rul under x til x. +`max` - Gør alle rul over x til x. +`rax` - Genruller og tilføjer rul med værdien x. +`l/h` før x - For de laveste/højeste x rul. \ No newline at end of file diff --git a/resources/help/help-spell.txt b/resources/help/help-spell.txt index 49c38fe..16d9eb4 100644 --- a/resources/help/help-spell.txt +++ b/resources/help/help-spell.txt @@ -1,2 +1,2 @@ -Søg efter en spell i D&D med "!spell [spell]", hvor [spell] er navnet på den spell du søger efter. +Søg efter en spell i D&D med `!spell [spell]`, hvor [spell] er navnet på den spell du søger efter. Hvis Gwendolyn ikke kan finde den, er det ofte fordi du har skrevet navnet forkert. \ No newline at end of file diff --git a/resources/help/help-swchar.txt b/resources/help/help-swchar.txt index a235c6f..70fc0eb 100644 --- a/resources/help/help-swchar.txt +++ b/resources/help/help-swchar.txt @@ -1 +1 @@ - Du kan bruge kommandoer som "!swchar name Jared" eller "!swchar skills astrogation 3" til at ændre din karakters info. Kommandoen "!swchar" vil give dig et character sheet for din karakter. \ No newline at end of file + Du kan bruge kommandoer som `!swchar name Jared` eller `!swchar skills astrogation 3` til at ændre din karakters info. Kommandoen `!swchar` vil give dig et character sheet for din karakter. \ No newline at end of file diff --git a/resources/help/help-trivia.txt b/resources/help/help-trivia.txt index 3ce57c0..305b0ba 100644 --- a/resources/help/help-trivia.txt +++ b/resources/help/help-trivia.txt @@ -1,4 +1,4 @@ -Lader dig spille et spil trivia. "!trivia" starter spillet. +Lader dig spille et spil trivia. `!trivia` starter spillet. Hvert spil trivia varer i 1 minut, og der kan kun være et enkelt spil i hver kanal ad gangen. -"!trivia [svar]" lader dig svare på det nuværende spørgsmål, hvor [svar] er a, b, c eller d. +`!trivia [svar]` lader dig svare på det nuværende spørgsmål, hvor [svar] er a, b, c eller d. Hvis du svarer rigtigt får du 1 GwendoBuck. \ No newline at end of file diff --git a/resources/help/help.txt b/resources/help/help.txt index 0545095..1010e01 100644 --- a/resources/help/help.txt +++ b/resources/help/help.txt @@ -1,35 +1,35 @@ -**!hello** - En venlig hilsen. +`!hello` - En venlig hilsen. -**!roll** - Rul terninger i xdy format. +`!roll` - Rul terninger i xdy format. -**!spell** - Slå en besværgelse op. +`!spell` - Slå en besværgelse op. -**!monster** - Slå et monster op. +`!monster` - Slå et monster op. -**!map** - Få et billede af Senkulpa kortet. +`!map` - Få et billede af Senkulpa kortet. -**!image** - Finder et tilfældigt billede fra internettet. +`!image` - Finder et tilfældigt billede fra internettet. -**!movie** - Giver titlen på en tilfældig film fra Bedre Netflix +`!movie` - Giver titlen på en tilfældig film fra Bedre Netflix -**!name** - Genererer et tilfældigt navn. +`!name` - Genererer et tilfældigt navn. -**!tavern** - Genererer en tilfældig tavern. +`!tavern` - Genererer en tilfældig tavern. -**!give** - Lader dig give GwendoBucks til andre. +`!give` - Lader dig give GwendoBucks til andre. -**!swchar** - Lader dig lave en Star Wars karakter. +`!swchar` - Lader dig lave en Star Wars karakter. -**!swroll** - Lader dig rulle Star Wars terninger. +`!swroll` - Lader dig rulle Star Wars terninger. -**!balance** - Viser dig hvor mange GwendoBucks du har. +`!balance` - Viser dig hvor mange GwendoBucks du har. -**!blackjack** - Lader dig spille et spil blackjack. +`!blackjack` - Lader dig spille et spil blackjack. -**!trivia** - Lader dig spille et spil trivia, hvor du kan tjene GwendoBucks. +`!trivia` - Lader dig spille et spil trivia, hvor du kan tjene GwendoBucks. -**!fourinarow** - Lader dig spille et spil fire på stribe. +`!fourinarow` - Lader dig spille et spil fire på stribe. -**!hex** - Lader dig spille et spil Hex. +`!hex` - Lader dig spille et spil Hex. Du kan få ekstra information om kommandoerne med "!help [kommando]". From 65378fd6c4f28daba4e44f06621f9dae2f3b0eb4 Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Wed, 5 Aug 2020 22:39:31 +0200 Subject: [PATCH 11/26] :sparkles: Uses channel ID istead of name --- Gwendolyn.py | 150 ++++++++++++++++++++++----------------------- funcs/miscFuncs.py | 8 +-- gameLoops.py | 98 ++++++++++++++--------------- 3 files changed, 128 insertions(+), 128 deletions(-) diff --git a/Gwendolyn.py b/Gwendolyn.py index 03e7b37..cd26e35 100644 --- a/Gwendolyn.py +++ b/Gwendolyn.py @@ -34,26 +34,26 @@ async def parseCommands(message,content): em = discord.Embed(title = "Help", description = text,colour = 0x59f442) await message.channel.send(embed = em) except: - logThis("Couldn't find help.txt (error code 101)",str(message.channel)) + logThis("Couldn't find help.txt (error code 101)",str(message.channel.id)) await message.channel.send("Couldn't find help.txt (error code 101)") else: command = content.replace(" ","-") - logThis("Looking for "+command+".txt",str(message.channel)) + logThis("Looking for "+command+".txt",str(message.channel.id)) try: with codecs.open("resources/help/"+command+".txt",encoding="utf-8") as f: text = f.read() em = discord.Embed(title = command.replace("help-","").capitalize(), description = text,colour = 0x59f442) await message.channel.send(embed = em) except: - logThis("Couldn't find help for that command (error code 102)",str(message.channel)) + logThis("Couldn't find help for that command (error code 102)",str(message.channel.id)) await message.channel.send("Couldn't find help for that command (error code 102)") except: - logThis("Something fucked up (error code 100)",str(message.channel)) + logThis("Something fucked up (error code 100)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 100)") # Logs whatever you write in the message elif content.startswith("log "): - logThis(content.replace("log ",""),str(message.channel)) + logThis(content.replace("log ",""),str(message.channel.id)) # Stops the bot elif content.startswith("stop"): @@ -65,10 +65,10 @@ async def parseCommands(message,content): await client.logout() else: - logThis(message.author.display_name+" tried to run stop me! (error code 201)",str(message.channel)) + logThis(message.author.display_name+" tried to run stop me! (error code 201)",str(message.channel.id)) await message.channel.send("I don't think I will, "+message.author.display_name+" (error code 201)") except: - logThis("Something fucked up (error code 200)",str(message.channel)) + logThis("Something fucked up (error code 200)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 200)") # Does a hello with the helloFunc function from funcs/gwendolynpy @@ -76,7 +76,7 @@ async def parseCommands(message,content): try: await message.channel.send(helloFunc(message.author.display_name)) except: - logThis("Something fucked up (error code 310)",str(message.channel)) + logThis("Something fucked up (error code 310)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 310)") # Rolls dice with the roll_dice function from funcs/roll/dice.py @@ -87,7 +87,7 @@ async def parseCommands(message,content): else: await message.channel.send(roll_dice(message.author.display_name, content.replace("roll",""))) except: - logThis("Something fucked up (error code 400)",str(message.channel)) + logThis("Something fucked up (error code 400)",str(message.channel.id)) await message.channel.send("Not a valid command (error code 400)") # Looks up a spell with the spellFunc function from funcs/lookup/lookuppy @@ -100,7 +100,7 @@ async def parseCommands(message,content): else: await message.channel.send(spell) except: - logThis("Something fucked up (error code 500)",str(message.channel)) + logThis("Something fucked up (error code 500)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 500)") # Looks up a monster with the monsterFuncs() from funcs/lookup/lookuppy @@ -149,7 +149,7 @@ async def parseCommands(message,content): em5_2 = discord.Embed(title = "", description = text5[2048:], colour=0xDEADBF) await message.channel.send(embed = em5_2) except: - logThis("Something fucked up (error code 600)",str(message.channel)) + logThis("Something fucked up (error code 600)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 600)") # Sends an image of the Senkulpa map @@ -157,7 +157,7 @@ async def parseCommands(message,content): try: await message.channel.send("https://i.imgur.com/diMXXJs.jpg") except: - logThis("Something fucked up (error code 320)",str(message.channel)) + logThis("Something fucked up (error code 320)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 320)") # Finds a random image on the internet with the imageFuncs function from @@ -167,7 +167,7 @@ async def parseCommands(message,content): randomImage = imageFunc() await message.channel.send(randomImage) except: - logThis("Something fucked up (error code 700)",str(message.channel)) + logThis("Something fucked up (error code 700)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 700)") # Sends information about a random movie with the movieFunc function from @@ -187,7 +187,7 @@ async def parseCommands(message,content): except: logThis("Error embedding (error code 805)") except: - logThis("Something fucked up (error code 800)",str(message.channel)) + logThis("Something fucked up (error code 800)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 800)") # Generates a random name with the nameGen function from funcs/other/generators.py @@ -195,7 +195,7 @@ async def parseCommands(message,content): try: await message.channel.send(nameGen()) except: - logThis("Something fucked up (error code 330)",str(message.channel)) + logThis("Something fucked up (error code 330)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 330)") # Generates a random tavern name with the tavernGen function from funcs/other/generators.py @@ -203,7 +203,7 @@ async def parseCommands(message,content): try: await message.channel.send(tavernGen()) except: - logThis("Something fucked up (error code 340)",str(message.channel)) + logThis("Something fucked up (error code 340)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 340)") # Changes the "Playing this game" thing in Discord @@ -213,7 +213,7 @@ async def parseCommands(message,content): game = discord.Game(gamePlaying) await client.change_presence(activity=game) except: - logThis("Something fucked up (error code 350)",str(message.channel)) + logThis("Something fucked up (error code 350)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 350)") # Rolls star wars dice with the parseRoll function from funcs/swfuncs/swroll.py @@ -225,7 +225,7 @@ async def parseCommands(message,content): for messageItem in messageList: await message.channel.send(messageItem) except: - logThis("Something fucked up (error code 910)",str(message.channel)) + logThis("Something fucked up (error code 910)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 910)") # Deals with Destiny Points and stuff @@ -237,7 +237,7 @@ async def parseCommands(message,content): for messageItem in messageList: await message.channel.send(messageItem) except: - logThis("Something fucked up (error code 920)",str(message.channel)) + logThis("Something fucked up (error code 920)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 920)") # Rolls for critical injuries @@ -251,14 +251,14 @@ async def parseCommands(message,content): try: newMessage = critRoll(int(command)) except: - logThis("They didn't include a number (error code 931)",str(message.channel)) + logThis("They didn't include a number (error code 931)",str(message.channel.id)) newMessage = "Try using a number, stupid (error code 931)" messageList = newMessage.split("\n") for messageItem in messageList: await message.channel.send(messageItem) except: - logThis("Something fucked up (error code 930)",str(message.channel)) + logThis("Something fucked up (error code 930)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 930)") # Accesses and changes character sheet data with the parseChar function @@ -273,7 +273,7 @@ async def parseCommands(message,content): else: await message.channel.send(desc) except: - logThis("Something fucked up (error code 940)",str(message.channel)) + logThis("Something fucked up (error code 940)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 940)") @@ -284,7 +284,7 @@ async def parseCommands(message,content): command = string.capwords(content.replace("wiki ","")) title, content, thumbnail = findWikiPage(command) if title != "": - logThis("Sending the embedded message",str(message.channel)) + logThis("Sending the embedded message",str(message.channel.id)) content += "\n[Læs mere](https://senkulpa.fandom.com/da/wiki/"+title.replace(" ","_")+")" embed = discord.Embed(title = title, description = content, colour=0xDEADBF) if thumbnail != "": @@ -294,7 +294,7 @@ async def parseCommands(message,content): else: await message.channel.send(content) except: - logThis("Something fucked up (error code 1000)",str(message.channel)) + logThis("Something fucked up (error code 1000)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 1000)") @@ -302,7 +302,7 @@ async def parseCommands(message,content): elif content.startswith("trivia"): try: if content == "trivia" or content == "trivia ": - question, answers, correctAnswer = triviaStart(str(message.channel)) + question, answers, correctAnswer = triviaStart(str(message.channel.id)) if answers != "": results = "**"+question+"**\n" for answer in range(len(answers)): @@ -312,27 +312,27 @@ async def parseCommands(message,content): await asyncio.sleep(60) - triviaCountPoints(str(message.channel)) + triviaCountPoints(str(message.channel.id)) - deleteGame("trivia questions",str(message.channel)) + deleteGame("trivia questions",str(message.channel.id)) - logThis("Time's up for the trivia question",str(message.channel)) + logThis("Time's up for the trivia question",str(message.channel.id)) await message.channel.send("Time's up The answer was \""+chr(correctAnswer)+") "+answers[correctAnswer-97]+"\". Anyone who answered that has gotten 1 GwendoBuck") else: await message.channel.send(question) elif content.startswith("trivia "): command = content.replace("trivia ","") - response = triviaAnswer("#"+str(message.author.id),str(message.channel),command) + response = triviaAnswer("#"+str(message.author.id),str(message.channel.id),command) if response.startswith("Locked in "): await message.add_reaction("👍") else: await message.channel.send(response) else: - logThis("I didn't understand that (error code 1101)",str(message.channel)) + logThis("I didn't understand that (error code 1101)",str(message.channel.id)) await message.channel.send("I didn't understand that (error code 1101)") except: - logThis("Something fucked up (error code 1100)",str(message.channel)) + logThis("Something fucked up (error code 1100)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 1100)") @@ -346,7 +346,7 @@ async def parseCommands(message,content): new_message = message.author.display_name + " has " + str(response) + " GwendoBucks" await message.channel.send(new_message) except: - logThis("Something fucked up (error code 1210)",str(message.channel)) + logThis("Something fucked up (error code 1210)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 1210)") # Gives money to other player @@ -357,16 +357,16 @@ async def parseCommands(message,content): try: amount = int(commands[2]) except: - logThis("Conversion error (error code 1221)",str(message.channel)) + logThis("Conversion error (error code 1221)",str(message.channel.id)) await message.channel.send("I didn't quite understand that (error code 1221)") else: response = giveMoney("#"+str(message.author.id),commands[1],amount) await message.channel.send(response) else: - logThis("I didn't understand that (error code 1222)",str(message.channel)) + logThis("I didn't understand that (error code 1222)",str(message.channel.id)) await message.channel.send("I didn't understand that (error code 1222)") except: - logThis("Something fucked up (error code 1220)",str(message.channel)) + logThis("Something fucked up (error code 1220)",str(message.channel.id)) await message.channel.send("Something fucked up (error code 1220)") # Runs a game of Blackjack @@ -375,25 +375,25 @@ async def parseCommands(message,content): # Starts the game if content == "blackjack" or content == "blackjack ": cardsLeft = 0 - if os.path.exists("resources/games/blackjackCards/"+str(message.channel)+".txt"): - with open("resources/games/blackjackCards/"+str(message.channel)+".txt","r") as f: + if os.path.exists("resources/games/blackjackCards/"+str(message.channel.id)+".txt"): + with open("resources/games/blackjackCards/"+str(message.channel.id)+".txt","r") as f: for _ in f: cardsLeft += 1 # Shuffles if not enough cards if cardsLeft < blackjackMinCards: - blackjackShuffle(blackjackDecks,str(message.channel)) - logThis("Shuffling the blackjack deck...",str(message.channel)) + blackjackShuffle(blackjackDecks,str(message.channel.id)) + logThis("Shuffling the blackjack deck...",str(message.channel.id)) await message.channel.send("Shuffling the deck...") - new_message = blackjackStart(str(message.channel)) + new_message = blackjackStart(str(message.channel.id)) if new_message == "started": new_message = "Blackjack game started. Use \""+commandPrefix+"blackjack bet [amount]\" to enter the game within the next 30 seconds." await message.channel.send(new_message) - oldImage = await message.channel.send(file = discord.File("resources/games/blackjackTables/blackjackTable"+str(message.channel)+".png")) + oldImage = await message.channel.send(file = discord.File("resources/games/blackjackTables/blackjackTable"+str(message.channel.id)+".png")) - with open("resources/games/oldImages/blackjack"+str(message.channel), "w") as f: + with open("resources/games/oldImages/blackjack"+str(message.channel.id), "w") as f: f.write(str(oldImage.id)) await asyncio.sleep(30) @@ -402,17 +402,17 @@ async def parseCommands(message,content): with open("resources/games/games.json", "r") as f: data = json.load(f) - if len(data["blackjack games"][str(message.channel)]["user hands"]) == 0: + if len(data["blackjack games"][str(message.channel.id)]["user hands"]) == 0: gamedone = True await message.channel.send("No one entered the game. Ending the game.") - gameID = data["blackjack games"][str(message.channel)]["id"] + gameID = data["blackjack games"][str(message.channel.id)]["id"] # Loop of game rounds if gamedone == False: - logThis("!blackjack calling blackjackLoop()",str(message.channel)) + logThis("!blackjack calling blackjackLoop()",str(message.channel.id)) await blackjackLoop(message.channel,1,gameID) else: - new_message = blackjackFinish(str(message.channel)) + new_message = blackjackFinish(str(message.channel.id)) await message.channel.send(new_message) else: await message.channel.send(new_message) @@ -423,34 +423,34 @@ async def parseCommands(message,content): try: amount = int(commands[2]) except: - logThis("I didn't understand that",str(message.channel)) + logThis("I didn't understand that",str(message.channel.id)) response = "I didn't understand that" else: - response = blackjackPlayerDrawHand(str(message.channel),"#"+str(message.author.id),amount) + response = blackjackPlayerDrawHand(str(message.channel.id),"#"+str(message.author.id),amount) await message.channel.send(response) # Hitting elif content.startswith("blackjack hit"): if content == "blackjack hit" or content == "blackjack hit ": - response = blackjackHit(str(message.channel),"#"+str(message.author.id)) + response = blackjackHit(str(message.channel.id),"#"+str(message.author.id)) else: commands = content.split(" ") try: handNumber = int(commands[2]) except: handNumber = 0 - response = blackjackHit(str(message.channel),"#"+str(message.author.id),handNumber) + response = blackjackHit(str(message.channel.id),"#"+str(message.author.id),handNumber) if response.startswith("accept"): await message.add_reaction("👍") try: if response[6] == "T": with open("resources/games/games.json", "r") as f: - gameID = json.load(f)["blackjack games"][str(message.channel)]["id"] - logThis("Hit calling blackjackLoop()",str(message.channel)) + gameID = json.load(f)["blackjack games"][str(message.channel.id)]["id"] + logThis("Hit calling blackjackLoop()",str(message.channel.id)) await blackjackLoop(message.channel,int(response[7:])+1,gameID) except: - logThis("Something fucked up (error code 1320)",str(message.channel)) + logThis("Something fucked up (error code 1320)",str(message.channel.id)) else: await message.channel.send(response) @@ -458,25 +458,25 @@ async def parseCommands(message,content): # Standing elif content.startswith("blackjack stand"): if content == "blackjack hit" or content == "blackjack hit ": - response = blackjackStand(str(message.channel),"#"+str(message.author.id)) + response = blackjackStand(str(message.channel.id),"#"+str(message.author.id)) else: commands = content.split(" ") try: handNumber = int(commands[2]) except: handNumber = 0 - response = blackjackStand(str(message.channel),"#"+str(message.author.id),handNumber) + response = blackjackStand(str(message.channel.id),"#"+str(message.author.id),handNumber) if response.startswith("accept"): await message.add_reaction("👍") try: if response[6] == "T": with open("resources/games/games.json", "r") as f: - gameID = json.load(f)["blackjack games"][str(message.channel)]["id"] - logThis("Stand calling blackjackLoop()",str(message.channel)) + gameID = json.load(f)["blackjack games"][str(message.channel.id)]["id"] + logThis("Stand calling blackjackLoop()",str(message.channel.id)) await blackjackLoop(message.channel,int(response[7:])+1,gameID) except: - logThis("Something fucked up (error code 1320)",str(message.channel)) + logThis("Something fucked up (error code 1320)",str(message.channel.id)) else: await message.channel.send(response) @@ -487,18 +487,18 @@ async def parseCommands(message,content): handNumber = int(commands[2]) except: handNumber = 0 - response, roundDone = blackjackDouble(str(message.channel),"#"+str(message.author.id),handNumber) + response, roundDone = blackjackDouble(str(message.channel.id),"#"+str(message.author.id),handNumber) await message.channel.send(response) try: if roundDone[0] == "T": with open("resources/games/games.json", "r") as f: - gameID = json.load(f)["blackjack games"][str(message.channel)]["id"] - logThis("Double calling blackjackLoop()",str(message.channel)) + gameID = json.load(f)["blackjack games"][str(message.channel.id)]["id"] + logThis("Double calling blackjackLoop()",str(message.channel.id)) await blackjackLoop(message.channel,int(roundDone[1:])+1,gameID) except: - logThis("Something fucked up (error code 1320)",str(message.channel)) + logThis("Something fucked up (error code 1320)",str(message.channel.id)) # Splitting hand elif content.startswith("blackjack split"): @@ -507,23 +507,23 @@ async def parseCommands(message,content): handNumber = int(commands[2]) except: handNumber = 0 - response, roundDone = blackjackSplit(str(message.channel),"#"+str(message.author.id),handNumber) + response, roundDone = blackjackSplit(str(message.channel.id),"#"+str(message.author.id),handNumber) await message.channel.send(response) try: if roundDone[0] == "T": with open("resources/games/games.json", "r") as f: - gameID = json.load(f)["blackjack games"][str(message.channel)]["id"] - logThis("Split calling blackjackLoop()",str(message.channel)) + gameID = json.load(f)["blackjack games"][str(message.channel.id)]["id"] + logThis("Split calling blackjackLoop()",str(message.channel.id)) await blackjackLoop(message.channel,int(roundDone[1:])+1,gameID) except: logThis("Something fucked up (error code 1320)") # Returning current hi-lo value elif content.startswith("blackjack hilo") and "#"+str(message.author.id) == "#266269899859427329": - if os.path.exists("resources/games/blackjackCards/"+str(message.channel)+".txt"): - with open("resources/games/hilo/"+str(message.channel)+".txt", "r") as f: + if os.path.exists("resources/games/blackjackCards/"+str(message.channel.id)+".txt"): + with open("resources/games/hilo/"+str(message.channel.id)+".txt", "r") as f: data = f.read() else: data = "0" @@ -531,16 +531,16 @@ async def parseCommands(message,content): # Shuffles the blackjack deck elif content.startswith("blackjack shuffle"): - blackjackShuffle(blackjackDecks,str(message.channel)) - logThis("Shuffling the blackjack deck...",str(message.channel)) + blackjackShuffle(blackjackDecks,str(message.channel.id)) + logThis("Shuffling the blackjack deck...",str(message.channel.id)) await message.channel.send("Shuffling the deck...") # Tells you the amount of cards left elif content.startswith("blackjack cards"): cardsLeft = 0 - if os.path.exists("resources/games/blackjackCards/"+str(message.channel)+".txt"): - with open("resources/games/blackjackCards/"+str(message.channel)+".txt","r") as f: + if os.path.exists("resources/games/blackjackCards/"+str(message.channel.id)+".txt"): + with open("resources/games/blackjackCards/"+str(message.channel.id)+".txt","r") as f: for _ in f: cardsLeft += 1 @@ -579,7 +579,7 @@ async def parseCommands(message,content): # Not a command else: - logThis("That's not a command (error code 001)",str(message.channel)) + logThis("That's not a command (error code 001)",str(message.channel.id)) await message.channel.send("That's not a command (error code 001)") # Makes files if they don't exist yet @@ -604,7 +604,7 @@ async def on_message(message): try: content = message.content if content.startswith(commandPrefix): - logThis(message.author.display_name+" ("+"#"+str(message.author.id)+") ran \""+content+"\"",str(message.channel)) + logThis(message.author.display_name+" ("+"#"+str(message.author.id)+") ran \""+content+"\"",str(message.channel.id)) addToDict("#"+str(message.author.id),message.author.display_name) await parseCommands(message,content.lower()[1:]) except: @@ -613,7 +613,7 @@ async def on_message(message): # Is a bit sassy sometimes if ("gwendolyn" in message.content.lower() or message.content.startswith(commandPrefix)) and any(x in message.content.lower() for x in meanWords) and "ikke" not in message.content.lower() and "not" not in message.content.lower(): - logThis(message.author.display_name+" was a bit mean",str(message.channel)) + logThis(message.author.display_name+" was a bit mean",str(message.channel.id)) emoji = random.choice(["😠", "🖕", "👎"]) await message.add_reaction(emoji) @@ -622,7 +622,7 @@ async def on_reaction_add(reaction,user): if user.bot == False: message = reaction.message channel = message.channel - logThis(user.display_name+" reacted to a message",str(channel)) + logThis(user.display_name+" reacted to a message",str(channel.id)) try: fourInARowTheirTurn, piece = fiarReactionTest(channel,message,"#"+str(user.id)) except: diff --git a/funcs/miscFuncs.py b/funcs/miscFuncs.py index 0546f0a..cf528c8 100644 --- a/funcs/miscFuncs.py +++ b/funcs/miscFuncs.py @@ -209,13 +209,13 @@ def fiarReactionTest(channel,message,user): with open("resources/games/games.json", "r") as f: data = json.load(f) - with open("resources/games/oldImages/fourInARow"+str(channel), "r") as f: + with open("resources/games/oldImages/fourInARow"+str(channel.id), "r") as f: oldImage = int(f.read()) if message.id == oldImage: logThis("They reacted to the fourinarow game") - turn = data["4 in a row games"][str(channel)]["turn"] - if user == data["4 in a row games"][str(channel)]["players"][turn]: + turn = data["4 in a row games"][str(channel.id)]["turn"] + if user == data["4 in a row games"][str(channel.id)]["players"][turn]: return True, turn+1 else: logThis("It wasn't their turn") @@ -224,7 +224,7 @@ def fiarReactionTest(channel,message,user): return False, 0 def monopolyReactionTest(channel,message): - with open("resources/games/oldImages/monopoly"+str(channel), "r") as f: + with open("resources/games/oldImages/monopoly"+str(channel.id), "r") as f: oldImage = int(f.read()) if message.id == oldImage: diff --git a/gameLoops.py b/gameLoops.py index 058f033..893e737 100644 --- a/gameLoops.py +++ b/gameLoops.py @@ -20,34 +20,34 @@ async def deleteMessage(imageLocation,channel): # Runs Hex async def runHex(channel,command,user): try: - response, showImage, deleteImage, gameDone, gwendoTurn = parseHex(command,str(channel),user) + response, showImage, deleteImage, gameDone, gwendoTurn = parseHex(command,str(channel.id),user) except: logThis("Error parsing command (error code 1510)") await channel.send(response) - logThis(response,str(channel)) + logThis(response,str(channel.id)) if showImage: if deleteImage: try: - oldImage = await deleteMessage("hex"+str(channel),channel) + oldImage = await deleteMessage("hex"+str(channel.id),channel) except: logThis("Error deleting old image (error code 1501)") - oldImage = await channel.send(file = discord.File("resources/games/hexBoards/board"+str(channel)+".png")) + oldImage = await channel.send(file = discord.File("resources/games/hexBoards/board"+str(channel.id)+".png")) if not gameDone: if gwendoTurn: try: - response, showImage, deleteImage, gameDone, gwendoTurn = hexAI(str(channel)) + response, showImage, deleteImage, gameDone, gwendoTurn = hexAI(str(channel.id)) except: logThis("AI error (error code 1520)") await channel.send(response) - logThis(response,str(channel)) + logThis(response,str(channel.id)) if showImage: if deleteImage: await oldImage.delete() - oldImage = await channel.send(file = discord.File("resources/games/hexBoards/board"+str(channel)+".png")) + oldImage = await channel.send(file = discord.File("resources/games/hexBoards/board"+str(channel.id)+".png")) else: - with open("resources/games/oldImages/hex"+str(channel), "w") as f: + with open("resources/games/oldImages/hex"+str(channel.id), "w") as f: f.write(str(oldImage.id)) if gameDone: @@ -55,52 +55,52 @@ async def runHex(channel,command,user): data = json.load(f) try: - with open("resources/games/oldImages/hex"+str(channel), "r") as f: + with open("resources/games/oldImages/hex"+str(channel.id), "r") as f: oldImage = await channel.fetch_message(int(f.read())) await oldImage.delete() except: logThis("The old image was already deleted") - winner = data["hex games"][str(channel)]["winner"] + winner = data["hex games"][str(channel.id)]["winner"] if winner != 0: - addMoney(data["hex games"][str(channel)]["players"][winner-1].lower(),20) + addMoney(data["hex games"][str(channel.id)]["players"][winner-1].lower(),20) with open("resources/games/games.json", "r") as f: data = json.load(f) #why is this here? - deleteGame("hex games",str(channel)) + deleteGame("hex games",str(channel.id)) # Runs Four in a Row async def fiar(channel,command,user): try: - response, showImage, deleteImage, gameDone, gwendoTurn = parseFourInARow(command,str(channel),user) + response, showImage, deleteImage, gameDone, gwendoTurn = parseFourInARow(command,str(channel.id),user) except: logThis("Error parsing command (error code 1410)") await channel.send(response) - logThis(response,str(channel)) + logThis(response,str(channel.id)) if showImage: if deleteImage: try: - oldImage = await deleteMessage("fourInARow"+str(channel),channel) + oldImage = await deleteMessage("fourInARow"+str(channel.id),channel) except: logThis("Error deleting message (error code 1401)") - oldImage = await channel.send(file = discord.File("resources/games/4InARowBoards/board"+str(channel)+".png")) + oldImage = await channel.send(file = discord.File("resources/games/4InARowBoards/board"+str(channel.id)+".png")) if gameDone == False: if gwendoTurn: try: - response, showImage, deleteImage, gameDone, gwendoTurn = fourInARowAI(str(channel)) + response, showImage, deleteImage, gameDone, gwendoTurn = fourInARowAI(str(channel.id)) except: logThis("AI error (error code 1420)") await channel.send(response) - logThis(response,str(channel)) + logThis(response,str(channel.id)) if showImage: if deleteImage: await oldImage.delete() - oldImage = await channel.send(file = discord.File("resources/games/4InARowBoards/board"+str(channel)+".png")) + oldImage = await channel.send(file = discord.File("resources/games/4InARowBoards/board"+str(channel.id)+".png")) if gameDone == False: - with open("resources/games/oldImages/fourInARow"+str(channel), "w") as f: + with open("resources/games/oldImages/fourInARow"+str(channel.id), "w") as f: f.write(str(oldImage.id)) try: reactions = ["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣","6️⃣","7️⃣"] @@ -111,7 +111,7 @@ async def fiar(channel,command,user): logThis("Image deleted before I could react to all of them") else: - with open("resources/games/oldImages/fourInARow"+str(channel), "w") as f: + with open("resources/games/oldImages/fourInARow"+str(channel.id), "w") as f: f.write(str(oldImage.id)) try: reactions = ["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣","6️⃣","7️⃣"] @@ -125,39 +125,39 @@ async def fiar(channel,command,user): data = json.load(f) try: - with open("resources/games/oldImages/fourInARow"+str(channel), "r") as f: + with open("resources/games/oldImages/fourInARow"+str(channel.id), "r") as f: oldImage = await channel.fetch_message(int(f.read())) await oldImage.delete() except: logThis("The old image was already deleted") - winner = data["4 in a row games"][str(channel)]["winner"] - difficulty = int(data["4 in a row games"][str(channel)]["difficulty"]) + winner = data["4 in a row games"][str(channel.id)]["winner"] + difficulty = int(data["4 in a row games"][str(channel.id)]["difficulty"]) reward = difficulty**2 + 5 if winner != 0: - if data["4 in a row games"][str(channel)]["players"][winner-1].lower() != "gwendolyn": - addMoney(data["4 in a row games"][str(channel)]["players"][winner-1].lower(),reward) + if data["4 in a row games"][str(channel.id)]["players"][winner-1].lower() != "gwendolyn": + addMoney(data["4 in a row games"][str(channel.id)]["players"][winner-1].lower(),reward) with open("resources/games/games.json", "r") as f: data = json.load(f) #why is this here? - deleteGame("4 in a row games",str(channel)) + deleteGame("4 in a row games",str(channel.id)) # Loop of blackjack game rounds async def blackjackLoop(channel,gameRound,gameID): - logThis("Loop "+str(gameRound),str(channel)) + logThis("Loop "+str(gameRound),str(channel.id)) - with open("resources/games/oldImages/blackjack"+str(channel), "r") as f: + with open("resources/games/oldImages/blackjack"+str(channel.id), "r") as f: oldImage = await channel.fetch_message(int(f.read())) - new_message, allStanding, gamedone = blackjackContinue(str(channel)) + new_message, allStanding, gamedone = blackjackContinue(str(channel.id)) if new_message != "": - logThis(new_message,str(channel)) + logThis(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)+".png")) - with open("resources/games/oldImages/blackjack"+str(channel), "w") as f: + 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: @@ -171,41 +171,41 @@ async def blackjackLoop(channel,gameRound,gameID): with open("resources/games/games.json", "r") as f: data = json.load(f) - if str(channel) in data["blackjack games"]: - realRound = data["blackjack games"][str(channel)]["round"] - realGameID = data["blackjack games"][str(channel)]["id"] + if str(channel.id) in data["blackjack games"]: + realRound = data["blackjack games"][str(channel.id)]["round"] + realGameID = data["blackjack games"][str(channel.id)]["id"] if gameRound == realRound and realGameID == gameID: if gamedone == False: - logThis("Loop "+str(gameRound)+" calling blackjackLoop()",str(channel)) + logThis("Loop "+str(gameRound)+" calling blackjackLoop()",str(channel.id)) await blackjackLoop(channel,gameRound+1,gameID) else: try: - new_message = blackjackFinish(str(channel)) + new_message = blackjackFinish(str(channel.id)) except: logThis("Something fucked up (error code 1310)") await channel.send(new_message) else: - logThis("Ending loop on round "+str(gameRound),str(channel)) + logThis("Ending loop on round "+str(gameRound),str(channel.id)) else: - logThis("Ending loop on round "+str(gameRound),str(channel)) + logThis("Ending loop on round "+str(gameRound),str(channel.id)) async def runMonopoly(channel, command, user): try: - response, showImage, deleteImage, gameStarted, gameContinue = parseMonopoly(command,str(channel),user) + response, showImage, deleteImage, gameStarted, gameContinue = parseMonopoly(command,str(channel.id),user) except: logThis("Error parsing command (error code 1610)") if response != "": await channel.send(response) - logThis(response,str(channel)) + logThis(response,str(channel.id)) if showImage: if deleteImage: try: - oldImage = await deleteMessage("monopoly"+str(channel),channel) + oldImage = await deleteMessage("monopoly"+str(channel.id),channel) except: logThis("Error deleting message (error code 1601)") - oldImage = await channel.send(file = discord.File("resources/games/monopolyBoards/monopolyBoard"+str(channel)+".png")) - with open("resources/games/oldImages/monopoly"+str(channel), "w") as f: + oldImage = await channel.send(file = discord.File("resources/games/monopolyBoards/monopolyBoard"+str(channel.id)+".png")) + with open("resources/games/oldImages/monopoly"+str(channel.id), "w") as f: f.write(str(oldImage.id)) if gameContinue: @@ -213,17 +213,17 @@ async def runMonopoly(channel, command, user): await asyncio.sleep(60) else: await asyncio.sleep(5) - response, showImage, deleteImage, gameDone = monopolyContinue(str(channel)) + response, showImage, deleteImage, gameDone = monopolyContinue(str(channel.id)) em = discord.Embed(description=response,colour = 0x59f442) await channel.send(embed=em) if showImage: if deleteImage: try: - oldImage = await deleteMessage("monopoly"+str(channel),channel) + oldImage = await deleteMessage("monopoly"+str(channel.id),channel) except: logThis("Error deleting message (error code 1601)") - oldImage = await channel.send(file = discord.File("resources/games/monopolyBoards/monopolyBoard"+str(channel)+".png")) - with open("resources/games/oldImages/monopoly"+str(channel), "w") as f: + oldImage = await channel.send(file = discord.File("resources/games/monopolyBoards/monopolyBoard"+str(channel.id)+".png")) + with open("resources/games/oldImages/monopoly"+str(channel.id), "w") as f: f.write(str(oldImage.id)) if gameDone == False: try: From 2d5b4e61c4ce10c32b230cdb3e4cc826d9ad79e1 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 09:43:10 +0200 Subject: [PATCH 12/26] :bug: --- Gwendolyn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gwendolyn.py b/Gwendolyn.py index cd26e35..b80c6fb 100644 --- a/Gwendolyn.py +++ b/Gwendolyn.py @@ -10,7 +10,7 @@ import random #import math import os -from funcs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, emojiToCommand, fiarReactionTest, deleteGame, stopServer, checkBalance, giveMoney, triviaCountPoints, triviaStart, triviaAnswer, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackContinue, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit, parseFourInARow, fourInARowAI, spellFunc, monsterFunc, nameGen, tavernGen, movieFunc, roll_dice, parseChar, parseRoll, critRoll, parseDestiny, parseHex, addToDict, monopolyReactionTest +from funcs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, emojiToCommand, fiarReactionTest, deleteGame, stopServer, checkBalance, giveMoney, triviaCountPoints, triviaStart, triviaAnswer, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit, parseFourInARow, fourInARowAI, spellFunc, monsterFunc, nameGen, tavernGen, movieFunc, roll_dice, parseChar, parseRoll, critRoll, parseDestiny, parseHex, addToDict, monopolyReactionTest from gameLoops import fiar, blackjackLoop, runHex, runMonopoly From 5151e1faf74199279e8ad6d1e1499c6576a009ce Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 13:01:00 +0200 Subject: [PATCH 13/26] :gear: Cogs --- Gwendolyn.py | 588 +------------------------------------------ bot.py | 52 ++++ cogs/GamesCog.py | 269 ++++++++++++++++++++ cogs/LookupCog.py | 70 ++++++ cogs/MiscCog.py | 123 +++++++++ cogs/ReactionCog.py | 31 +++ cogs/SwCog.py | 52 ++++ funcs/games/money.py | 2 +- funcs/roll/dice.py | 2 +- 9 files changed, 601 insertions(+), 588 deletions(-) create mode 100644 bot.py create mode 100644 cogs/GamesCog.py create mode 100644 cogs/LookupCog.py create mode 100644 cogs/MiscCog.py create mode 100644 cogs/ReactionCog.py create mode 100644 cogs/SwCog.py diff --git a/Gwendolyn.py b/Gwendolyn.py index b80c6fb..74357b5 100644 --- a/Gwendolyn.py +++ b/Gwendolyn.py @@ -10,548 +10,17 @@ import random #import math import os +from discord.ext import commands + from funcs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, emojiToCommand, fiarReactionTest, deleteGame, stopServer, checkBalance, giveMoney, triviaCountPoints, triviaStart, triviaAnswer, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit, parseFourInARow, fourInARowAI, spellFunc, monsterFunc, nameGen, tavernGen, movieFunc, roll_dice, parseChar, parseRoll, critRoll, parseDestiny, parseHex, addToDict, monopolyReactionTest from gameLoops import fiar, blackjackLoop, runHex, runMonopoly -commandPrefix = "!" - # Blackjack shuffle variables blackjackMinCards = 50 blackjackDecks = 4 -# Variable for reacting to messages -meanWords = ["stupid", "bitch", "fuck", "dumb", "idiot"] - async def parseCommands(message,content): - # Sends the contents of a help file, as specified by the message. - if content.startswith("help"): - try: - if content == "help" or content == "help ": - try: - with codecs.open("resources/help/help.txt",encoding="utf-8") as f: - text = f.read() - em = discord.Embed(title = "Help", description = text,colour = 0x59f442) - await message.channel.send(embed = em) - except: - logThis("Couldn't find help.txt (error code 101)",str(message.channel.id)) - await message.channel.send("Couldn't find help.txt (error code 101)") - else: - command = content.replace(" ","-") - logThis("Looking for "+command+".txt",str(message.channel.id)) - try: - with codecs.open("resources/help/"+command+".txt",encoding="utf-8") as f: - text = f.read() - em = discord.Embed(title = command.replace("help-","").capitalize(), description = text,colour = 0x59f442) - await message.channel.send(embed = em) - except: - logThis("Couldn't find help for that command (error code 102)",str(message.channel.id)) - await message.channel.send("Couldn't find help for that command (error code 102)") - except: - logThis("Something fucked up (error code 100)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 100)") - - # Logs whatever you write in the message - elif content.startswith("log "): - logThis(content.replace("log ",""),str(message.channel.id)) - - # Stops the bot - elif content.startswith("stop"): - try: - if "#"+str(message.author.id) in ["#266269899859427329", "#380732645602230272"]: - await message.channel.send("Logging out...") - - stopServer() - - await client.logout() - else: - logThis(message.author.display_name+" tried to run stop me! (error code 201)",str(message.channel.id)) - await message.channel.send("I don't think I will, "+message.author.display_name+" (error code 201)") - except: - logThis("Something fucked up (error code 200)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 200)") - - # Does a hello with the helloFunc function from funcs/gwendolynpy - elif content.startswith("hello"): - try: - await message.channel.send(helloFunc(message.author.display_name)) - except: - logThis("Something fucked up (error code 310)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 310)") - - # Rolls dice with the roll_dice function from funcs/roll/dice.py - elif content.startswith("roll"): - try: - if content == "roll" or content == "roll ": - await message.channel.send(roll_dice(message.author.display_name)) - else: - await message.channel.send(roll_dice(message.author.display_name, content.replace("roll",""))) - except: - logThis("Something fucked up (error code 400)",str(message.channel.id)) - await message.channel.send("Not a valid command (error code 400)") - - # Looks up a spell with the spellFunc function from funcs/lookup/lookuppy - elif content.startswith("spell "): - try: - spell = spellFunc(cap(content.replace("spell",""))) - if len(spell) > 2000: - await message.channel.send(spell[:2000]) - await message.channel.send(spell[2000:]) - else: - await message.channel.send(spell) - except: - logThis("Something fucked up (error code 500)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 500)") - - # Looks up a monster with the monsterFuncs() from funcs/lookup/lookuppy - elif content.startswith("monster "): - try: - title, text1, text2, text3, text4, text5 = monsterFunc(cap(content.replace("monster",""))) - em1 = discord.Embed(title = title, description = text1, colour=0xDEADBF) - - # Sends the received information. Seperates into seperate messages if - # there is too much text - await message.channel.send(embed = em1) - if text2 != "": - if len(text2) < 2048: - em2 = discord.Embed(title = "Special Abilities", description = text2, colour=0xDEADBF) - await message.channel.send(embed = em2) - else: - em2 = discord.Embed(title = "Special Abilities", description = text2[:2048], colour=0xDEADBF) - await message.channel.send(embed = em2) - em2_2 = discord.Embed(title = "", description = text2[2048:], colour=0xDEADBF) - await message.channel.send(embed = em2_2) - if text3 != "": - if len(text3) < 2048: - em3 = discord.Embed(title = "Actions", description = text3, colour=0xDEADBF) - await message.channel.send(embed = em3) - else: - em3 = discord.Embed(title = "Actions", description = text3[:2048], colour=0xDEADBF) - await message.channel.send(embed = em3) - em3_2 = discord.Embed(title = "", description = text3[2048:], colour=0xDEADBF) - await message.channel.send(embed = em3_2) - if text4 != "": - if len(text4) < 2048: - em4 = discord.Embed(title = "Reactions", description = text4, colour=0xDEADBF) - await message.channel.send(embed = em4) - else: - em4 = discord.Embed(title = "Reactions", description = text4[:2048], colour=0xDEADBF) - await message.channel.send(embed = em4) - em4_2 = discord.Embed(title = "", description = text4[2048:], colour=0xDEADBF) - await message.channel.send(embed = em4_2) - if text5 != "": - if len(text5) < 2048: - em5 = discord.Embed(title = "Legendary Actions", description = text5, colour=0xDEADBF) - await message.channel.send(embed = em5) - else: - em5 = discord.Embed(title = "Legendary Actions", description = text5[:2048], colour=0xDEADBF) - await message.channel.send(embed = em5) - em5_2 = discord.Embed(title = "", description = text5[2048:], colour=0xDEADBF) - await message.channel.send(embed = em5_2) - except: - logThis("Something fucked up (error code 600)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 600)") - - # Sends an image of the Senkulpa map - elif content.startswith("map"): - try: - await message.channel.send("https://i.imgur.com/diMXXJs.jpg") - except: - logThis("Something fucked up (error code 320)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 320)") - - # Finds a random image on the internet with the imageFuncs function from - # funcs/gwendolynpy - elif content.startswith("image"): - try: - randomImage = imageFunc() - await message.channel.send(randomImage) - except: - logThis("Something fucked up (error code 700)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 700)") - - # Sends information about a random movie with the movieFunc function from - # funcs/other/movie.py - elif content.startswith("movie"): - try: - async with message.channel.typing(): - title, plot, cover, cast = movieFunc() - if title == "error": - await message.channel.send("An error occurred. Try again (error code "+plot+")") - else: - try: - embed = discord.Embed(title=title, description=plot, color=0x24ec19) - embed.set_thumbnail(url=cover) - embed.add_field(name="Cast", value=cast,inline = True) - await message.channel.send(embed = embed) - except: - logThis("Error embedding (error code 805)") - except: - logThis("Something fucked up (error code 800)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 800)") - - # Generates a random name with the nameGen function from funcs/other/generators.py - elif content.startswith("name"): - try: - await message.channel.send(nameGen()) - except: - logThis("Something fucked up (error code 330)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 330)") - - # Generates a random tavern name with the tavernGen function from funcs/other/generators.py - elif content.startswith("tavern"): - try: - await message.channel.send(tavernGen()) - except: - logThis("Something fucked up (error code 340)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 340)") - - # Changes the "Playing this game" thing in Discord - elif content.startswith("game "): - try: - gamePlaying = cap(content.replace("game ","")) - game = discord.Game(gamePlaying) - await client.change_presence(activity=game) - except: - logThis("Something fucked up (error code 350)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 350)") - - # Rolls star wars dice with the parseRoll function from funcs/swfuncs/swroll.py - elif content.startswith("swroll"): - try: - command = cap(content.replace("swroll","")) - newMessage = parseRoll("#"+str(message.author.id),command) - messageList = newMessage.split("\n") - for messageItem in messageList: - await message.channel.send(messageItem) - except: - logThis("Something fucked up (error code 910)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 910)") - - # Deals with Destiny Points and stuff - elif content.startswith("swd"): - try: - command = content.replace("swd","") - newMessage = parseDestiny("#"+str(message.author.id),command) - messageList = newMessage.split("\n") - for messageItem in messageList: - await message.channel.send(messageItem) - except: - logThis("Something fucked up (error code 920)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 920)") - - # Rolls for critical injuries - elif content.startswith("swcrit"): - try: - command = content.replace("swcrit","").replace(" ","").replace("+","") - - if command == "": - command = 0 - - try: - newMessage = critRoll(int(command)) - except: - logThis("They didn't include a number (error code 931)",str(message.channel.id)) - newMessage = "Try using a number, stupid (error code 931)" - - messageList = newMessage.split("\n") - for messageItem in messageList: - await message.channel.send(messageItem) - except: - logThis("Something fucked up (error code 930)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 930)") - - # Accesses and changes character sheet data with the parseChar function - # from funcs/swfuncs/swchar.py - elif content.startswith("swchar") or content.startswith("sw"): - try: - command = string.capwords(content.replace("swchar","").replace("sw","").replace("+","+ ").replace("-","- ").replace(",",", ")) - title, desc = parseChar("#"+str(message.author.id),command) - if title != "": - em1 = discord.Embed(title = title, description = desc, colour=0xDEADBF) - await message.channel.send(embed = em1) - else: - await message.channel.send(desc) - except: - logThis("Something fucked up (error code 940)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 940)") - - - # Searches for a specific page on the Senkulpa Wiki - elif content.startswith("wiki "): - try: - async with message.channel.typing(): - command = string.capwords(content.replace("wiki ","")) - title, content, thumbnail = findWikiPage(command) - if title != "": - logThis("Sending the embedded message",str(message.channel.id)) - content += "\n[Læs mere](https://senkulpa.fandom.com/da/wiki/"+title.replace(" ","_")+")" - embed = discord.Embed(title = title, description = content, colour=0xDEADBF) - if thumbnail != "": - embed.set_thumbnail(url=thumbnail) - - await message.channel.send(embed = embed) - else: - await message.channel.send(content) - except: - logThis("Something fucked up (error code 1000)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 1000)") - - - # Runs a trivia game - elif content.startswith("trivia"): - try: - if content == "trivia" or content == "trivia ": - question, answers, correctAnswer = triviaStart(str(message.channel.id)) - if answers != "": - results = "**"+question+"**\n" - for answer in range(len(answers)): - results += chr(answer+97) + ") "+answers[answer]+"\n" - - await message.channel.send(results) - - await asyncio.sleep(60) - - triviaCountPoints(str(message.channel.id)) - - deleteGame("trivia questions",str(message.channel.id)) - - logThis("Time's up for the trivia question",str(message.channel.id)) - await message.channel.send("Time's up The answer was \""+chr(correctAnswer)+") "+answers[correctAnswer-97]+"\". Anyone who answered that has gotten 1 GwendoBuck") - else: - await message.channel.send(question) - - elif content.startswith("trivia "): - command = content.replace("trivia ","") - response = triviaAnswer("#"+str(message.author.id),str(message.channel.id),command) - if response.startswith("Locked in "): - await message.add_reaction("👍") - else: - await message.channel.send(response) - else: - logThis("I didn't understand that (error code 1101)",str(message.channel.id)) - await message.channel.send("I didn't understand that (error code 1101)") - except: - logThis("Something fucked up (error code 1100)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 1100)") - - - # Checks your GwendoBucks balance - elif content.startswith("balance"): - try: - response = checkBalance("#"+str(message.author.id)) - if response == 1: - new_message = message.author.display_name + " has " + str(response) + " GwendoBuck" - else: - new_message = message.author.display_name + " has " + str(response) + " GwendoBucks" - await message.channel.send(new_message) - except: - logThis("Something fucked up (error code 1210)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 1210)") - - # Gives money to other player - elif content.startswith("give "): - try: - commands = content.split(" ") - if len(commands) >= 3: - try: - amount = int(commands[2]) - except: - logThis("Conversion error (error code 1221)",str(message.channel.id)) - await message.channel.send("I didn't quite understand that (error code 1221)") - else: - response = giveMoney("#"+str(message.author.id),commands[1],amount) - await message.channel.send(response) - else: - logThis("I didn't understand that (error code 1222)",str(message.channel.id)) - await message.channel.send("I didn't understand that (error code 1222)") - except: - logThis("Something fucked up (error code 1220)",str(message.channel.id)) - await message.channel.send("Something fucked up (error code 1220)") - - # Runs a game of Blackjack - elif content.startswith("blackjack"): - try: - # Starts the game - if content == "blackjack" or content == "blackjack ": - cardsLeft = 0 - if os.path.exists("resources/games/blackjackCards/"+str(message.channel.id)+".txt"): - with open("resources/games/blackjackCards/"+str(message.channel.id)+".txt","r") as f: - for _ in f: - cardsLeft += 1 - - # Shuffles if not enough cards - if cardsLeft < blackjackMinCards: - blackjackShuffle(blackjackDecks,str(message.channel.id)) - logThis("Shuffling the blackjack deck...",str(message.channel.id)) - await message.channel.send("Shuffling the deck...") - - new_message = blackjackStart(str(message.channel.id)) - if new_message == "started": - - new_message = "Blackjack game started. Use \""+commandPrefix+"blackjack bet [amount]\" to enter the game within the next 30 seconds." - await message.channel.send(new_message) - oldImage = await message.channel.send(file = discord.File("resources/games/blackjackTables/blackjackTable"+str(message.channel.id)+".png")) - - with open("resources/games/oldImages/blackjack"+str(message.channel.id), "w") as f: - f.write(str(oldImage.id)) - - await asyncio.sleep(30) - - gamedone = False - - with open("resources/games/games.json", "r") as f: - data = json.load(f) - if len(data["blackjack games"][str(message.channel.id)]["user hands"]) == 0: - gamedone = True - await message.channel.send("No one entered the game. Ending the game.") - gameID = data["blackjack games"][str(message.channel.id)]["id"] - - # Loop of game rounds - if gamedone == False: - logThis("!blackjack calling blackjackLoop()",str(message.channel.id)) - await blackjackLoop(message.channel,1,gameID) - else: - new_message = blackjackFinish(str(message.channel.id)) - await message.channel.send(new_message) - else: - await message.channel.send(new_message) - - # Entering game and placing bet - elif content.startswith("blackjack bet"): - commands = content.split(" ") - try: - amount = int(commands[2]) - except: - logThis("I didn't understand that",str(message.channel.id)) - response = "I didn't understand that" - else: - response = blackjackPlayerDrawHand(str(message.channel.id),"#"+str(message.author.id),amount) - await message.channel.send(response) - - # Hitting - elif content.startswith("blackjack hit"): - if content == "blackjack hit" or content == "blackjack hit ": - response = blackjackHit(str(message.channel.id),"#"+str(message.author.id)) - else: - commands = content.split(" ") - try: - handNumber = int(commands[2]) - except: - handNumber = 0 - response = blackjackHit(str(message.channel.id),"#"+str(message.author.id),handNumber) - - if response.startswith("accept"): - await message.add_reaction("👍") - try: - if response[6] == "T": - with open("resources/games/games.json", "r") as f: - gameID = json.load(f)["blackjack games"][str(message.channel.id)]["id"] - logThis("Hit calling blackjackLoop()",str(message.channel.id)) - await blackjackLoop(message.channel,int(response[7:])+1,gameID) - except: - logThis("Something fucked up (error code 1320)",str(message.channel.id)) - else: - await message.channel.send(response) - - - # Standing - elif content.startswith("blackjack stand"): - if content == "blackjack hit" or content == "blackjack hit ": - response = blackjackStand(str(message.channel.id),"#"+str(message.author.id)) - else: - commands = content.split(" ") - try: - handNumber = int(commands[2]) - except: - handNumber = 0 - response = blackjackStand(str(message.channel.id),"#"+str(message.author.id),handNumber) - - if response.startswith("accept"): - await message.add_reaction("👍") - try: - if response[6] == "T": - with open("resources/games/games.json", "r") as f: - gameID = json.load(f)["blackjack games"][str(message.channel.id)]["id"] - logThis("Stand calling blackjackLoop()",str(message.channel.id)) - await blackjackLoop(message.channel,int(response[7:])+1,gameID) - except: - logThis("Something fucked up (error code 1320)",str(message.channel.id)) - else: - await message.channel.send(response) - - # Doubling bet - elif content.startswith("blackjack double"): - commands = content.split(" ") - try: - handNumber = int(commands[2]) - except: - handNumber = 0 - response, roundDone = blackjackDouble(str(message.channel.id),"#"+str(message.author.id),handNumber) - - await message.channel.send(response) - - try: - if roundDone[0] == "T": - with open("resources/games/games.json", "r") as f: - gameID = json.load(f)["blackjack games"][str(message.channel.id)]["id"] - logThis("Double calling blackjackLoop()",str(message.channel.id)) - await blackjackLoop(message.channel,int(roundDone[1:])+1,gameID) - except: - logThis("Something fucked up (error code 1320)",str(message.channel.id)) - - # Splitting hand - elif content.startswith("blackjack split"): - commands = content.split(" ") - try: - handNumber = int(commands[2]) - except: - handNumber = 0 - response, roundDone = blackjackSplit(str(message.channel.id),"#"+str(message.author.id),handNumber) - - await message.channel.send(response) - - try: - if roundDone[0] == "T": - with open("resources/games/games.json", "r") as f: - gameID = json.load(f)["blackjack games"][str(message.channel.id)]["id"] - logThis("Split calling blackjackLoop()",str(message.channel.id)) - await blackjackLoop(message.channel,int(roundDone[1:])+1,gameID) - except: - logThis("Something fucked up (error code 1320)") - - # Returning current hi-lo value - elif content.startswith("blackjack hilo") and "#"+str(message.author.id) == "#266269899859427329": - if os.path.exists("resources/games/blackjackCards/"+str(message.channel.id)+".txt"): - with open("resources/games/hilo/"+str(message.channel.id)+".txt", "r") as f: - data = f.read() - else: - data = "0" - await message.channel.send(data) - - # Shuffles the blackjack deck - elif content.startswith("blackjack shuffle"): - blackjackShuffle(blackjackDecks,str(message.channel.id)) - logThis("Shuffling the blackjack deck...",str(message.channel.id)) - await message.channel.send("Shuffling the deck...") - - - # Tells you the amount of cards left - elif content.startswith("blackjack cards"): - cardsLeft = 0 - if os.path.exists("resources/games/blackjackCards/"+str(message.channel.id)+".txt"): - with open("resources/games/blackjackCards/"+str(message.channel.id)+".txt","r") as f: - for _ in f: - cardsLeft += 1 - - decksLeft = round(cardsLeft/52,1) - await message.channel.send(str(cardsLeft)+" cards, "+str(decksLeft)+" decks") - - else: - logThis("Not a command (error code 1301)") - await message.channel.send("I didn't quite understand that (error code 1301)") - except: - logThis("Something went wrong (error code 1300)") # Runs a game of four in a row elif content.startswith("fourinarow"): @@ -582,57 +51,4 @@ async def parseCommands(message,content): logThis("That's not a command (error code 001)",str(message.channel.id)) await message.channel.send("That's not a command (error code 001)") -# Makes files if they don't exist yet -makeFiles() -# Gets secret bot token -with open("token.txt","r") as f: - token = f.read().replace("\n","") - -client = discord.Client() - -# Logs in -@client.event -async def on_ready(): - logThis("Logged in as "+client.user.name+", "+str(client.user.id)) - game = discord.Game("Some weeb shit") - await client.change_presence(activity=game) - -# Reads messages and tests if they are Gwendolyn commands -@client.event -async def on_message(message): - try: - content = message.content - if content.startswith(commandPrefix): - logThis(message.author.display_name+" ("+"#"+str(message.author.id)+") ran \""+content+"\"",str(message.channel.id)) - addToDict("#"+str(message.author.id),message.author.display_name) - await parseCommands(message,content.lower()[1:]) - except: - logThis("Something fucked up (error code 000)") - await message.channel.send("Something fucked up (error code 000)") - - # Is a bit sassy sometimes - if ("gwendolyn" in message.content.lower() or message.content.startswith(commandPrefix)) and any(x in message.content.lower() for x in meanWords) and "ikke" not in message.content.lower() and "not" not in message.content.lower(): - logThis(message.author.display_name+" was a bit mean",str(message.channel.id)) - emoji = random.choice(["😠", "🖕", "👎"]) - await message.add_reaction(emoji) - -@client.event -async def on_reaction_add(reaction,user): - if user.bot == False: - message = reaction.message - channel = message.channel - logThis(user.display_name+" reacted to a message",str(channel.id)) - try: - fourInARowTheirTurn, piece = fiarReactionTest(channel,message,"#"+str(user.id)) - except: - fourInARowTheirTurn = False - - if fourInARowTheirTurn: - place = emojiToCommand(reaction.emoji) - await fiar(channel," place "+str(piece)+" "+str(place),user.id) - elif monopolyReactionTest(channel,message): - await runMonopoly(channel,"roll","#"+str(user.id)) - -# Runs the whole shabang -client.run(token) diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..4f590d8 --- /dev/null +++ b/bot.py @@ -0,0 +1,52 @@ +import discord, os + +from discord.ext import commands + +from funcs import logThis, makeFiles + +commandPrefix = "!" +client = commands.Bot(command_prefix=commandPrefix) + +# Logs in +@client.event +async def on_ready(): + logThis("Logged in as "+client.user.name+", "+str(client.user.id)) + game = discord.Game("Some weeb shit") + await client.change_presence(activity=game) + +# Loads and unloads cogs + +@client.command() +async def load(ctx,extension): + client.load_extension(f"cogs.{extension}") + +@client.command() +async def unload(ctx,extension): + client.unload_extension(f"cogs.{extension}") + +@client.event +async def on_command(ctx): + logThis(f"{ctx.message.author.display_name} ran {ctx.message.content}") + +# Logs if a command experiences an error +@client.event +async def on_command_error(ctx, error): + if isinstance(error, commands.CommandNotFound): + await ctx.send("That's not a command (error code 001)") + else: + logThis(f"Something went wrong, {error}",str(ctx.message.channel.id)) + await ctx.send("Something went wrong (error code 000)") + +for filename in os.listdir("./cogs"): + if filename.endswith(".py"): + client.load_extension(f"cogs.{filename[:-3]}") + +# Creates the required files +makeFiles() + +# Gets secret bot token +with open("token.txt","r") as f: + token = f.read().replace("\n","") + +# Runs the whole shabang +client.run(token) diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py new file mode 100644 index 0000000..c0b651c --- /dev/null +++ b/cogs/GamesCog.py @@ -0,0 +1,269 @@ +import discord, asyncio, os, json +from discord.ext import commands + +from funcs import logThis, triviaAnswer, triviaCountPoints, triviaStart, deleteGame, checkBalance, giveMoney, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackHit, blackjackDouble, blackjackFinish, blackjackSplit, blackjackStand + +from gameLoops import blackjackLoop, fiar, runMonopoly, runHex + +class GamesCog(commands.Cog): + + """Cog for game functions""" + + def __init__(self,client): + self.client = client + + # Checks user balance + @commands.command(aliases = ["b"]) + async def balance(self, ctx): + response = checkBalance("#"+str(ctx.message.author.id)) + if response == 1: + new_message = ctx.message.author.display_name + " has " + str(response) + " GwendoBuck" + else: + new_message = ctx.message.author.display_name + " has " + str(response) + " GwendoBucks" + await ctx.send(new_message) + + # Gives another user an amount of GwendoBucks + @commands.command() + async def give(self, ctx, *, content): + commands = content.split(" ") + if len(commands) == 2: + print(commands) + amount = int(commands[1]) + response = giveMoney("#"+str(ctx.message.author.id),commands[0],amount) + await ctx.send(response) + else: + logThis("I didn't understand that (error code 1222)",str(ctx.message.channel.id)) + await ctx.send("I didn't understand that (error code 1222)") + + # Runs a game of trivia + @commands.command() + async def trivia(self, ctx, *, content = ""): + if content == "": + question, answers, correctAnswer = triviaStart(str(ctx.message.channel.id)) + if answers != "": + results = "**"+question+"**\n" + for answer in range(len(answers)): + results += chr(answer+97) + ") "+answers[answer]+"\n" + + await ctx.send(results) + + await asyncio.sleep(60) + + triviaCountPoints(str(ctx.message.channel.id)) + + deleteGame("trivia questions",str(ctx.message.channel.id)) + + logThis("Time's up for the trivia question",str(ctx.message.channel.id)) + await ctx.send("Time's up The answer was \""+chr(correctAnswer)+") "+answers[correctAnswer-97]+"\". Anyone who answered that has gotten 1 GwendoBuck") + else: + await ctx.send(question) + + elif content in ["a","b","c","d"]: + response = triviaAnswer("#"+str(ctx.message.author.id),str(ctx.message.channel.id),content) + if response.startswith("Locked in "): + await ctx.message.add_reaction("👍") + else: + await ctx.send(response) + else: + logThis("I didn't understand that (error code 1101)",str(ctx.message.channel.id)) + await ctx.send("I didn't understand that (error code 1101)") + + # Runs a game of blackjack + @commands.command(aliases = ["bj"]) + async def blackjack(self, ctx, *, content = ""): + # Blackjack shuffle variables + blackjackMinCards = 50 + blackjackDecks = 4 + + channel = ctx.message.channel.id + # Starts the game + if content == "": + cardsLeft = 0 + if os.path.exists("resources/games/blackjackCards/"+str(channel)+".txt"): + with open("resources/games/blackjackCards/"+str(channel)+".txt","r") as f: + for _ in f: + cardsLeft += 1 + + # Shuffles if not enough cards + if cardsLeft < blackjackMinCards: + blackjackShuffle(blackjackDecks,str(channel)) + logThis("Shuffling the blackjack deck...",str(channel)) + await ctx.send("Shuffling the deck...") + + new_message = blackjackStart(str(channel)) + if new_message == "started": + + new_message = "Blackjack game started. Use \"!blackjack bet [amount]\" to enter the game within the next 30 seconds." + await ctx.send(new_message) + oldImage = await ctx.send(file = discord.File("resources/games/blackjackTables/blackjackTable"+str(channel)+".png")) + + with open("resources/games/oldImages/blackjack"+str(channel), "w") as f: + f.write(str(oldImage.id)) + + await asyncio.sleep(30) + + gamedone = False + + with open("resources/games/games.json", "r") as f: + data = json.load(f) + if len(data["blackjack games"][str(channel)]["user hands"]) == 0: + gamedone = True + await ctx.send("No one entered the game. Ending the game.") + gameID = data["blackjack games"][str(channel)]["id"] + + # Loop of game rounds + if gamedone == False: + logThis("!blackjack calling blackjackLoop()",str(channel)) + await blackjackLoop(ctx.message.channel,1,gameID) + else: + new_message = blackjackFinish(str(channel)) + await ctx.send(new_message) + else: + await ctx.send(new_message) + + # Entering game and placing bet + elif content.startswith("bet"): + commands = content.split(" ") + amount = int(commands[1]) + response = blackjackPlayerDrawHand(str(channel),"#"+str(ctx.message.author.id),amount) + await ctx.send(response) + + # Hitting + elif content.startswith("hit"): + if content == "hit": + response = blackjackHit(str(channel),"#"+str(ctx.message.author.id)) + else: + commands = content.split(" ") + try: + handNumber = int(commands[1]) + except: + handNumber = 0 + response = blackjackHit(str(channel),"#"+str(ctx.message.author.id),handNumber) + + if response.startswith("accept"): + await ctx.message.add_reaction("👍") + try: + if response[6] == "T": + with open("resources/games/games.json", "r") as f: + gameID = json.load(f)["blackjack games"][str(channel)]["id"] + logThis("Hit calling blackjackLoop()",str(channel)) + await blackjackLoop(ctx.message.channel,int(response[7:])+1,gameID) + except: + logThis("Something fucked up (error code 1320)",str(channel)) + else: + await ctx.send(response) + + + # Standing + elif content.startswith("stand"): + if content == "hit": + response = blackjackStand(str(channel),"#"+str(ctx.message.author.id)) + else: + commands = content.split(" ") + try: + handNumber = int(commands[1]) + except: + handNumber = 0 + response = blackjackStand(str(channel),"#"+str(ctx.message.author.id),handNumber) + + if response.startswith("accept"): + await ctx.message.add_reaction("👍") + try: + if response[6] == "T": + with open("resources/games/games.json", "r") as f: + gameID = json.load(f)["blackjack games"][str(channel)]["id"] + logThis("Stand calling blackjackLoop()",str(channel)) + await blackjackLoop(ctx.message.channel,int(response[7:])+1,gameID) + except: + logThis("Something fucked up (error code 1320)",str(channel)) + else: + await ctx.send(response) + + # Doubling bet + elif content.startswith("blackjack double"): + commands = content.split(" ") + try: + handNumber = int(commands[1]) + except: + handNumber = 0 + response, roundDone = blackjackDouble(str(channel),"#"+str(ctx.message.author.id),handNumber) + + await ctx.send(response) + + try: + if roundDone[0] == "T": + with open("resources/games/games.json", "r") as f: + gameID = json.load(f)["blackjack games"][str(channel)]["id"] + logThis("Double calling blackjackLoop()",str(channel)) + await blackjackLoop(ctx.message.channel,int(roundDone[1:])+1,gameID) + except: + logThis("Something fucked up (error code 1320)",str(channel)) + + # Splitting hand + elif content.startswith("blackjack split"): + commands = content.split(" ") + try: + handNumber = int(commands[1]) + except: + handNumber = 0 + response, roundDone = blackjackSplit(str(channel),"#"+str(ctx.message.author.id),handNumber) + + await ctx.send(response) + + try: + if roundDone[0] == "T": + with open("resources/games/games.json", "r") as f: + gameID = json.load(f)["blackjack games"][str(channel)]["id"] + logThis("Split calling blackjackLoop()",str(channel)) + await blackjackLoop(ctx.message.channel,int(roundDone[1:])+1,gameID) + except: + logThis("Something fucked up (error code 1320)") + + # Returning current hi-lo value + elif content.startswith("blackjack hilo") and "#"+str(ctx.message.author.id) == "#266269899859427329": + if os.path.exists("resources/games/blackjackCards/"+str(channel)+".txt"): + with open("resources/games/hilo/"+str(channel)+".txt", "r") as f: + data = f.read() + else: + data = "0" + await ctx.send(data) + + # Shuffles the blackjack deck + elif content.startswith("blackjack shuffle"): + blackjackShuffle(blackjackDecks,str(channel)) + logThis("Shuffling the blackjack deck...",str(channel)) + await ctx.send("Shuffling the deck...") + + + # Tells you the amount of cards left + elif content.startswith("blackjack cards"): + cardsLeft = 0 + if os.path.exists("resources/games/blackjackCards/"+str(channel)+".txt"): + with open("resources/games/blackjackCards/"+str(channel)+".txt","r") as f: + for _ in f: + cardsLeft += 1 + + decksLeft = round(cardsLeft/52,1) + await ctx.send(str(cardsLeft)+" cards, "+str(decksLeft)+" decks") + + else: + logThis("Not a command (error code 1301)") + await ctx.send("I didn't quite understand that (error code 1301)") + + # Runs a game of Connect four + @commands.command(aliases = ["fiar","connect4","connectfour","4iar","4inarow"]) + async def fourinarow(self, ctx, *, content = ""): + await fiar(ctx.message.channel,content,"#"+str(ctx.message.author.id)) + + # Runs a game of Hex + @commands.command(name="hex") + async def hexCommand(self, ctx, *, content = ""): + await runHex(ctx.message.channel,content,"#"+str(ctx.message.author.id)) + + # Runs a game of Monopoly + @commands.command(aliases = ["m","mon","mono"]) + async def monopoly(self, ctx, *, content = ""): + await runMonopoly(ctx.message.channel,content,"#"+str(ctx.message.author.id)) + +def setup(client): + client.add_cog(GamesCog(client)) \ No newline at end of file diff --git a/cogs/LookupCog.py b/cogs/LookupCog.py new file mode 100644 index 0000000..146568e --- /dev/null +++ b/cogs/LookupCog.py @@ -0,0 +1,70 @@ +import discord, codecs +from discord.ext import commands + +from funcs import logThis, spellFunc, monsterFunc, cap + +class LookupCog(commands.Cog): + + """Cog for lookup functions""" + + def __init__(self,client): + self.client = client + + # Looks up a spell + @commands.command() + async def spell(self, ctx, *, content): + spell = spellFunc(cap(content)) + if len(spell) > 2000: + await ctx.send(spell[:2000]) + await ctx.send(spell[2000:]) + else: + await ctx.send(spell) + + # Looks up a monster + @commands.command() + async def monster(self, ctx, *, content): + title, text1, text2, text3, text4, text5 = monsterFunc(cap(content)) + em1 = discord.Embed(title = title, description = text1, colour=0xDEADBF) + + # Sends the received information. Seperates into seperate messages if + # there is too much text + await ctx.send(embed = em1) + if text2 != "": + if len(text2) < 2048: + em2 = discord.Embed(title = "Special Abilities", description = text2, colour=0xDEADBF) + await ctx.send(embed = em2) + else: + em2 = discord.Embed(title = "Special Abilities", description = text2[:2048], colour=0xDEADBF) + await ctx.send(embed = em2) + em2_2 = discord.Embed(title = "", description = text2[2048:], colour=0xDEADBF) + await ctx.send(embed = em2_2) + if text3 != "": + if len(text3) < 2048: + em3 = discord.Embed(title = "Actions", description = text3, colour=0xDEADBF) + await ctx.send(embed = em3) + else: + em3 = discord.Embed(title = "Actions", description = text3[:2048], colour=0xDEADBF) + await ctx.send(embed = em3) + em3_2 = discord.Embed(title = "", description = text3[2048:], colour=0xDEADBF) + await ctx.send(embed = em3_2) + if text4 != "": + if len(text4) < 2048: + em4 = discord.Embed(title = "Reactions", description = text4, colour=0xDEADBF) + await ctx.send(embed = em4) + else: + em4 = discord.Embed(title = "Reactions", description = text4[:2048], colour=0xDEADBF) + await ctx.send(embed = em4) + em4_2 = discord.Embed(title = "", description = text4[2048:], colour=0xDEADBF) + await ctx.send(embed = em4_2) + if text5 != "": + if len(text5) < 2048: + em5 = discord.Embed(title = "Legendary Actions", description = text5, colour=0xDEADBF) + await ctx.send(embed = em5) + else: + em5 = discord.Embed(title = "Legendary Actions", description = text5[:2048], colour=0xDEADBF) + await ctx.send(embed = em5) + em5_2 = discord.Embed(title = "", description = text5[2048:], colour=0xDEADBF) + await ctx.send(embed = em5_2) + +def setup(client): + client.add_cog(LookupCog(client)) \ No newline at end of file diff --git a/cogs/MiscCog.py b/cogs/MiscCog.py new file mode 100644 index 0000000..ca23d8f --- /dev/null +++ b/cogs/MiscCog.py @@ -0,0 +1,123 @@ +import discord, codecs, string +from discord.ext import commands + +from funcs import logThis, stopServer, helloFunc, roll_dice, imageFunc, nameGen, tavernGen, movieFunc, cap, findWikiPage + +class MiscCog(commands.Cog): + + """Cog for misc functions""" + + def __init__(self,client): + self.client = client + self.client.remove_command("help") + + @commands.command(name = "help") + async def helpCommand(self, ctx, *, content = ""): + if content == "": + with codecs.open("resources/help/help.txt",encoding="utf-8") as f: + text = f.read() + em = discord.Embed(title = "Help", description = text,colour = 0x59f442) + await ctx.send(embed = em) + else: + logThis(f"Looking for help-{content}.txt",str(ctx.message.channel.id)) + with codecs.open(f"resources/help/help-{content}.txt",encoding="utf-8") as f: + text = f.read() + em = discord.Embed(title = content.capitalize(), description = text,colour = 0x59f442) + await ctx.send(embed = em) + + # Sends the bot's latency + @commands.command() + async def ping(self, ctx): + await ctx.send(f"Pong!\nLatency is {round(self.client.latency * 1000)} ms") + + # Logs whatever is written + @commands.command(hidden = True) + async def log(self, ctx, *, content): + logThis(content,str("Logged by "+ctx.message.author.display_name)) + + # Stops the bot + @commands.command(hidden = True) + async def stop(self, ctx): + if "#"+str(ctx.message.author.id) in ["#266269899859427329", "#380732645602230272"]: + await ctx.send("Logging out...") + + stopServer() + + await self.client.logout() + else: + logThis(f"{ctx.message.author.display_name} tried to stop me! (error code 201)",str(ctx.message.channel.id)) + await ctx.send(f"I don't think I will, {ctx.message.author.display_name} (error code 201)") + + # Sends a friendly message + @commands.command(aliases = ["hi","howdy"]) + async def hello(self, ctx): + await ctx.send(helloFunc(ctx.message.author.display_name)) + + # Rolls dice + @commands.command() + async def roll(self, ctx, *, content = "1d20"): + await ctx.send(roll_dice(ctx.message.author.display_name,content)) + + # Sends an image of the Senkulpa map + @commands.command(name="map") + async def mapCommand(self, ctx): + await ctx.send("https://i.imgur.com/diMXXJs.jpg") + + # Sends a random image + @commands.command(aliases = ["img"]) + async def image(self, ctx): + randomImage = imageFunc() + await ctx.send(randomImage) + + # Finds a random movie + @commands.command() + async def movie(self,ctx): + async with ctx.typing(): + title, plot, cover, cast = movieFunc() + if title == "error": + await ctx.send("An error occurred. Try again (error code "+plot+")") + else: + try: + embed = discord.Embed(title=title, description=plot, color=0x24ec19) + embed.set_thumbnail(url=cover) + embed.add_field(name="Cast", value=cast,inline = True) + await ctx.send(embed = embed) + except: + logThis("Error embedding (error code 805)") + + # Generates a random name + @commands.command() + async def name(self, ctx): + await ctx.send(nameGen()) + + # Generates a random tavern name + @commands.command() + async def tavern(self, ctx): + await ctx.send(tavernGen()) + + # Sets the game Gwendolyn's playing + @commands.command() + async def game(self, ctx, *, content): + gamePlaying = cap(content) + game = discord.Game(gamePlaying) + await self.client.change_presence(activity=game) + + # Finds a page on the Senkulpa wiki + @commands.command(aliases = ["wikia"]) + async def wiki(self, ctx, *, content): + async with ctx.message.channel.typing(): + command = string.capwords(content) + title, content, thumbnail = findWikiPage(command) + if title != "": + logThis("Sending the embedded message",str(ctx.message.channel.id)) + content += "\n[Læs mere](https://senkulpa.fandom.com/da/wiki/"+title.replace(" ","_")+")" + embed = discord.Embed(title = title, description = content, colour=0xDEADBF) + if thumbnail != "": + embed.set_thumbnail(url=thumbnail) + + await ctx.send(embed = embed) + else: + await ctx.send(content) + +def setup(client): + client.add_cog(MiscCog(client)) diff --git a/cogs/ReactionCog.py b/cogs/ReactionCog.py new file mode 100644 index 0000000..f7ce202 --- /dev/null +++ b/cogs/ReactionCog.py @@ -0,0 +1,31 @@ +import discord +from discord.ext import commands + +from funcs import logThis, fiarReactionTest, monopolyReactionTest, emojiToCommand +from gameLoops import fiar, runMonopoly + +class ReactionCog(commands.Cog): + + """Cog for reactions""" + + def __init__(self, client): + self.client = client + + @commands.Cog.listener() + async def on_reaction_add(self, reaction,user): + if user.bot == False: + message = reaction.message + channel = message.channel + logThis(user.display_name+" reacted to a message",str(channel.id)) + try: + fourInARowTheirTurn, piece = fiarReactionTest(channel,message,"#"+str(user.id)) + except: + fourInARowTheirTurn = False + + if fourInARowTheirTurn: + place = emojiToCommand(reaction.emoji) + await fiar(channel," place "+str(piece)+" "+str(place),user.id) + elif monopolyReactionTest(channel,message): + await runMonopoly(channel,"roll","#"+str(user.id)) +def setup(client): + client.add_cog(ReactionCog(client)) diff --git a/cogs/SwCog.py b/cogs/SwCog.py new file mode 100644 index 0000000..4ea4150 --- /dev/null +++ b/cogs/SwCog.py @@ -0,0 +1,52 @@ +import discord, string +from discord.ext import commands + +from funcs import logThis, parseRoll, parseDestiny, critRoll, parseChar, cap + +class SwCog(commands.Cog): + + """Cog for Star Wars functions""" + + def __init__(self,client): + self.client = client + + # Rolls star wars dice + @commands.command() + async def swroll(self, ctx, *, content): + command = cap(content) + newMessage = parseRoll("#"+str(ctx.message.author.id),command) + messageList = newMessage.split("\n") + for messageItem in messageList: + await ctx.send(messageItem) + + # Controls destiny points + @commands.command() + async def swd(self, ctx, *, content): + newMessage = parseDestiny("#"+str(ctx.message.author.id),content) + messageList = newMessage.split("\n") + for messageItem in messageList: + await ctx.send(messageItem) + + # Rolls for critical injuries + @commands.command() + async def swcrit(self, ctx, arg : int = 0): + newMessage = critRoll(int(arg)) + + messageList = newMessage.split("\n") + for messageItem in messageList: + await ctx.send(messageItem) + + # Accesses and changes character sheet data with the parseChar function + # from funcs/swfuncs/swchar.py + @commands.command(aliases=["sw"]) + async def swchar(self, ctx, *, content = ""): + command = string.capwords(content.replace("+","+ ").replace("-","- ").replace(",",", ")) + title, desc = parseChar("#"+str(ctx.message.author.id),command) + if title != "": + em1 = discord.Embed(title = title, description = desc, colour=0xDEADBF) + await ctx.send(embed = em1) + else: + await ctx.send(desc) + +def setup(client): + client.add_cog(SwCog(client)) \ No newline at end of file diff --git a/funcs/games/money.py b/funcs/games/money.py index 0ab8283..1e2965d 100644 --- a/funcs/games/money.py +++ b/funcs/games/money.py @@ -36,7 +36,7 @@ def giveMoney(user,targetUser,amount): targetUser = getID(targetUser) if amount > 0: - if targetUser.startswith("#"): + if targetUser != None: if user in data: if data[user]["money"] >= amount: addMoney(user,-1 * amount) diff --git a/funcs/roll/dice.py b/funcs/roll/dice.py index 9fe7761..03385d8 100644 --- a/funcs/roll/dice.py +++ b/funcs/roll/dice.py @@ -11,7 +11,7 @@ class MyStringifier(d20.MarkdownStringifier): return f"**{resultText}**: {self._stringify(node.roll)}\n**Total**: {int(node.total)}" -def roll_dice(user,rollString = "1d20"): +def roll_dice(user, rollString): while len(rollString) > 1 and rollString[0] == " ": rollString = rollString[1:] return user+" :game_die:\n"+str(d20.roll(rollString, allow_comments=True,stringifier=MyStringifier())) From cab088af3d025e3a702219108982448bd9c01e16 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 13:04:59 +0200 Subject: [PATCH 14/26] :bug: --- cogs/LookupCog.py | 4 ++-- cogs/ReactionCog.py | 1 - cogs/SwCog.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cogs/LookupCog.py b/cogs/LookupCog.py index 146568e..55e3e0d 100644 --- a/cogs/LookupCog.py +++ b/cogs/LookupCog.py @@ -1,7 +1,7 @@ -import discord, codecs +import discord from discord.ext import commands -from funcs import logThis, spellFunc, monsterFunc, cap +from funcs import spellFunc, monsterFunc, cap class LookupCog(commands.Cog): diff --git a/cogs/ReactionCog.py b/cogs/ReactionCog.py index f7ce202..7ccb35b 100644 --- a/cogs/ReactionCog.py +++ b/cogs/ReactionCog.py @@ -1,4 +1,3 @@ -import discord from discord.ext import commands from funcs import logThis, fiarReactionTest, monopolyReactionTest, emojiToCommand diff --git a/cogs/SwCog.py b/cogs/SwCog.py index 4ea4150..c13e93b 100644 --- a/cogs/SwCog.py +++ b/cogs/SwCog.py @@ -1,7 +1,7 @@ import discord, string from discord.ext import commands -from funcs import logThis, parseRoll, parseDestiny, critRoll, parseChar, cap +from funcs import parseRoll, parseDestiny, critRoll, parseChar, cap class SwCog(commands.Cog): From b89448044631b3f787ab87928eeccbb4bde097b0 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 13:07:19 +0200 Subject: [PATCH 15/26] :bug: --- Gwendolyn.py | 84 +++++++++++++++++++++++++--------------------------- bot.py | 52 -------------------------------- 2 files changed, 41 insertions(+), 95 deletions(-) delete mode 100644 bot.py diff --git a/Gwendolyn.py b/Gwendolyn.py index 74357b5..4f590d8 100644 --- a/Gwendolyn.py +++ b/Gwendolyn.py @@ -1,54 +1,52 @@ -# -*- coding: utf-8 -*- - -import discord -import asyncio -#import pickle -import codecs -import string -import json -import random -#import math -import os +import discord, os from discord.ext import commands -from funcs import helloFunc, cap, imageFunc, logThis, findWikiPage, makeFiles, emojiToCommand, fiarReactionTest, deleteGame, stopServer, checkBalance, giveMoney, triviaCountPoints, triviaStart, triviaAnswer, blackjackShuffle, blackjackStart, blackjackPlayerDrawHand, blackjackFinish, blackjackHit, blackjackStand, blackjackDouble, blackjackSplit, parseFourInARow, fourInARowAI, spellFunc, monsterFunc, nameGen, tavernGen, movieFunc, roll_dice, parseChar, parseRoll, critRoll, parseDestiny, parseHex, addToDict, monopolyReactionTest +from funcs import logThis, makeFiles -from gameLoops import fiar, blackjackLoop, runHex, runMonopoly +commandPrefix = "!" +client = commands.Bot(command_prefix=commandPrefix) -# Blackjack shuffle variables -blackjackMinCards = 50 -blackjackDecks = 4 +# Logs in +@client.event +async def on_ready(): + logThis("Logged in as "+client.user.name+", "+str(client.user.id)) + game = discord.Game("Some weeb shit") + await client.change_presence(activity=game) -async def parseCommands(message,content): +# Loads and unloads cogs - # Runs a game of four in a row - elif content.startswith("fourinarow"): - try: - command = content.replace("fourinarow","") - await fiar(message.channel,command,"#"+str(message.author.id)) - except: - logThis("Something went wrong (error code 1400)") +@client.command() +async def load(ctx,extension): + client.load_extension(f"cogs.{extension}") - # Runs a game of Hex - elif content.startswith("hex"): - try: - command = content.replace("hex","") - await runHex(message.channel,command,"#"+str(message.author.id)) - except: - logThis("Something went wrong (error code 1500)") - - # Runs a game of monopoly - elif content.startswith("monopoly"): - try: - command = content.replace("monopoly","",1) - await runMonopoly(message.channel,command,"#"+str(message.author.id)) - except: - logThis("Something went wrong (error code 1600)") - - # Not a command +@client.command() +async def unload(ctx,extension): + client.unload_extension(f"cogs.{extension}") + +@client.event +async def on_command(ctx): + logThis(f"{ctx.message.author.display_name} ran {ctx.message.content}") + +# Logs if a command experiences an error +@client.event +async def on_command_error(ctx, error): + if isinstance(error, commands.CommandNotFound): + await ctx.send("That's not a command (error code 001)") else: - logThis("That's not a command (error code 001)",str(message.channel.id)) - await message.channel.send("That's not a command (error code 001)") + logThis(f"Something went wrong, {error}",str(ctx.message.channel.id)) + await ctx.send("Something went wrong (error code 000)") +for filename in os.listdir("./cogs"): + if filename.endswith(".py"): + client.load_extension(f"cogs.{filename[:-3]}") +# Creates the required files +makeFiles() + +# Gets secret bot token +with open("token.txt","r") as f: + token = f.read().replace("\n","") + +# Runs the whole shabang +client.run(token) diff --git a/bot.py b/bot.py deleted file mode 100644 index 4f590d8..0000000 --- a/bot.py +++ /dev/null @@ -1,52 +0,0 @@ -import discord, os - -from discord.ext import commands - -from funcs import logThis, makeFiles - -commandPrefix = "!" -client = commands.Bot(command_prefix=commandPrefix) - -# Logs in -@client.event -async def on_ready(): - logThis("Logged in as "+client.user.name+", "+str(client.user.id)) - game = discord.Game("Some weeb shit") - await client.change_presence(activity=game) - -# Loads and unloads cogs - -@client.command() -async def load(ctx,extension): - client.load_extension(f"cogs.{extension}") - -@client.command() -async def unload(ctx,extension): - client.unload_extension(f"cogs.{extension}") - -@client.event -async def on_command(ctx): - logThis(f"{ctx.message.author.display_name} ran {ctx.message.content}") - -# Logs if a command experiences an error -@client.event -async def on_command_error(ctx, error): - if isinstance(error, commands.CommandNotFound): - await ctx.send("That's not a command (error code 001)") - else: - logThis(f"Something went wrong, {error}",str(ctx.message.channel.id)) - await ctx.send("Something went wrong (error code 000)") - -for filename in os.listdir("./cogs"): - if filename.endswith(".py"): - client.load_extension(f"cogs.{filename[:-3]}") - -# Creates the required files -makeFiles() - -# Gets secret bot token -with open("token.txt","r") as f: - token = f.read().replace("\n","") - -# Runs the whole shabang -client.run(token) From 8126920e5ddbc6bd01481906ac988afd62196185 Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Thu, 6 Aug 2020 13:57:15 +0200 Subject: [PATCH 16/26] :art: :bug: --- funcs/games/monopolyDraw.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/funcs/games/monopolyDraw.py b/funcs/games/monopolyDraw.py index 598cc8c..926bb52 100644 --- a/funcs/games/monopolyDraw.py +++ b/funcs/games/monopolyDraw.py @@ -43,9 +43,9 @@ def getPosition(positionNumber): elif positionNumber > 20 and positionNumber < 30: x = w - math.floor(largeSpace - (smallSpace/2)) - (smallSpace*(positionNumber - 20)) - if positionNumber >= 0 and positionNumber <= 9: + if positionNumber >= 0 and positionNumber <= 20: y = math.floor(largeSpace/2) - elif positionNumber > 10 and positionNumber < 19: + elif positionNumber > 10 and positionNumber < 20: y = math.floor(largeSpace - (smallSpace/2)) + (smallSpace*(positionNumber-10)) elif positionNumber >= 20 and positionNumber <= 30: y = h - math.floor(largeSpace/2) From c18fe65607aed34d4c6d0be9bfe1c656b029eb69 Mon Sep 17 00:00:00 2001 From: NikolajDanger Date: Thu, 6 Aug 2020 14:04:44 +0200 Subject: [PATCH 17/26] :bug: --- funcs/games/blackjackDraw.py | 2 +- funcs/games/money.py | 2 +- funcs/games/monopolyDraw.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/funcs/games/blackjackDraw.py b/funcs/games/blackjackDraw.py index 46c1eb4..fdb3eb1 100644 --- a/funcs/games/blackjackDraw.py +++ b/funcs/games/blackjackDraw.py @@ -22,7 +22,7 @@ def drawImage(channel): dealerBusted = data["blackjack games"][channel]["dealer busted"] dealerBlackjack = data["blackjack games"][channel]["dealer blackjack"] - + try: if data["blackjack games"][channel]["all standing"] == False: dealerHand = drawHand(data["blackjack games"][channel]["dealer hand"],True,False,False) diff --git a/funcs/games/money.py b/funcs/games/money.py index 1e2965d..14d1167 100644 --- a/funcs/games/money.py +++ b/funcs/games/money.py @@ -18,7 +18,7 @@ def addMoney(user,amount): logThis("adding "+str(amount)+" to "+user+"'s account") with open("resources/users.json", "r") as f: data = json.load(f) - + if user in data: points = data[user]["money"] data[user]["money"] = points + amount diff --git a/funcs/games/monopolyDraw.py b/funcs/games/monopolyDraw.py index 926bb52..45fddd8 100644 --- a/funcs/games/monopolyDraw.py +++ b/funcs/games/monopolyDraw.py @@ -42,7 +42,7 @@ def getPosition(positionNumber): x = w - math.floor(largeSpace/2) elif positionNumber > 20 and positionNumber < 30: x = w - math.floor(largeSpace - (smallSpace/2)) - (smallSpace*(positionNumber - 20)) - + if positionNumber >= 0 and positionNumber <= 20: y = math.floor(largeSpace/2) elif positionNumber > 10 and positionNumber < 20: From 34d9c56489939d657f18e3cf4799f3296551dd6c Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 14:16:27 +0200 Subject: [PATCH 18/26] :bug: --- cogs/GamesCog.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py index c0b651c..1692dea 100644 --- a/cogs/GamesCog.py +++ b/cogs/GamesCog.py @@ -180,7 +180,7 @@ class GamesCog(commands.Cog): await ctx.send(response) # Doubling bet - elif content.startswith("blackjack double"): + elif content.startswith("double"): commands = content.split(" ") try: handNumber = int(commands[1]) @@ -200,7 +200,7 @@ class GamesCog(commands.Cog): logThis("Something fucked up (error code 1320)",str(channel)) # Splitting hand - elif content.startswith("blackjack split"): + elif content.startswith("split"): commands = content.split(" ") try: handNumber = int(commands[1]) @@ -220,7 +220,7 @@ class GamesCog(commands.Cog): logThis("Something fucked up (error code 1320)") # Returning current hi-lo value - elif content.startswith("blackjack hilo") and "#"+str(ctx.message.author.id) == "#266269899859427329": + elif content.startswith("hilo") and "#"+str(ctx.message.author.id) == "#266269899859427329": if os.path.exists("resources/games/blackjackCards/"+str(channel)+".txt"): with open("resources/games/hilo/"+str(channel)+".txt", "r") as f: data = f.read() @@ -229,14 +229,14 @@ class GamesCog(commands.Cog): await ctx.send(data) # Shuffles the blackjack deck - elif content.startswith("blackjack shuffle"): + elif content.startswith("shuffle"): blackjackShuffle(blackjackDecks,str(channel)) logThis("Shuffling the blackjack deck...",str(channel)) await ctx.send("Shuffling the deck...") # Tells you the amount of cards left - elif content.startswith("blackjack cards"): + elif content.startswith("cards"): cardsLeft = 0 if os.path.exists("resources/games/blackjackCards/"+str(channel)+".txt"): with open("resources/games/blackjackCards/"+str(channel)+".txt","r") as f: From 3c5e3e3a0a07972f8406108dd2553801c6424b9f Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 15:15:37 +0200 Subject: [PATCH 19/26] :game_die: --- funcs/games/monopoly.py | 23 +++++++++++++++++++--- gameLoops.py | 2 +- resources/games/monopolyProperties/R1.png | Bin 0 -> 39304 bytes resources/games/monopolyProperties/R2.png | Bin 0 -> 39304 bytes resources/games/monopolyProperties/R3.png | Bin 0 -> 39304 bytes resources/games/monopolyProperties/Y1.png | Bin 0 -> 39304 bytes resources/games/monopolyProperties/Y2.png | Bin 0 -> 39304 bytes resources/games/monopolyProperties/Y3.png | Bin 0 -> 39304 bytes 8 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 resources/games/monopolyProperties/R1.png create mode 100644 resources/games/monopolyProperties/R2.png create mode 100644 resources/games/monopolyProperties/R3.png create mode 100644 resources/games/monopolyProperties/Y1.png create mode 100644 resources/games/monopolyProperties/Y2.png create mode 100644 resources/games/monopolyProperties/Y3.png diff --git a/funcs/games/monopoly.py b/funcs/games/monopoly.py index 4990add..0d29a60 100644 --- a/funcs/games/monopoly.py +++ b/funcs/games/monopoly.py @@ -3,6 +3,11 @@ import json, random from funcs import getName, logThis from . import monopolyDraw +rulesAndTerms = { + "pass go money" : 200, + "money term" : "GP" +} + def monopolyStart(channel): logThis("Starting a monopoly game") with open("resources/games/monopolyGames.json", "r") as f: @@ -83,7 +88,10 @@ def monopolyContinue(channel): turn = 0 else: - turn = (data[channel]["turn"])%len(data[channel]["player list"]) + if data[channel]["last roll"][0] == data[channel]["last roll"][1]: + turn = data[channel]["turn"] + else: + turn = (data[channel]["turn"] + 1)%len(data[channel]["player list"]) data[channel]["turn"] = turn playerList = list(data[channel]["players"].keys()) @@ -107,8 +115,17 @@ def monopolyRoll(channel,user): if user == currentPlayer: rolls = [random.randint(1,6),random.randint(1,6)] + message = getName(user)+" rolled a "+str(rolls[0])+" and a "+str(rolls[1])+"." + if rolls[0] == rolls[1]: + message += " Doubbles!" + roll = rolls[0] + rolls[1] - newPosition = (data[channel]["players"][user]["position"] + roll)%40 + oldPosition = data[channel]["players"][user]["position"] + newPosition = (oldPosition + roll)%40 + if newPosition < oldPosition: + data[channel]["players"][user]["money"] += rulesAndTerms["pass go money"] + message += "\nYou passed go and got "+str(rulesAndTerms["pass go money"])+" "+rulesAndTerms["money term"]+"." + data[channel]["players"][user]["position"] = newPosition data[channel]["last roll"] = rolls @@ -120,5 +137,5 @@ def monopolyRoll(channel,user): except: logThis("Error drawing board (error code 1640)") - return "Rolled a "+str(rolls[0])+" and a "+str(rolls[1])+".", True, True, False, True + return message, True, True, False, True else: return "", False, False, False, False diff --git a/gameLoops.py b/gameLoops.py index 893e737..b3ec204 100644 --- a/gameLoops.py +++ b/gameLoops.py @@ -212,7 +212,7 @@ async def runMonopoly(channel, command, user): if gameStarted: await asyncio.sleep(60) else: - await asyncio.sleep(5) + await asyncio.sleep(3) response, showImage, deleteImage, gameDone = monopolyContinue(str(channel.id)) em = discord.Embed(description=response,colour = 0x59f442) await channel.send(embed=em) diff --git a/resources/games/monopolyProperties/R1.png b/resources/games/monopolyProperties/R1.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ade6df9e87243f9582dca48b4ff72ae9f2ad44 GIT binary patch literal 39304 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 Date: Thu, 6 Aug 2020 15:20:26 +0200 Subject: [PATCH 20/26] :bug: --- cogs/GamesCog.py | 2 +- cogs/SwCog.py | 2 +- funcs/games/fourInARowDraw.py | 3 +-- funcs/games/money.py | 2 +- funcs/miscFuncs.py | 2 +- gameLoops.py | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py index 1692dea..0cb2eb9 100644 --- a/cogs/GamesCog.py +++ b/cogs/GamesCog.py @@ -21,7 +21,7 @@ class GamesCog(commands.Cog): else: new_message = ctx.message.author.display_name + " has " + str(response) + " GwendoBucks" await ctx.send(new_message) - + # Gives another user an amount of GwendoBucks @commands.command() async def give(self, ctx, *, content): diff --git a/cogs/SwCog.py b/cogs/SwCog.py index c13e93b..0bf9af0 100644 --- a/cogs/SwCog.py +++ b/cogs/SwCog.py @@ -9,7 +9,7 @@ class SwCog(commands.Cog): def __init__(self,client): self.client = client - + # Rolls star wars dice @commands.command() async def swroll(self, ctx, *, content): diff --git a/funcs/games/fourInARowDraw.py b/funcs/games/fourInARowDraw.py index fddef65..fdc6ad8 100644 --- a/funcs/games/fourInARowDraw.py +++ b/funcs/games/fourInARowDraw.py @@ -121,8 +121,7 @@ def drawImage(channel): winBar = winBar.rotate(diagonalAngle,expand=1) startx -= placeGridSize[0]*3 + border starty -= gridBorder + border - - + mask = winBar.copy()#.convert("L") #mask.putalpha(128) #mask.save("test.png") diff --git a/funcs/games/money.py b/funcs/games/money.py index 14d1167..dfa854f 100644 --- a/funcs/games/money.py +++ b/funcs/games/money.py @@ -24,7 +24,7 @@ def addMoney(user,amount): data[user]["money"] = points + amount else: logThis("Error adding money") - + with open("resources/users.json", "w") as f: json.dump(data,f,indent=4) diff --git a/funcs/miscFuncs.py b/funcs/miscFuncs.py index cf528c8..bf223ed 100644 --- a/funcs/miscFuncs.py +++ b/funcs/miscFuncs.py @@ -165,7 +165,7 @@ def makeFolder(path): def makeFiles(): with open("resources/startingFiles.json") as f: data = json.load(f) - + for path, content in data["json"].items(): makeJsonFile(path,content) diff --git a/gameLoops.py b/gameLoops.py index b3ec204..ac400be 100644 --- a/gameLoops.py +++ b/gameLoops.py @@ -207,7 +207,7 @@ async def runMonopoly(channel, command, user): oldImage = await channel.send(file = discord.File("resources/games/monopolyBoards/monopolyBoard"+str(channel.id)+".png")) with open("resources/games/oldImages/monopoly"+str(channel.id), "w") as f: f.write(str(oldImage.id)) - + if gameContinue: if gameStarted: await asyncio.sleep(60) From 23f56f9f0e16fe2bcaf0714f58f8b8d74c0d34a8 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 15:22:18 +0200 Subject: [PATCH 21/26] :bug: --- funcs/games/money.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/funcs/games/money.py b/funcs/games/money.py index dfa854f..d6767c7 100644 --- a/funcs/games/money.py +++ b/funcs/games/money.py @@ -32,7 +32,7 @@ def addMoney(user,amount): def giveMoney(user,targetUser,amount): with open("resources/users.json", "r") as f: data = json.load(f) - + targetUser = getID(targetUser) if amount > 0: From 3cb00381e7aa0852932ed67a2bf844a1c06818d9 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 15:32:30 +0200 Subject: [PATCH 22/26] :bug: --- cogs/GamesCog.py | 1 - cogs/LookupCog.py | 1 - cogs/MiscCog.py | 1 - cogs/ReactionCog.py | 1 - cogs/SwCog.py | 1 - 5 files changed, 5 deletions(-) diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py index 0cb2eb9..63222f5 100644 --- a/cogs/GamesCog.py +++ b/cogs/GamesCog.py @@ -6,7 +6,6 @@ from funcs import logThis, triviaAnswer, triviaCountPoints, triviaStart, deleteG from gameLoops import blackjackLoop, fiar, runMonopoly, runHex class GamesCog(commands.Cog): - """Cog for game functions""" def __init__(self,client): diff --git a/cogs/LookupCog.py b/cogs/LookupCog.py index 55e3e0d..b461617 100644 --- a/cogs/LookupCog.py +++ b/cogs/LookupCog.py @@ -4,7 +4,6 @@ from discord.ext import commands from funcs import spellFunc, monsterFunc, cap class LookupCog(commands.Cog): - """Cog for lookup functions""" def __init__(self,client): diff --git a/cogs/MiscCog.py b/cogs/MiscCog.py index ca23d8f..3ce99e8 100644 --- a/cogs/MiscCog.py +++ b/cogs/MiscCog.py @@ -4,7 +4,6 @@ from discord.ext import commands from funcs import logThis, stopServer, helloFunc, roll_dice, imageFunc, nameGen, tavernGen, movieFunc, cap, findWikiPage class MiscCog(commands.Cog): - """Cog for misc functions""" def __init__(self,client): diff --git a/cogs/ReactionCog.py b/cogs/ReactionCog.py index 7ccb35b..3537fa5 100644 --- a/cogs/ReactionCog.py +++ b/cogs/ReactionCog.py @@ -4,7 +4,6 @@ from funcs import logThis, fiarReactionTest, monopolyReactionTest, emojiToComman from gameLoops import fiar, runMonopoly class ReactionCog(commands.Cog): - """Cog for reactions""" def __init__(self, client): diff --git a/cogs/SwCog.py b/cogs/SwCog.py index 0bf9af0..e80caa6 100644 --- a/cogs/SwCog.py +++ b/cogs/SwCog.py @@ -4,7 +4,6 @@ from discord.ext import commands from funcs import parseRoll, parseDestiny, critRoll, parseChar, cap class SwCog(commands.Cog): - """Cog for Star Wars functions""" def __init__(self,client): From ebeca603059bd64d25fc95f90f3b9eeb7f14d6db Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 15:36:51 +0200 Subject: [PATCH 23/26] :bug: --- cogs/GamesCog.py | 1 - cogs/LookupCog.py | 1 - cogs/MiscCog.py | 3 +-- cogs/ReactionCog.py | 2 -- cogs/SwCog.py | 1 - 5 files changed, 1 insertion(+), 7 deletions(-) diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py index 63222f5..c869a25 100644 --- a/cogs/GamesCog.py +++ b/cogs/GamesCog.py @@ -6,7 +6,6 @@ from funcs import logThis, triviaAnswer, triviaCountPoints, triviaStart, deleteG from gameLoops import blackjackLoop, fiar, runMonopoly, runHex class GamesCog(commands.Cog): - """Cog for game functions""" def __init__(self,client): self.client = client diff --git a/cogs/LookupCog.py b/cogs/LookupCog.py index b461617..bd277f0 100644 --- a/cogs/LookupCog.py +++ b/cogs/LookupCog.py @@ -4,7 +4,6 @@ from discord.ext import commands from funcs import spellFunc, monsterFunc, cap class LookupCog(commands.Cog): - """Cog for lookup functions""" def __init__(self,client): self.client = client diff --git a/cogs/MiscCog.py b/cogs/MiscCog.py index 3ce99e8..6f9fb66 100644 --- a/cogs/MiscCog.py +++ b/cogs/MiscCog.py @@ -4,7 +4,6 @@ from discord.ext import commands from funcs import logThis, stopServer, helloFunc, roll_dice, imageFunc, nameGen, tavernGen, movieFunc, cap, findWikiPage class MiscCog(commands.Cog): - """Cog for misc functions""" def __init__(self,client): self.client = client @@ -61,7 +60,7 @@ class MiscCog(commands.Cog): @commands.command(name="map") async def mapCommand(self, ctx): await ctx.send("https://i.imgur.com/diMXXJs.jpg") - + # Sends a random image @commands.command(aliases = ["img"]) async def image(self, ctx): diff --git a/cogs/ReactionCog.py b/cogs/ReactionCog.py index 3537fa5..0313188 100644 --- a/cogs/ReactionCog.py +++ b/cogs/ReactionCog.py @@ -4,8 +4,6 @@ from funcs import logThis, fiarReactionTest, monopolyReactionTest, emojiToComman from gameLoops import fiar, runMonopoly class ReactionCog(commands.Cog): - """Cog for reactions""" - def __init__(self, client): self.client = client diff --git a/cogs/SwCog.py b/cogs/SwCog.py index e80caa6..5dc7890 100644 --- a/cogs/SwCog.py +++ b/cogs/SwCog.py @@ -4,7 +4,6 @@ from discord.ext import commands from funcs import parseRoll, parseDestiny, critRoll, parseChar, cap class SwCog(commands.Cog): - """Cog for Star Wars functions""" def __init__(self,client): self.client = client From 5c881f17c9125145af8d9e60e904b828a6dce224 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 15:42:31 +0200 Subject: [PATCH 24/26] :bug: --- cogs/GamesCog.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py index c869a25..3329345 100644 --- a/cogs/GamesCog.py +++ b/cogs/GamesCog.py @@ -8,6 +8,7 @@ from gameLoops import blackjackLoop, fiar, runMonopoly, runHex class GamesCog(commands.Cog): def __init__(self,client): + """Runs game stuff""" self.client = client # Checks user balance From 7712c901fca52452ff3a158e3a38cb438bb1b312 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 15:45:13 +0200 Subject: [PATCH 25/26] :bug: --- cogs/GamesCog.py | 2 +- cogs/LookupCog.py | 1 + cogs/MiscCog.py | 3 ++- cogs/ReactionCog.py | 1 + cogs/SwCog.py | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py index 3329345..c7ad7af 100644 --- a/cogs/GamesCog.py +++ b/cogs/GamesCog.py @@ -8,7 +8,7 @@ from gameLoops import blackjackLoop, fiar, runMonopoly, runHex class GamesCog(commands.Cog): def __init__(self,client): - """Runs game stuff""" + """Runs game stuff.""" self.client = client # Checks user balance diff --git a/cogs/LookupCog.py b/cogs/LookupCog.py index bd277f0..c69ffd1 100644 --- a/cogs/LookupCog.py +++ b/cogs/LookupCog.py @@ -6,6 +6,7 @@ from funcs import spellFunc, monsterFunc, cap class LookupCog(commands.Cog): def __init__(self,client): + """Runs lookup commands.""" self.client = client # Looks up a spell diff --git a/cogs/MiscCog.py b/cogs/MiscCog.py index 6f9fb66..8409a9c 100644 --- a/cogs/MiscCog.py +++ b/cogs/MiscCog.py @@ -6,6 +6,7 @@ from funcs import logThis, stopServer, helloFunc, roll_dice, imageFunc, nameGen, class MiscCog(commands.Cog): def __init__(self,client): + """Runs misc commands.""" self.client = client self.client.remove_command("help") @@ -66,7 +67,7 @@ class MiscCog(commands.Cog): async def image(self, ctx): randomImage = imageFunc() await ctx.send(randomImage) - + # Finds a random movie @commands.command() async def movie(self,ctx): diff --git a/cogs/ReactionCog.py b/cogs/ReactionCog.py index 0313188..a210757 100644 --- a/cogs/ReactionCog.py +++ b/cogs/ReactionCog.py @@ -5,6 +5,7 @@ from gameLoops import fiar, runMonopoly class ReactionCog(commands.Cog): def __init__(self, client): + """Listens for reactions.""" self.client = client @commands.Cog.listener() diff --git a/cogs/SwCog.py b/cogs/SwCog.py index 5dc7890..0507ecb 100644 --- a/cogs/SwCog.py +++ b/cogs/SwCog.py @@ -6,6 +6,7 @@ from funcs import parseRoll, parseDestiny, critRoll, parseChar, cap class SwCog(commands.Cog): def __init__(self,client): + """Runs star wars commands.""" self.client = client # Rolls star wars dice From 592ace1eb4d031414dde9cef775e3e2f16b76302 Mon Sep 17 00:00:00 2001 From: Nikolaj Danger Date: Thu, 6 Aug 2020 15:48:06 +0200 Subject: [PATCH 26/26] :bug: --- cogs/MiscCog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cogs/MiscCog.py b/cogs/MiscCog.py index 8409a9c..4718019 100644 --- a/cogs/MiscCog.py +++ b/cogs/MiscCog.py @@ -88,19 +88,19 @@ class MiscCog(commands.Cog): @commands.command() async def name(self, ctx): await ctx.send(nameGen()) - + # Generates a random tavern name @commands.command() async def tavern(self, ctx): await ctx.send(tavernGen()) - + # Sets the game Gwendolyn's playing @commands.command() async def game(self, ctx, *, content): gamePlaying = cap(content) game = discord.Game(gamePlaying) await self.client.change_presence(activity=game) - + # Finds a page on the Senkulpa wiki @commands.command(aliases = ["wikia"]) async def wiki(self, ctx, *, content):