diff --git a/.gitignore b/.gitignore index e09e81f..f1f852f 100644 --- a/.gitignore +++ b/.gitignore @@ -153,12 +153,14 @@ 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 resources/games/blackjackTables/ resources/games/oldImages/ resources/games/4InARowBoards/ +resources/games/monopolyBoards/ resources/lookup/monsters.json resources/lookup/spells.json resources/movies.txt diff --git a/Gwendolyn.py b/Gwendolyn.py index 96bc45b..4f590d8 100644 --- a/Gwendolyn.py +++ b/Gwendolyn.py @@ -1,587 +1,11 @@ -# -*- coding: utf-8 -*- +import discord, os -import discord -import asyncio -#import pickle -import codecs -import string -import json -import random -#import math -import os +from discord.ext import commands -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 gameLoops import fiar, blackjackLoop, runHex +from funcs import logThis, makeFiles 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)) - await message.channel.send("Couldn't find help.txt (error code 101)") - else: - command = content.replace(" ","-") - logThis("Looking for "+command+".txt",str(message.channel)) - 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)) - 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)) - 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)) - - # 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)) - 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)) - 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)) - 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)) - await message.channel.send("Something fucked up (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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - 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)) - - deleteGame("trivia questions",str(message.channel)) - - logThis("Time's up for the trivia question",str(message.channel)) - 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) - 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)) - await message.channel.send("I didn't understand that (error code 1101)") - except: - logThis("Something fucked up (error code 1100)",str(message.channel)) - 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)) - 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)) - 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)) - await message.channel.send("I didn't understand that (error code 1222)") - except: - logThis("Something fucked up (error code 1220)",str(message.channel)) - 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)+".txt"): - with open("resources/games/blackjackCards/"+str(message.channel)+".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)) - await message.channel.send("Shuffling the deck...") - - new_message = blackjackStart(str(message.channel)) - 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")) - - with open("resources/games/oldImages/blackjack"+str(message.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(message.channel)]["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"] - - # Loop of game rounds - if gamedone == False: - logThis("!blackjack calling blackjackLoop()",str(message.channel)) - await blackjackLoop(message.channel,1,gameID) - else: - new_message = blackjackFinish(str(message.channel)) - 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)) - response = "I didn't understand that" - else: - response = blackjackPlayerDrawHand(str(message.channel),"#"+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)) - else: - commands = content.split(" ") - try: - handNumber = int(commands[2]) - except: - handNumber = 0 - response = blackjackHit(str(message.channel),"#"+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)) - await blackjackLoop(message.channel,int(response[7:])+1,gameID) - except: - logThis("Something fucked up (error code 1320)",str(message.channel)) - 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),"#"+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) - - 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)) - await blackjackLoop(message.channel,int(response[7:])+1,gameID) - except: - logThis("Something fucked up (error code 1320)",str(message.channel)) - 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),"#"+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)) - await blackjackLoop(message.channel,int(roundDone[1:])+1,gameID) - except: - logThis("Something fucked up (error code 1320)",str(message.channel)) - - # Splitting hand - elif content.startswith("blackjack split"): - commands = content.split(" ") - try: - handNumber = int(commands[2]) - except: - handNumber = 0 - response, roundDone = blackjackSplit(str(message.channel),"#"+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)) - 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: - 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)) - logThis("Shuffling the blackjack deck...",str(message.channel)) - 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: - 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"): - try: - command = content.replace("fourinarow","") - await fiar(message.channel,command,"#"+str(message.author.id)) - except: - logThis("Something went wrong (error code 1400)") - - # 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)") - - # Not a command - else: - logThis("That's not a command (error code 001)",str(message.channel)) - 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() +client = commands.Bot(command_prefix=commandPrefix) # Logs in @client.event @@ -590,36 +14,39 @@ async def on_ready(): 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)) - 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)") +# Loads and unloads cogs - # 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)) - emoji = random.choice(["😠", "🖕", "👎"]) - await message.add_reaction(emoji) +@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_reaction_add(reaction,user): - if user.bot == False: - message = reaction.message - channel = message.channel - logThis(user.display_name+" reacted to a message",str(channel)) - fourInARowTheirTurn, piece = fiarReactionTest(channel,message,"#"+str(user.id)) +async def on_command(ctx): + logThis(f"{ctx.message.author.display_name} ran {ctx.message.content}") - if fourInARowTheirTurn: - place = emojiToNumber(reaction.emoji) - await fiar(channel," place "+str(piece)+" "+str(place),user.id) +# 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..c7ad7af --- /dev/null +++ b/cogs/GamesCog.py @@ -0,0 +1,268 @@ +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): + + def __init__(self,client): + """Runs game stuff.""" + 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("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("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("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("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("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..c69ffd1 --- /dev/null +++ b/cogs/LookupCog.py @@ -0,0 +1,69 @@ +import discord +from discord.ext import commands + +from funcs import spellFunc, monsterFunc, cap + +class LookupCog(commands.Cog): + + def __init__(self,client): + """Runs lookup commands.""" + 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..4718019 --- /dev/null +++ b/cogs/MiscCog.py @@ -0,0 +1,122 @@ +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): + + def __init__(self,client): + """Runs misc commands.""" + 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..a210757 --- /dev/null +++ b/cogs/ReactionCog.py @@ -0,0 +1,28 @@ +from discord.ext import commands + +from funcs import logThis, fiarReactionTest, monopolyReactionTest, emojiToCommand +from gameLoops import fiar, runMonopoly + +class ReactionCog(commands.Cog): + def __init__(self, client): + """Listens for reactions.""" + 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..0507ecb --- /dev/null +++ b/cogs/SwCog.py @@ -0,0 +1,51 @@ +import discord, string +from discord.ext import commands + +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 + @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/__init__.py b/funcs/__init__.py index a80ec3e..3fd867e 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", "hexAI", "addToDict", "getName", "getID"] +__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 @@ -13,4 +13,3 @@ from .other import nameGen, tavernGen, movieFunc from .roll import roll_dice from .swfuncs import parseChar, parseRoll, parseDestiny, critRoll - diff --git a/funcs/games/__init__.py b/funcs/games/__init__.py index 329d3f3..c5edc07 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","hexAI"] +__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 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..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) @@ -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/funcs/games/fourInARowDraw.py b/funcs/games/fourInARowDraw.py index ddbbc9e..fdc6ad8 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"] @@ -120,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") @@ -133,11 +133,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)) diff --git a/funcs/games/money.py b/funcs/games/money.py index 0ab8283..d6767c7 100644 --- a/funcs/games/money.py +++ b/funcs/games/money.py @@ -18,13 +18,13 @@ 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 else: logThis("Error adding money") - + with open("resources/users.json", "w") as f: json.dump(data,f,indent=4) @@ -32,11 +32,11 @@ 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: - if targetUser.startswith("#"): + if targetUser != None: if user in data: if data[user]["money"] >= amount: addMoney(user,-1 * amount) diff --git a/funcs/games/monopoly.py b/funcs/games/monopoly.py new file mode 100644 index 0000000..0d29a60 --- /dev/null +++ b/funcs/games/monopoly.py @@ -0,0 +1,141 @@ +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: + 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: + 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()) + + 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)] + 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] + 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 + + 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 message, 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..45fddd8 --- /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 <= 20: + y = math.floor(largeSpace/2) + 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) + 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 90fe08a..bf223ed 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() + with open("resources/startingFiles.json") as f: + data = json.load(f) - # 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() + for path, content in data["json"].items(): + makeJsonFile(path,content) - # 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["txt"].items(): + makeTxtFile(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() - - # 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): @@ -286,7 +186,7 @@ def replaceMultiple(mainString, toBeReplaces, newString): return mainString -def emojiToNumber(emoji): +def emojiToCommand(emoji): if emoji == "1️⃣": return 1 elif emoji == "2️⃣": @@ -301,21 +201,21 @@ def emojiToNumber(emoji): return 6 elif emoji == "7️⃣": return 7 + elif emoji == "🎲": + return "roll" else: return "" 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"] - 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]: + 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") @@ -323,16 +223,31 @@ def fiarReactionTest(channel,message,user): else: return False, 0 +def monopolyReactionTest(channel,message): + with open("resources/games/oldImages/monopoly"+str(channel.id), "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/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..03385d8 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): + 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 3c7d488..0000000 --- a/funcs/roll/errors.py +++ /dev/null @@ -1,162 +0,0 @@ -class AvraeException(Exception): - """A base exception class.""" - - def __init__(self, msg): - super().__init__(msg) - - -class NoCharacter(AvraeException): - """Raised when a user has no active character.""" - - def __init__(self): - 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.") diff --git a/gameLoops.py b/gameLoops.py index e8ef39f..ac400be 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): @@ -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️⃣"] @@ -119,48 +119,45 @@ 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: 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: @@ -174,21 +171,63 @@ 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.id),user) + except: + logThis("Error parsing command (error code 1610)") + if response != "": + await channel.send(response) + logThis(response,str(channel.id)) + if showImage: + if deleteImage: + try: + 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.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) + else: + await asyncio.sleep(3) + 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.id),channel) + except: + logThis("Error deleting message (error code 1601)") + 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: + 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 4876893..1e08b02 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 @@ -112,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 0000000..a7cb5c8 Binary files /dev/null and b/resources/games/monopolyBoard.png differ diff --git a/resources/games/monopolyBoards/monopolyBoardtest.png b/resources/games/monopolyBoards/monopolyBoardtest.png new file mode 100644 index 0000000..50d8787 Binary files /dev/null and b/resources/games/monopolyBoards/monopolyBoardtest.png differ diff --git a/resources/games/monopolyProperties/R1.png b/resources/games/monopolyProperties/R1.png new file mode 100644 index 0000000..f9ade6d Binary files /dev/null and b/resources/games/monopolyProperties/R1.png differ diff --git a/resources/games/monopolyProperties/R2.png b/resources/games/monopolyProperties/R2.png new file mode 100644 index 0000000..f9ade6d Binary files /dev/null and b/resources/games/monopolyProperties/R2.png differ diff --git a/resources/games/monopolyProperties/R3.png b/resources/games/monopolyProperties/R3.png new file mode 100644 index 0000000..f9ade6d Binary files /dev/null and b/resources/games/monopolyProperties/R3.png differ diff --git a/resources/games/monopolyProperties/Y1.png b/resources/games/monopolyProperties/Y1.png new file mode 100644 index 0000000..f9ade6d Binary files /dev/null and b/resources/games/monopolyProperties/Y1.png differ diff --git a/resources/games/monopolyProperties/Y2.png b/resources/games/monopolyProperties/Y2.png new file mode 100644 index 0000000..f9ade6d Binary files /dev/null and b/resources/games/monopolyProperties/Y2.png differ diff --git a/resources/games/monopolyProperties/Y3.png b/resources/games/monopolyProperties/Y3.png new file mode 100644 index 0000000..f9ade6d Binary files /dev/null and b/resources/games/monopolyProperties/Y3.png differ 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]". 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..85537f4 --- /dev/null +++ b/resources/startingFiles.json @@ -0,0 +1,82 @@ +{ + "json":{ + "resources/starWars/swcharacters.json" : {}, + "resources/games/hexGames.json": {}, + "resources/games/monopolyGames.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", + "resources/games/monopolyBoards" + ] +} \ No newline at end of file