didier/cogs/games.py

258 lines
9.9 KiB
Python
Raw Permalink Normal View History

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))