mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 11:18:54 -05:00
[Economy] Refactored slot machine, fixed [p]bank register (#538)
This commit is contained in:
parent
607f88cf75
commit
0330e4f221
259
cogs/economy.py
259
cogs/economy.py
@ -1,30 +1,33 @@
|
|||||||
import discord
|
import discord
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from cogs.utils.dataIO import dataIO
|
from cogs.utils.dataIO import dataIO
|
||||||
from collections import namedtuple, defaultdict
|
from collections import namedtuple, defaultdict, deque
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from random import randint
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from .utils import checks
|
from .utils import checks
|
||||||
from cogs.utils.chat_formatting import pagify, box
|
from cogs.utils.chat_formatting import pagify, box
|
||||||
|
from enum import Enum
|
||||||
from __main__ import send_cmd_help
|
from __main__ import send_cmd_help
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
import random
|
||||||
|
|
||||||
default_settings = {"PAYDAY_TIME": 300, "PAYDAY_CREDITS": 120,
|
default_settings = {"PAYDAY_TIME": 300, "PAYDAY_CREDITS": 120,
|
||||||
"SLOT_MIN": 5, "SLOT_MAX": 100, "SLOT_TIME": 0,
|
"SLOT_MIN": 5, "SLOT_MAX": 100, "SLOT_TIME": 0,
|
||||||
"REGISTER_CREDITS": 0}
|
"REGISTER_CREDITS": 0}
|
||||||
|
|
||||||
slot_payouts = """Slot machine payouts:
|
|
||||||
:two: :two: :six: Bet * 5000
|
|
||||||
:four_leaf_clover: :four_leaf_clover: :four_leaf_clover: +1000
|
|
||||||
:cherries: :cherries: :cherries: +800
|
|
||||||
:two: :six: Bet * 4
|
|
||||||
:cherries: :cherries: Bet * 3
|
|
||||||
|
|
||||||
Three symbols: +500
|
class EconomyError(Exception):
|
||||||
Two symbols: Bet * 2"""
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OnCooldown(EconomyError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidBid(EconomyError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BankError(Exception):
|
class BankError(Exception):
|
||||||
@ -51,6 +54,62 @@ class SameSenderAndReceiver(BankError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
NUM_ENC = "\N{COMBINING ENCLOSING KEYCAP}"
|
||||||
|
|
||||||
|
|
||||||
|
class SMReel(Enum):
|
||||||
|
cherries = "\N{CHERRIES}"
|
||||||
|
cookie = "\N{COOKIE}"
|
||||||
|
two = "\N{DIGIT TWO}" + NUM_ENC
|
||||||
|
flc = "\N{FOUR LEAF CLOVER}"
|
||||||
|
cyclone = "\N{CYCLONE}"
|
||||||
|
sunflower = "\N{SUNFLOWER}"
|
||||||
|
six = "\N{DIGIT SIX}" + NUM_ENC
|
||||||
|
mushroom = "\N{MUSHROOM}"
|
||||||
|
heart = "\N{HEAVY BLACK HEART}"
|
||||||
|
snowflake = "\N{SNOWFLAKE}"
|
||||||
|
|
||||||
|
PAYOUTS = {
|
||||||
|
(SMReel.two, SMReel.two, SMReel.six) : {
|
||||||
|
"payout" : lambda x: x * 2500 + x,
|
||||||
|
"phrase" : "JACKPOT! 226! Your bid has been multiplied * 2500!"
|
||||||
|
},
|
||||||
|
(SMReel.flc, SMReel.flc, SMReel.flc) : {
|
||||||
|
"payout" : lambda x: x + 1000,
|
||||||
|
"phrase" : "4LC! +1000!"
|
||||||
|
},
|
||||||
|
(SMReel.cherries, SMReel.cherries, SMReel.cherries) : {
|
||||||
|
"payout" : lambda x: x + 800,
|
||||||
|
"phrase" : "Three cherries! +800!"
|
||||||
|
},
|
||||||
|
(SMReel.two, SMReel.six) : {
|
||||||
|
"payout" : lambda x: x * 4 + x,
|
||||||
|
"phrase" : "2 6! Your bid has been multiplied * 4!"
|
||||||
|
},
|
||||||
|
(SMReel.cherries, SMReel.cherries) : {
|
||||||
|
"payout" : lambda x: x * 3 + x,
|
||||||
|
"phrase" : "Two cherries! Your bid has been multiplied * 3!"
|
||||||
|
},
|
||||||
|
"3 symbols" : {
|
||||||
|
"payout" : lambda x: x + 500,
|
||||||
|
"phrase" : "Three symbols! +500!"
|
||||||
|
},
|
||||||
|
"2 symbols" : {
|
||||||
|
"payout" : lambda x: x * 2 + x,
|
||||||
|
"phrase" : "Two consecutive symbols! Your bid has been multiplied * 2!"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
SLOT_PAYOUTS_MSG = ("Slot machine payouts:\n"
|
||||||
|
"{two.value} {two.value} {six.value} Bet * 2500\n"
|
||||||
|
"{flc.value} {flc.value} {flc.value} +1000\n"
|
||||||
|
"{cherries.value} {cherries.value} {cherries.value} +800\n"
|
||||||
|
"{two.value} {six.value} Bet * 4\n"
|
||||||
|
"{cherries.value} {cherries.value} Bet * 3\n\n"
|
||||||
|
"Three symbols: +500\n"
|
||||||
|
"Two symbols: Bet * 2".format(**SMReel.__dict__))
|
||||||
|
|
||||||
|
|
||||||
class Bank:
|
class Bank:
|
||||||
|
|
||||||
def __init__(self, bot, file_path):
|
def __init__(self, bot, file_path):
|
||||||
@ -248,17 +307,18 @@ class Economy:
|
|||||||
@_bank.command(pass_context=True, no_pm=True)
|
@_bank.command(pass_context=True, no_pm=True)
|
||||||
async def register(self, ctx):
|
async def register(self, ctx):
|
||||||
"""Registers an account at the Twentysix bank"""
|
"""Registers an account at the Twentysix bank"""
|
||||||
user = ctx.message.author
|
settings = self.settings[ctx.message.server.id]
|
||||||
|
author = ctx.message.author
|
||||||
credits = 0
|
credits = 0
|
||||||
if ctx.message.server.id in self.settings:
|
if ctx.message.server.id in self.settings:
|
||||||
credits = self.settings[ctx.message.server.id].get("REGISTER_CREDITS", 0)
|
credits = settings.get("REGISTER_CREDITS", 0)
|
||||||
try:
|
try:
|
||||||
account = self.bank.create_account(user)
|
account = self.bank.create_account(author, initial_balance=credits)
|
||||||
await self.bot.say("{} Account opened. Current balance: {}".format(
|
await self.bot.say("{} Account opened. Current balance: {}"
|
||||||
user.mention, account.balance))
|
"".format(author.mention, account.balance))
|
||||||
except AccountAlreadyExists:
|
except AccountAlreadyExists:
|
||||||
await self.bot.say("{} You already have an account at the"
|
await self.bot.say("{} You already have an account at the"
|
||||||
" Twentysix bank.".format(user.mention))
|
" Twentysix bank.".format(author.mention))
|
||||||
|
|
||||||
@_bank.command(pass_context=True)
|
@_bank.command(pass_context=True)
|
||||||
async def balance(self, ctx, user: discord.Member=None):
|
async def balance(self, ctx, user: discord.Member=None):
|
||||||
@ -451,95 +511,91 @@ class Economy:
|
|||||||
@commands.command()
|
@commands.command()
|
||||||
async def payouts(self):
|
async def payouts(self):
|
||||||
"""Shows slot machine payouts"""
|
"""Shows slot machine payouts"""
|
||||||
await self.bot.whisper(slot_payouts)
|
await self.bot.whisper(SLOT_PAYOUTS_MSG)
|
||||||
|
|
||||||
@commands.command(pass_context=True, no_pm=True)
|
@commands.command(pass_context=True, no_pm=True)
|
||||||
async def slot(self, ctx, bid: int):
|
async def slot(self, ctx, bid: int):
|
||||||
"""Play the slot machine"""
|
"""Play the slot machine"""
|
||||||
author = ctx.message.author
|
author = ctx.message.author
|
||||||
server = author.server
|
server = author.server
|
||||||
if not self.bank.account_exists(author):
|
settings = self.settings[server.id]
|
||||||
await self.bot.say("{} You need an account to use the slot machine. Type `{}bank register` to open one.".format(author.mention, ctx.prefix))
|
valid_bid = settings["SLOT_MIN"] <= bid and bid <= settings["SLOT_MAX"]
|
||||||
return
|
slot_time = settings["SLOT_TIME"]
|
||||||
if self.bank.can_spend(author, bid):
|
last_slot = self.slot_register.get(author.id)
|
||||||
if bid >= self.settings[server.id]["SLOT_MIN"] and bid <= self.settings[server.id]["SLOT_MAX"]:
|
now = datetime.utcnow()
|
||||||
if author.id in self.slot_register:
|
try:
|
||||||
if abs(self.slot_register[author.id] - int(time.perf_counter())) >= self.settings[server.id]["SLOT_TIME"]:
|
if last_slot:
|
||||||
self.slot_register[author.id] = int(
|
if (now - last_slot).seconds < slot_time:
|
||||||
time.perf_counter())
|
raise OnCooldown()
|
||||||
await self.slot_machine(ctx.message, bid)
|
if not valid_bid:
|
||||||
else:
|
raise InvalidBid()
|
||||||
await self.bot.say("Slot machine is still cooling off! Wait {} seconds between each pull".format(self.settings[server.id]["SLOT_TIME"]))
|
if not self.bank.can_spend(author, bid):
|
||||||
else:
|
raise InsufficientBalance
|
||||||
self.slot_register[author.id] = int(time.perf_counter())
|
await self.slot_machine(author, bid)
|
||||||
await self.slot_machine(ctx.message, bid)
|
except NoAccount:
|
||||||
else:
|
await self.bot.say("{} You need an account to use the slot "
|
||||||
await self.bot.say("{0} Bid must be between {1} and {2}.".format(author.mention, self.settings[server.id]["SLOT_MIN"], self.settings[server.id]["SLOT_MAX"]))
|
"machine. Type `{}bank register` to open one."
|
||||||
else:
|
"".format(author.mention, ctx.prefix))
|
||||||
await self.bot.say("{0} You need an account with enough funds to play the slot machine.".format(author.mention))
|
except InsufficientBalance:
|
||||||
|
await self.bot.say("{} You need an account with enough funds to "
|
||||||
|
"play the slot machine.".format(author.mention))
|
||||||
|
except OnCooldown:
|
||||||
|
await self.bot.say("Slot machine is still cooling off! Wait {} "
|
||||||
|
"seconds between each pull".format(slot_time))
|
||||||
|
except InvalidBid:
|
||||||
|
await self.bot.say("Bid must be between {} and {}."
|
||||||
|
"".format(settings["SLOT_MIN"],
|
||||||
|
settings["SLOT_MAX"]))
|
||||||
|
|
||||||
async def slot_machine(self, message, bid):
|
async def slot_machine(self, author, bid):
|
||||||
reel_pattern = [":cherries:", ":cookie:", ":two:", ":four_leaf_clover:",
|
default_reel = deque(SMReel)
|
||||||
":cyclone:", ":sunflower:", ":six:", ":mushroom:", ":heart:", ":snowflake:"]
|
|
||||||
# padding prevents index errors
|
|
||||||
padding_before = [":mushroom:", ":heart:", ":snowflake:"]
|
|
||||||
padding_after = [":cherries:", ":cookie:", ":two:"]
|
|
||||||
reel = padding_before + reel_pattern + padding_after
|
|
||||||
reels = []
|
reels = []
|
||||||
for i in range(0, 3):
|
self.slot_register[author.id] = datetime.utcnow()
|
||||||
n = randint(3, 12)
|
for i in range(3):
|
||||||
reels.append([reel[n - 1], reel[n], reel[n + 1]])
|
default_reel.rotate(random.randint(-999, 999)) # weeeeee
|
||||||
line = [reels[0][1], reels[1][1], reels[2][1]]
|
new_reel = deque(default_reel, maxlen=3) # we need only 3 symbols
|
||||||
|
reels.append(new_reel) # for each reel
|
||||||
|
rows = ((reels[0][0], reels[1][0], reels[2][0]),
|
||||||
|
(reels[0][1], reels[1][1], reels[2][1]),
|
||||||
|
(reels[0][2], reels[1][2], reels[2][2]))
|
||||||
|
|
||||||
display_reels = "~~\n~~ " + \
|
slot = "~~\n~~" # Mobile friendly
|
||||||
reels[0][0] + " " + reels[1][0] + " " + reels[2][0] + "\n"
|
for i, row in enumerate(rows): # Let's build the slot to show
|
||||||
display_reels += ">" + reels[0][1] + " " + \
|
sign = " "
|
||||||
reels[1][1] + " " + reels[2][1] + "\n"
|
if i == 1:
|
||||||
display_reels += " " + reels[0][2] + " " + \
|
sign = ">"
|
||||||
reels[1][2] + " " + reels[2][2] + "\n"
|
slot += "{}{} {} {}\n".format(sign, *[c.value for c in row])
|
||||||
|
|
||||||
if line[0] == ":two:" and line[1] == ":two:" and line[2] == ":six:":
|
payout = PAYOUTS.get(rows[1])
|
||||||
bid = bid * 5000
|
if not payout:
|
||||||
slotMsg = "{}{} 226! Your bet is multiplied * 5000! {}! ".format(
|
# Checks for two-consecutive-symbols special rewards
|
||||||
display_reels, message.author.mention, str(bid))
|
payout = PAYOUTS.get((rows[1][0], rows[1][1]),
|
||||||
elif line[0] == ":four_leaf_clover:" and line[1] == ":four_leaf_clover:" and line[2] == ":four_leaf_clover:":
|
PAYOUTS.get((rows[1][1], rows[1][2]))
|
||||||
bid += 1000
|
)
|
||||||
slotMsg = "{}{} Three FLC! +1000! ".format(
|
if not payout:
|
||||||
display_reels, message.author.mention)
|
# Still nothing. Let's check for 3 generic same symbols
|
||||||
elif line[0] == ":cherries:" and line[1] == ":cherries:" and line[2] == ":cherries:":
|
# or 2 consecutive symbols
|
||||||
bid += 800
|
has_three = rows[1][0] == rows[1][1] == rows[1][2]
|
||||||
slotMsg = "{}{} Three cherries! +800! ".format(
|
has_two = (rows[1][0] == rows[1][1]) or (rows[1][1] == rows[1][0])
|
||||||
display_reels, message.author.mention)
|
if has_three:
|
||||||
elif line[0] == line[1] == line[2]:
|
payout = PAYOUTS["3 symbols"]
|
||||||
bid += 500
|
elif has_two:
|
||||||
slotMsg = "{}{} Three symbols! +500! ".format(
|
payout = PAYOUTS["2 symbols"]
|
||||||
display_reels, message.author.mention)
|
|
||||||
elif line[0] == ":two:" and line[1] == ":six:" or line[1] == ":two:" and line[2] == ":six:":
|
if payout:
|
||||||
bid = bid * 4
|
then = self.bank.get_balance(author)
|
||||||
slotMsg = "{}{} 26! Your bet is multiplied * 4! {}! ".format(
|
pay = payout["payout"](bid)
|
||||||
display_reels, message.author.mention, str(bid))
|
now = then - bid + pay
|
||||||
elif line[0] == ":cherries:" and line[1] == ":cherries:" or line[1] == ":cherries:" and line[2] == ":cherries:":
|
self.bank.set_credits(author, now)
|
||||||
bid = bid * 3
|
await self.bot.say("{}\n{} {}\n\nYour bid: {}\n{} → {}!"
|
||||||
slotMsg = "{}{} Two cherries! Your bet is multiplied * 3! {}! ".format(
|
"".format(slot, author.mention,
|
||||||
display_reels, message.author.mention, str(bid))
|
payout["phrase"], bid, then, now))
|
||||||
elif line[0] == line[1] or line[1] == line[2]:
|
|
||||||
bid = bid * 2
|
|
||||||
slotMsg = "{}{} Two symbols! Your bet is multiplied * 2! {}! ".format(
|
|
||||||
display_reels, message.author.mention, str(bid))
|
|
||||||
else:
|
else:
|
||||||
slotMsg = "{}{} Nothing! Lost bet. ".format(
|
then = self.bank.get_balance(author)
|
||||||
display_reels, message.author.mention)
|
self.bank.withdraw_credits(author, bid)
|
||||||
self.bank.withdraw_credits(message.author, bid)
|
now = then - bid
|
||||||
slotMsg += "\n" + \
|
await self.bot.say("{}\n{} Nothing!\nYour bid: {}\n{} → {}!"
|
||||||
" Credits left: {}".format(
|
"".format(slot, author.mention, bid, then, now))
|
||||||
self.bank.get_balance(message.author))
|
|
||||||
await self.bot.send_message(message.channel, slotMsg)
|
|
||||||
return True
|
|
||||||
self.bank.deposit_credits(message.author, bid)
|
|
||||||
slotMsg += "\n" + \
|
|
||||||
" Current credits: {}".format(
|
|
||||||
self.bank.get_balance(message.author))
|
|
||||||
await self.bot.send_message(message.channel, slotMsg)
|
|
||||||
|
|
||||||
@commands.group(pass_context=True, no_pm=True)
|
@commands.group(pass_context=True, no_pm=True)
|
||||||
@checks.admin_or_permissions(manage_server=True)
|
@checks.admin_or_permissions(manage_server=True)
|
||||||
@ -560,7 +616,7 @@ class Economy:
|
|||||||
"""Minimum slot machine bid"""
|
"""Minimum slot machine bid"""
|
||||||
server = ctx.message.server
|
server = ctx.message.server
|
||||||
self.settings[server.id]["SLOT_MIN"] = bid
|
self.settings[server.id]["SLOT_MIN"] = bid
|
||||||
await self.bot.say("Minimum bid is now " + str(bid) + " credits.")
|
await self.bot.say("Minimum bid is now {} credits.".format(bid))
|
||||||
dataIO.save_json(self.file_path, self.settings)
|
dataIO.save_json(self.file_path, self.settings)
|
||||||
|
|
||||||
@economyset.command(pass_context=True)
|
@economyset.command(pass_context=True)
|
||||||
@ -568,7 +624,7 @@ class Economy:
|
|||||||
"""Maximum slot machine bid"""
|
"""Maximum slot machine bid"""
|
||||||
server = ctx.message.server
|
server = ctx.message.server
|
||||||
self.settings[server.id]["SLOT_MAX"] = bid
|
self.settings[server.id]["SLOT_MAX"] = bid
|
||||||
await self.bot.say("Maximum bid is now " + str(bid) + " credits.")
|
await self.bot.say("Maximum bid is now {} credits.".format(bid))
|
||||||
dataIO.save_json(self.file_path, self.settings)
|
dataIO.save_json(self.file_path, self.settings)
|
||||||
|
|
||||||
@economyset.command(pass_context=True)
|
@economyset.command(pass_context=True)
|
||||||
@ -576,7 +632,7 @@ class Economy:
|
|||||||
"""Seconds between each slots use"""
|
"""Seconds between each slots use"""
|
||||||
server = ctx.message.server
|
server = ctx.message.server
|
||||||
self.settings[server.id]["SLOT_TIME"] = seconds
|
self.settings[server.id]["SLOT_TIME"] = seconds
|
||||||
await self.bot.say("Cooldown is now " + str(seconds) + " seconds.")
|
await self.bot.say("Cooldown is now {} seconds.".format(seconds))
|
||||||
dataIO.save_json(self.file_path, self.settings)
|
dataIO.save_json(self.file_path, self.settings)
|
||||||
|
|
||||||
@economyset.command(pass_context=True)
|
@economyset.command(pass_context=True)
|
||||||
@ -584,7 +640,8 @@ class Economy:
|
|||||||
"""Seconds between each payday"""
|
"""Seconds between each payday"""
|
||||||
server = ctx.message.server
|
server = ctx.message.server
|
||||||
self.settings[server.id]["PAYDAY_TIME"] = seconds
|
self.settings[server.id]["PAYDAY_TIME"] = seconds
|
||||||
await self.bot.say("Value modified. At least " + str(seconds) + " seconds must pass between each payday.")
|
await self.bot.say("Value modified. At least {} seconds must pass "
|
||||||
|
"between each payday.".format(seconds))
|
||||||
dataIO.save_json(self.file_path, self.settings)
|
dataIO.save_json(self.file_path, self.settings)
|
||||||
|
|
||||||
@economyset.command(pass_context=True)
|
@economyset.command(pass_context=True)
|
||||||
@ -592,7 +649,8 @@ class Economy:
|
|||||||
"""Credits earned each payday"""
|
"""Credits earned each payday"""
|
||||||
server = ctx.message.server
|
server = ctx.message.server
|
||||||
self.settings[server.id]["PAYDAY_CREDITS"] = credits
|
self.settings[server.id]["PAYDAY_CREDITS"] = credits
|
||||||
await self.bot.say("Every payday will now give " + str(credits) + " credits.")
|
await self.bot.say("Every payday will now give {} credits."
|
||||||
|
"".format(credits))
|
||||||
dataIO.save_json(self.file_path, self.settings)
|
dataIO.save_json(self.file_path, self.settings)
|
||||||
|
|
||||||
@economyset.command(pass_context=True)
|
@economyset.command(pass_context=True)
|
||||||
@ -602,7 +660,8 @@ class Economy:
|
|||||||
if credits < 0:
|
if credits < 0:
|
||||||
credits = 0
|
credits = 0
|
||||||
self.settings[server.id]["REGISTER_CREDITS"] = credits
|
self.settings[server.id]["REGISTER_CREDITS"] = credits
|
||||||
await self.bot.say("Registering an account will now give {} credits.".format(credits))
|
await self.bot.say("Registering an account will now give {} credits."
|
||||||
|
"".format(credits))
|
||||||
dataIO.save_json(self.file_path, self.settings)
|
dataIO.save_json(self.file_path, self.settings)
|
||||||
|
|
||||||
# What would I ever do without stackoverflow?
|
# What would I ever do without stackoverflow?
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user