from converters.numbers import Abbreviated, abbreviated from decorators import help import discord from discord.ext import commands from enums.help_categories import Category from functions import checks, dinks from functions.database import currency, stats import json import math import random class Games(commands.Cog): def __init__(self, client): self.client = client # Don't allow any commands to work when locked def cog_check(self, ctx): return not self.client.locked @commands.group(name="Coinflip", aliases=["Cf"], usage="[Inzet]* [Aantal]*", case_insensitive=True, invoke_without_command=True) @commands.check(checks.allowedChannels) @help.Category(category=Category.Gamble) async def coinflip(self, ctx, *args): """ Command to flip a coin, optionally for Didier Dinks. :param ctx: Discord Context :param args: bet & wager """ args = list(args) choices = ["Kop", "Munt"] result = random.choice(choices) # No choice made & no wager if len(args) == 0: await ctx.send("**{}**!".format(result)) self.updateStats("cf", "h" if result == "Kop" else "t") return # Check for invalid args if len(args) == 1 or args[0][0].lower() not in "kmht": return await ctx.send("Controleer je argumenten.") args[1] = abbreviated(args[1]) valid = checks.isValidAmount(ctx, args[1]) # Invalid amount if not valid[0]: return await ctx.send(valid[1]) # Allow full words, abbreviations, and English alternatives args[0] = "k" if args[0][0].lower() == "k" or args[0][0].lower() == "h" else "m" won = await self.gamble(ctx, args[0], result, valid[1], 2) if won: s = stats.getOrAddUser(ctx.author.id) stats.update(ctx.author.id, "cf_wins", int(s[8]) + 1) stats.update(ctx.author.id, "cf_profit", float(s[9]) + float(valid[1])) self.updateStats("cf", "h" if result == "Kop" else "t") @coinflip.command(name="Stats", hidden=True) async def cf_stats(self, ctx): return await self.client.get_cog("Stats").callStats("cf", ctx) @commands.group(name="Dice", aliases=["Roll"], usage="[Inzet]* [Aantal]*", case_insensitive=True, invoke_without_command=True) @commands.check(checks.allowedChannels) @help.Category(category=Category.Gamble) async def dice(self, ctx, *args): """ Command to roll a dice, optionally for Didier Dinks. :param ctx: Discord Context :param args: bet & wager """ args = list(args) result = random.randint(1, 6) # No choice made & no wager if len(args) == 0: self.updateStats("dice", result) return await ctx.send(":game_die: **{}**!".format(result)) # Check for invalid args if len(args) == 1 or not args[0].isdigit() or not 0 < int(args[0]) < 7: return await ctx.send("Controleer je argumenten.") args[1] = abbreviated(args[1]) valid = checks.isValidAmount(ctx, args[1]) # Invalid amount if not valid[0]: return await ctx.send(valid[1]) await self.gamble(ctx, args[0], str(result), valid[1], 6, ":game_die: ") self.updateStats("dice", result) @dice.command(name="Stats", hidden=True) async def dice_stats(self, ctx): await self.client.get_cog("Stats").callStats("dice", ctx) async def gamble(self, ctx, bet, result, wager, factor, pre="", post=""): """ Function for gambling because it's the same thing every time. :param ctx: Discord Context :param bet: the option the user bet on :param result: randomly generated result :param wager: size of the bet of the user :param factor: the factor by which the person's wager is amplified :param pre: any string that might have to be pre-pended to the output string :param post: any string that might have to be appended to the output string :return: a boolean indicating whether or not the user has won """ # Code no longer first removes your bet to then add profit, # resulting in triple coinflip profit (@Clement). # Subtract one off of the factor to compensate for the initial wager factor -= 1 answer = "**{}**! ".format(result) won = False # Check if won if result[0].lower() == bet[0].lower(): won = True answer += "Je wint **{:,}** Didier Dink{}" currency.update(ctx.author.id, "dinks", float(currency.dinks(ctx.author.id)) + (float(wager) * factor)) else: answer += "Je hebt je inzet (**{:,}** Didier Dink{}) verloren" currency.update(ctx.author.id, "dinks", float(currency.dinks(ctx.author.id)) - float(wager)) self.loseDinks(round(float(wager))) # If won -> multiple dinkS, if lost, it's possible that the user only bet on 1 dinK await ctx.send(pre + answer.format(round(float(wager) * factor if won else float(wager)), checks.pluralS(float(wager) * factor if won else float(wager))) + ", **{}**!".format(ctx.author.display_name)) return won @commands.group(name="Slots", usage="[Aantal]", case_insensitive=True, invoke_without_command=True) @commands.check(checks.allowedChannels) @help.Category(category=Category.Gamble) async def slots(self, ctx, wager: Abbreviated = None): """ Command to play slot machines. :param ctx: Discord Context :param wager: the amount of Didier Dinks to bet with """ valid = checks.isValidAmount(ctx, wager) # Invalid amount if not valid[0]: return await ctx.send(valid[1]) ratios = dinks.getRatios() def randomKey(): return random.choice(list(ratios.keys())) def generateResults(): return [randomKey(), randomKey(), randomKey()] # Generate the result result = generateResults() textFormatted = "{}\n{}\n:yellow_square:{}:yellow_square:\n:arrow_right:{}:arrow_left::part_alternation_mark:\n" \ ":yellow_square:{}:yellow_square: :red_circle:\n{}\n{}".format( dinks.slotsHeader, dinks.slotsEmptyRow, "".join(generateResults()), "".join(result), "".join(generateResults()), dinks.slotsEmptyRow, dinks.slotsFooter) await ctx.send(textFormatted) # Everything different -> no profit if len(set(result)) == 3: await ctx.send("Je hebt je inzet (**{:,}** Didier Dinks) verloren, **{}**.".format( math.floor(float(valid[1])), ctx.author.display_name )) currency.update(ctx.author.id, "dinks", float(currency.dinks(ctx.author.id)) - math.floor(float(valid[1]))) return # Calculate the profit multiplier multiplier = 1.0 for symbol in set(result): multiplier *= ratios[symbol][result.count(symbol) - 1] await ctx.send(":moneybag: Je wint **{:,}** Didier Dinks, **{}**! :moneybag:".format( round(float(valid[1]) * multiplier, 2), ctx.author.display_name )) currency.update(ctx.author.id, "dinks", float(currency.dinks(ctx.author.id)) + (float(valid[1]) * multiplier) - math.floor( float(valid[1]))) # Current Dinks - wager + profit # Returns list of profits @slots.command(name="Chart", aliases=["Symbols", "Profit"]) async def chart(self, ctx): """ Command to show the profit distributions for the Didier Slotmachines. :param ctx: Discord Context """ embed = discord.Embed(colour=discord.Colour.blue()) embed.set_author(name="Slots Profit Chart") ratios = dinks.getRatios() # Add every symbol into the embed for ratio in ratios: embed.add_field(name=ratio, value="1: x{}\n2: x{}\n3: x{}".format( str(ratios[ratio][0]), str(ratios[ratio][1]), str(ratios[ratio][2]) )) await ctx.send(embed=embed) @commands.group(name="Lost", case_insensitive=True, invoke_without_command=True) @commands.check(checks.allowedChannels) @help.Category(category=Category.Gamble) async def lost(self, ctx): """ Command that shows the amount of Didier Dinks that have been lost due to gambling. :param ctx: Discord Context """ await ctx.send("Er zijn al **{:,}** Didier Dinks verloren sinds 13/03/2020." .format(dinks.lost())) @lost.command(name="Today") async def today(self, ctx): """ Command that shows the amount of Didier Dinks lost today. :param ctx: Discord Context """ await ctx.send("Er zijn vandaag al **{:,}** Didier Dinks verloren." .format(dinks.lostToday())) def updateStats(self, game, key): """ Function to update the stats file for a game. :param game: the game to change the stats for :param key: the key in the game's dict to update """ with open("files/stats.json", "r") as fp: s = json.load(fp) s[game][str(key)] += 1 with open("files/stats.json", "w") as fp: json.dump(s, fp) def loseDinks(self, amount): """ Function that adds Didier Dinks to the lost file. :param amount: the amount of Didier Dinks lost """ with open("files/lost.json", "r") as fp: fc = json.load(fp) fc["lost"] = fc["lost"] + round(amount) fc["today"] = fc["today"] + round(amount) with open("files/lost.json", "w") as fp: json.dump(fc, fp) def setup(client): client.add_cog(Games(client))