From 646749acb178f24ad16b771f9cc934ebf6a72c71 Mon Sep 17 00:00:00 2001 From: jona605a Date: Fri, 28 Aug 2020 23:11:19 +0200 Subject: [PATCH 1/4] :love_letter: Started on Love letter --- cogs/GamesCog.py | 5 ++ funcs/games/gameLoops.py | 41 ++++++++++++++- funcs/games/loveletter.py | 96 +++++++++++++++++++++++++++++++++++ funcs/games/loveletterDraw.py | 15 ++++++ resources/errorCodes.txt | 4 ++ 5 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 funcs/games/loveletter.py create mode 100644 funcs/games/loveletterDraw.py diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py index a8b8dab..86ecdff 100644 --- a/cogs/GamesCog.py +++ b/cogs/GamesCog.py @@ -100,5 +100,10 @@ class GamesCog(commands.Cog): async def hexCommand(self, ctx, *, content = ""): await self.client.gameLoops.runHex(ctx.message.channel,content,"#"+str(ctx.message.author.id)) + # Runs a game of Love Letter + @commands.command(aliases = ["ll"]) + async def loveletter(self, ctx, *, content = ""): + await self.client.gameLoops.runLoveletter(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/funcs/games/gameLoops.py b/funcs/games/gameLoops.py index 4a558bf..08066eb 100644 --- a/funcs/games/gameLoops.py +++ b/funcs/games/gameLoops.py @@ -203,11 +203,48 @@ class GameLoops(): f.write(str(oldImage.id)) if gameDone: - game = self.bot.database["hexGames"].find_one({"_id":str(channel.id)}) - print(game) + game = self.bot.database["hex games"].find_one({"_id":str(channel.id)}) + winner = game["winner"] if winner != 0 and game["players"][0] != game["players"][1]: # player1 != player2 winnings = game["difficulty"]*10 self.bot.money.addMoney(game["players"][winner-1].lower(),winnings) self.bot.funcs.deleteGame("hex games",str(channel.id)) + + + # Runs Love letter + + async def runLoveletter(self,channel,command,user): + try: + response, showImage, deleteImage = self.bot.hex.parseLove(command,str(channel.id),user) + except: + logThis("Error parsing command (error code 1810)") + + await channel.send(response) + logThis(response,str(channel.id)) + if showImage: + if deleteImage: + await self.deleteMessage("loveletter"+str(channel.id),channel) + oldImage = await channel.send(file = discord.File("resources/games/loveletterBoards/loveletterBoard"+str(channel.id)+".png")) + + if len(remainingLetters) > 15: + otherMessage = await channel.send("_ _") + reactionMessages = {oldImage : remainingLetters[:15],otherMessage : remainingLetters[15:]} + else: + otherMessage = "" + reactionMessages = {oldImage : remainingLetters} + + oldMessages = str(oldImage.id) + if otherMessage != "": + oldMessages += "\n"+str(otherMessage.id) + with open("resources/games/oldImages/hangman"+str(channel.id), "w") as f: + f.write(oldMessages) + + try: + for message, letters in reactionMessages.items(): + for letter in letters: + emoji = chr(ord(letter)+127397) + await message.add_reaction(emoji) + except: + logThis("Image deleted before adding all reactions") \ No newline at end of file diff --git a/funcs/games/loveletter.py b/funcs/games/loveletter.py new file mode 100644 index 0000000..6281fc0 --- /dev/null +++ b/funcs/games/loveletter.py @@ -0,0 +1,96 @@ +import random + +from funcs import logThis +from .loveletterDraw import DrawLove + +class HexGame(): + def __init__(self,bot): + self.bot = bot + self.draw = DrawHex(bot) + + # Parses command + def parseLove(self, command, channel, user): + commands = command.lower().split() + game = self.bot.database["loveletter games"].find_one({"_id":channel}) + + if command == "" or command == " ": + logThis(str(user)+"started a Love Letter game with loveStart(). "+) + return self.loveStart(channel,user,commands[1]) # commands[1] is the opponent + + elif commands[0] == "start": + # Starting a game + if len(commands) == 1: # if the commands is "!hex start", the opponent is Gwendolyn at difficulty 2 + commands.append("2") + logThis("Starting a hex game with hexStart(). "+str(user)+" challenged "+commands[1]) + return self.hexStart(channel,user,commands[1]) # commands[1] is the opponent + + # If using a command with no game, return error + elif game == None: + return "There's no game in this channel", False, False, False, False + + # Stopping the game + elif commands[0] == "stop": + if user in game["players"]: + return "Ending game.", False, False, True, False + else: + return "You can't end a game where you're not a player.", False, False, False, False + + # Placing a piece + elif commands[0] == "place": + try: + return self.placeHex(channel,commands[1], user) + except: + return "I didn't get that. To place a piece use \"!hex place [position]\". A valid position is e.g. \"E2\".", False, False, False, False + + # Undo + elif commands[0] == "undo": + return self.undoHex(channel, user) + + # Surrender + elif commands[0] == "surrender": + players = game["players"] + if user in players: + opponent = (players.index(user) + 1) % 2 + self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"winner":opponent + 1}}) + return "{} surrendered. That means {} won! Adding 30 Gwendobucks to their account.".format(self.bot.funcs.getName(user),self.bot.funcs.getName(players[opponent])), False, False, True, False + else: + return "You can't surrender when you're not a player.", False, False, False, False + + # Swap + elif commands[0] == "swap": + if len(game["gameHistory"]) == 1: # Only after the first move + self.bot.database["hex games"].update_one({"_id":channel}, + {"$set":{"players":game["players"][::-1]}}) # Swaps their player-number + + # Swaps the color of the hexes on the board drawing: + self.draw.drawSwap(channel) + player2 = game["players"][1] + gwendoTurn = (player2 == "Gwendolyn") + return "The color of both players were swapped. It is now {}'s turn".format(player2), True, True, False, gwendoTurn + else: + return "You can only swap as the second player after the very first move.", False, False, False, False + + else: + return "I didn't get that. Use \"!hex start [opponent]\" to start a game, \"!hex place [position]\" to place a piece, \"!hex undo\" to undo your last move or \"!hex stop\" to stop a current game.", False, False, False, False + + # Starts the game + def loveStart(self, channel, user, opponent): + game = self.bot.database["loveletter games"].find_one({"_id":channel}) + + if game == None: + + + deck = [1,1,1,1,1, 2,2, 3,3, 4,4, 5,5, 6, 7, 8] + random.shuffle(deck) + cardAside = deck[0] + del deck[0] # The card that is set aside + + newGame = {"_id":channel,"user hands": {},"discard piles":{},"deck":deck,"round":0,"cardAside":cardAside} + + self.bot.database["loveletter games"].insert_one(newGame) + + return "" + else: + logThis("There's already a Love Letter game going on in this channel",str(channel)) + return "There's already a Love Letter game going on in this channel" + diff --git a/funcs/games/loveletterDraw.py b/funcs/games/loveletterDraw.py new file mode 100644 index 0000000..51f4145 --- /dev/null +++ b/funcs/games/loveletterDraw.py @@ -0,0 +1,15 @@ +import math + +from PIL import Image, ImageDraw, ImageFont +from funcs import logThis + + + + + +class DrawLove(): + def __init__(self,bot): + self.bot = bot + + def drawBoard(self, channel): + logThis("Drawing empty Hex board") diff --git a/resources/errorCodes.txt b/resources/errorCodes.txt index cbfec1c..317003d 100644 --- a/resources/errorCodes.txt +++ b/resources/errorCodes.txt @@ -137,3 +137,7 @@ 1714 - Error in drawMisses() 1720 - Unspecified hangmanGuess() error 1730 - Unspecified hangmanStart() error + +18 - Love Letter +1800 - Unspecified error +1801 - Error parsing command \ No newline at end of file From d57673e1963755cdf5b0a67c0d85a7de9110fb4d Mon Sep 17 00:00:00 2001 From: jona605a Date: Sun, 30 Aug 2020 22:48:51 +0200 Subject: [PATCH 2/4] :love_letter: --- funcs/games/loveletter.py | 90 ++++++++++++++++----------------------- resources/errorCodes.txt | 2 +- 2 files changed, 38 insertions(+), 54 deletions(-) diff --git a/funcs/games/loveletter.py b/funcs/games/loveletter.py index 6281fc0..4bc3a03 100644 --- a/funcs/games/loveletter.py +++ b/funcs/games/loveletter.py @@ -3,10 +3,10 @@ import random from funcs import logThis from .loveletterDraw import DrawLove -class HexGame(): +class LoveLetter(): def __init__(self,bot): self.bot = bot - self.draw = DrawHex(bot) + self.draw = DrawLove(bot) # Parses command def parseLove(self, command, channel, user): @@ -14,67 +14,51 @@ class HexGame(): game = self.bot.database["loveletter games"].find_one({"_id":channel}) if command == "" or command == " ": - logThis(str(user)+"started a Love Letter game with loveStart(). "+) - return self.loveStart(channel,user,commands[1]) # commands[1] is the opponent - - elif commands[0] == "start": - # Starting a game - if len(commands) == 1: # if the commands is "!hex start", the opponent is Gwendolyn at difficulty 2 - commands.append("2") - logThis("Starting a hex game with hexStart(). "+str(user)+" challenged "+commands[1]) - return self.hexStart(channel,user,commands[1]) # commands[1] is the opponent + logThis(str(user)+" started a Love Letter game with loveStart(). ") + return self.loveStart(channel) # If using a command with no game, return error elif game == None: - return "There's no game in this channel", False, False, False, False + return "There's no game in this channel", False, False + + # Joining the game + elif commands[0] == "join": + if game["round"] == 0: + if user not in game["player hands"]: + # Deal cards + card = game["deck"].pop() + username = self.bot.funcs.getName(user) + game["player hands"][username] = card + game["discard piles"][username] = [] + self.bot.database["loveletter games"].replace_one({"_id":channel},game) + return username+" joined the game! Type \"!loveletter begin\" once all players have joined.", False, False + else: + return "You're already playing!", False, False + else: + return "It's too late to join", False, False + + # Beginning the game + elif commands[0] == "begin": + if user in game["player hands"]: + if len(game["player hands"]) > 1: + pass + else: + return "AI functionality hasn't been implemented yet. Get another player to join!", False, False + else: + return "You can't begin a game, when you're not a player!", False, False # Stopping the game elif commands[0] == "stop": - if user in game["players"]: - return "Ending game.", False, False, True, False + if user in game["player hands"]: + return "Ending game.", False, False else: - return "You can't end a game where you're not a player.", False, False, False, False - - # Placing a piece - elif commands[0] == "place": - try: - return self.placeHex(channel,commands[1], user) - except: - return "I didn't get that. To place a piece use \"!hex place [position]\". A valid position is e.g. \"E2\".", False, False, False, False - - # Undo - elif commands[0] == "undo": - return self.undoHex(channel, user) - - # Surrender - elif commands[0] == "surrender": - players = game["players"] - if user in players: - opponent = (players.index(user) + 1) % 2 - self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"winner":opponent + 1}}) - return "{} surrendered. That means {} won! Adding 30 Gwendobucks to their account.".format(self.bot.funcs.getName(user),self.bot.funcs.getName(players[opponent])), False, False, True, False - else: - return "You can't surrender when you're not a player.", False, False, False, False - - # Swap - elif commands[0] == "swap": - if len(game["gameHistory"]) == 1: # Only after the first move - self.bot.database["hex games"].update_one({"_id":channel}, - {"$set":{"players":game["players"][::-1]}}) # Swaps their player-number - - # Swaps the color of the hexes on the board drawing: - self.draw.drawSwap(channel) - player2 = game["players"][1] - gwendoTurn = (player2 == "Gwendolyn") - return "The color of both players were swapped. It is now {}'s turn".format(player2), True, True, False, gwendoTurn - else: - return "You can only swap as the second player after the very first move.", False, False, False, False + return "You can't end a game where you're not a player.", False, False else: - return "I didn't get that. Use \"!hex start [opponent]\" to start a game, \"!hex place [position]\" to place a piece, \"!hex undo\" to undo your last move or \"!hex stop\" to stop a current game.", False, False, False, False + return "I didn't get that. Use \"!loveletter\" to start a game or \"!loveletter join\" to join a game. ", False, False # Starts the game - def loveStart(self, channel, user, opponent): + def loveStart(self, channel): game = self.bot.database["loveletter games"].find_one({"_id":channel}) if game == None: @@ -85,7 +69,7 @@ class HexGame(): cardAside = deck[0] del deck[0] # The card that is set aside - newGame = {"_id":channel,"user hands": {},"discard piles":{},"deck":deck,"round":0,"cardAside":cardAside} + newGame = {"_id":channel,"player hands": {},"discard piles":{},"deck":deck,"round":0,"cardAside":cardAside} self.bot.database["loveletter games"].insert_one(newGame) diff --git a/resources/errorCodes.txt b/resources/errorCodes.txt index 317003d..bd33632 100644 --- a/resources/errorCodes.txt +++ b/resources/errorCodes.txt @@ -140,4 +140,4 @@ 18 - Love Letter 1800 - Unspecified error -1801 - Error parsing command \ No newline at end of file +1801 - Error parsing command From 3fb2da1c0e5183304a049fe2a7c5e4ba4112c700 Mon Sep 17 00:00:00 2001 From: jona605a Date: Thu, 3 Sep 2020 16:10:00 +0200 Subject: [PATCH 3/4] :bug: --- funcs/games/hex.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/funcs/games/hex.py b/funcs/games/hex.py index 74a76d1..dbdf5e5 100644 --- a/funcs/games/hex.py +++ b/funcs/games/hex.py @@ -231,8 +231,9 @@ class HexGame(): logThis("Undoing {}'s last move".format(self.bot.funcs.getName(user))) lastMove = game["gameHistory"].pop() + game["board"][lastMove[0]][lastMove[1]] = 0 self.bot.database["hex games"].update_one({"_id":channel}, - {"$set":{"board."+lastMove[0]+"."+lastMove[1]:0}}) + {"$set":{"board":game["board"]}}) self.bot.database["hex games"].update_one({"_id":channel}, {"$set":{"turn":turn%2 + 1}}) From dcd37206bcd4eaff6c9f79504aefff5161ff747e Mon Sep 17 00:00:00 2001 From: jona605a Date: Fri, 25 Sep 2020 19:00:58 +0200 Subject: [PATCH 4/4] :sparkles: --- cogs/GamesCog.py | 2 +- funcs/games/gameLoops.py | 6 +++--- funcs/games/hex.py | 1 - funcs/games/loveletter.py | 5 +++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cogs/GamesCog.py b/cogs/GamesCog.py index 86ecdff..6d44d6d 100644 --- a/cogs/GamesCog.py +++ b/cogs/GamesCog.py @@ -103,7 +103,7 @@ class GamesCog(commands.Cog): # Runs a game of Love Letter @commands.command(aliases = ["ll"]) async def loveletter(self, ctx, *, content = ""): - await self.client.gameLoops.runLoveletter(ctx.message.channel,content,"#"+str(ctx.message.author.id)) + await self.client.gameLoops.runLoveletter(ctx.message.channel,content,"#"+str(ctx.message.author.id),ctx.message.author) def setup(client): client.add_cog(GamesCog(client)) \ No newline at end of file diff --git a/funcs/games/gameLoops.py b/funcs/games/gameLoops.py index 08066eb..fdafa77 100644 --- a/funcs/games/gameLoops.py +++ b/funcs/games/gameLoops.py @@ -176,6 +176,7 @@ class GameLoops(): logThis("Error parsing command (error code 1510)") await channel.send(response) + logThis(response,str(channel.id)) if showImage: if deleteImage: @@ -214,10 +215,9 @@ class GameLoops(): # Runs Love letter - - async def runLoveletter(self,channel,command,user): + async def runLoveletter(self,channel,command,user,userchannel): try: - response, showImage, deleteImage = self.bot.hex.parseLove(command,str(channel.id),user) + response, showImage, deleteImage = self.bot.loveletter.parseLove(command,str(channel.id),user,userchannel) except: logThis("Error parsing command (error code 1810)") diff --git a/funcs/games/hex.py b/funcs/games/hex.py index dbdf5e5..4fc819c 100644 --- a/funcs/games/hex.py +++ b/funcs/games/hex.py @@ -22,7 +22,6 @@ class HexGame(): def parseHex(self, command, channel, user): commands = command.lower().split() game = self.bot.database["hex games"].find_one({"_id":channel}) - if command == "" or command == " ": return "I didn't get that. Use \"!hex start [opponent]\" to start a game.", False, False, False, False diff --git a/funcs/games/loveletter.py b/funcs/games/loveletter.py index 4bc3a03..b42a88e 100644 --- a/funcs/games/loveletter.py +++ b/funcs/games/loveletter.py @@ -9,12 +9,12 @@ class LoveLetter(): self.draw = DrawLove(bot) # Parses command - def parseLove(self, command, channel, user): + def parseLove(self, command, channel, user, userchannel): commands = command.lower().split() game = self.bot.database["loveletter games"].find_one({"_id":channel}) if command == "" or command == " ": - logThis(str(user)+" started a Love Letter game with loveStart(). ") + logThis(str(user)+" created a Love Letter game with loveStart(). ") return self.loveStart(channel) # If using a command with no game, return error @@ -30,6 +30,7 @@ class LoveLetter(): username = self.bot.funcs.getName(user) game["player hands"][username] = card game["discard piles"][username] = [] + game["user channel"][username] = userchannel # Used for direct (private) messages to the users self.bot.database["loveletter games"].replace_one({"_id":channel},game) return username+" joined the game! Type \"!loveletter begin\" once all players have joined.", False, False else: