Guest User

Untitled

a guest
Jun 7th, 2017
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 118.85 KB | None | 0 0
  1. # Developed by Redjumpman for Redbot.
  2. # Inspired by Spriter's work on a modded economy.
  3. # Creates 1 json file, 1 log file per 10mb, and requires tabulate.
  4.  
  5. # STD Library
  6. import asyncio
  7. import logging
  8. import logging.handlers
  9. import os
  10. import random
  11. from copy import deepcopy
  12. from fractions import Fraction
  13. from operator import itemgetter
  14. from datetime import datetime, timedelta
  15.  
  16. # Discord imports
  17. import discord
  18. from .utils import checks
  19. from .utils.dataIO import dataIO
  20. from discord.ext import commands
  21. from __main__ import send_cmd_help
  22.  
  23. # Third Party Libraries
  24. try:
  25. from tabulate import tabulate
  26. tabulateAvailable = True
  27. except ImportError:
  28. tabulateAvailable = False
  29.  
  30.  
  31. try:
  32. from dateutil import parser
  33. dateutilAvailable = True
  34. except ImportError:
  35. dateutilAvailable = False
  36.  
  37.  
  38. # Default settings that is created when a server begin's using Casino
  39. server_default = {"System Config": {"Casino Name": "Redjumpman", "Casino Open": True,
  40. "Chip Name": "Jump", "Chip Rate": 1, "Default Payday": 100,
  41. "Payday Timer": 1200, "Threshold Switch": False,
  42. "Threshold": 10000, "Credit Rate": 1, "Transfer Limit": 1000,
  43. "Transfer Cooldown": 30, "Version": 1.710
  44. },
  45. "Memberships": {},
  46. "Players": {},
  47. "Games": {"Dice": {"Multiplier": 2.2, "Cooldown": 5, "Open": True, "Min": 50,
  48. "Max": 500, "Access Level": 0},
  49. "Coin": {"Multiplier": 1.5, "Cooldown": 5, "Open": True, "Min": 10,
  50. "Max": 10, "Access Level": 0},
  51. "Cups": {"Multiplier": 2.2, "Cooldown": 5, "Open": True, "Min": 50,
  52. "Max": 500, "Access Level": 0},
  53. "Blackjack": {"Multiplier": 2.2, "Cooldown": 5, "Open": True,
  54. "Min": 50, "Max": 500, "Access Level": 0},
  55. "Allin": {"Multiplier": 2.2, "Cooldown": 86400, "Open": True,
  56. "Access Level": 0},
  57. "Hi-Lo": {"Multiplier": 1.5, "Cooldown": 5, "Open": True,
  58. "Min": 20, "Max": 20, "Access Level": 0},
  59. "War": {"Multiplier": 1.5, "Cooldown": 5, "Open": True,
  60. "Min": 20, "Max": 20, "Access Level": 0},
  61. }
  62. }
  63.  
  64. new_user = {"Chips": 100,
  65. "Membership": None,
  66. "Pending": 0,
  67. "Played": {"Dice Played": 0, "Cups Played": 0, "BJ Played": 0, "Coin Played": 0,
  68. "Allin Played": 0, "Hi-Lo Played": 0, "War Played": 0},
  69. "Won": {"Dice Won": 0, "Cups Won": 0, "BJ Won": 0, "Coin Won": 0, "Allin Won": 0,
  70. "Hi-Lo Won": 0, "War Won": 0},
  71. "Cooldowns": {"Dice": 0, "Cups": 0, "Coin": 0, "Allin": 0, "Hi-Lo": 0, "War": 0,
  72. "Blackjack": 0, "Payday": 0, "Transfer": 0}
  73. }
  74.  
  75. # Deck used for blackjack, and a dictionary to correspond values of the cards.
  76. main_deck = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace'] * 4
  77.  
  78.  
  79. bj_values = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'Jack': 10,
  80. 'Queen': 10, 'King': 10}
  81.  
  82. war_values = {'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'Jack': 11,
  83. 'Queen': 12, 'King': 13, 'Ace': 14}
  84.  
  85. hilo_data = {"Played": {"Hi-Lo Played": 0}, "Won": {"Hi-Lo Won": 0}, "Cooldown": {"Hi-Lo": 0}}
  86.  
  87. war_data = {"Played": {"War Played": 0}, "Won": {"War Won": 0}, "Cooldown": {"War": 0}}
  88.  
  89. c_games = ["Blackjack", "Coin", "Allin", "Cups", "Dice", "Hi-Lo", "War"]
  90.  
  91.  
  92. class CasinoError(Exception):
  93. pass
  94.  
  95.  
  96. class UserAlreadyRegistered(CasinoError):
  97. pass
  98.  
  99.  
  100. class UserNotRegistered(CasinoError):
  101. pass
  102.  
  103.  
  104. class InsufficientChips(CasinoError):
  105. pass
  106.  
  107.  
  108. class NegativeChips(CasinoError):
  109. pass
  110.  
  111.  
  112. class SameSenderAndReceiver(CasinoError):
  113. pass
  114.  
  115.  
  116. class BotNotAUser(CasinoError):
  117. pass
  118.  
  119.  
  120. class CasinoBank:
  121. """Holds all of the Casino hooks for integration"""
  122.  
  123. def __init__(self, bot, file_path):
  124. self.memberships = dataIO.load_json(file_path)
  125. self.bot = bot
  126. self.patch = 1.710
  127.  
  128. def create_account(self, user):
  129. server = user.server
  130. path = self.check_server_settings(server)
  131.  
  132. if user.id not in path["Players"]:
  133. default_user = deepcopy(new_user)
  134. path["Players"][user.id] = default_user
  135. path["Players"][user.id]["Name"] = user.name
  136. self.save_system()
  137. membership = path["Players"][user.id]
  138. return membership
  139. else:
  140. raise UserAlreadyRegistered()
  141.  
  142. def membership_exists(self, user):
  143. try:
  144. self.get_membership(user)
  145. except UserNotRegistered:
  146. return False
  147. return True
  148.  
  149. def chip_balance(self, user):
  150. account = self.get_membership(user)
  151. return account["Chips"]
  152.  
  153. def can_bet(self, user, amount):
  154. account = self.get_membership(user)
  155. if account["Chips"] >= amount:
  156. return True
  157. else:
  158. raise InsufficientChips()
  159.  
  160. def set_chips(self, user, amount):
  161. if amount < 0:
  162. raise NegativeChips()
  163. account = self.get_membership(user)
  164. account["Chips"] = amount
  165. self.save_system()
  166.  
  167. def deposit_chips(self, user, amount):
  168. amount = int(round(amount))
  169. if amount < 0:
  170. raise NegativeChips()
  171. account = self.get_membership(user)
  172. account["Chips"] += amount
  173. self.save_system()
  174.  
  175. def withdraw_chips(self, user, amount):
  176. if amount < 0:
  177. raise NegativeChips()
  178.  
  179. account = self.get_membership(user)
  180. if account["Chips"] >= amount:
  181. account["Chips"] -= amount
  182. self.save_system()
  183. else:
  184. raise InsufficientChips()
  185.  
  186. def transfer_chips(self, sender, receiver, amount):
  187. if amount < 0:
  188. raise NegativeChips()
  189.  
  190. if sender is receiver:
  191. raise SameSenderAndReceiver()
  192.  
  193. if receiver == self.bot.user:
  194. raise BotNotAUser()
  195.  
  196. if self.membership_exists(sender) and self.membership_exists(receiver):
  197. sender_acc = self.get_membership(sender)
  198. if sender_acc["Chips"] < amount:
  199. raise InsufficientChips()
  200. self.withdraw_chips(sender, amount)
  201. self.deposit_chips(receiver, amount)
  202. else:
  203. raise UserNotRegistered()
  204.  
  205. def wipe_caisno_server(self, server):
  206. self.memberships["Servers"].pop(server.id)
  207. self.save_system()
  208.  
  209. def wipe_casino_members(self, server):
  210. self.memberships["Servers"][server.id]["Players"] = {}
  211. self.save_system()
  212.  
  213. def remove_membership(self, user):
  214. server = user.server
  215. self.memberships["Servers"][server.id]["Players"].pop(user.id)
  216. self.save_system()
  217.  
  218. def get_membership(self, user):
  219. server = user.server
  220. path = self.check_server_settings(server)
  221.  
  222. try:
  223. return path["Players"][user.id]
  224. except KeyError:
  225. raise UserNotRegistered()
  226.  
  227. def get_all_servers(self):
  228. return self.memberships["Servers"]
  229.  
  230. def get_casino_server(self, server):
  231. return self.memberships["Servers"][server.id]
  232.  
  233. def get_server_memberships(self, server):
  234. if server.id in self.memberships["Servers"]:
  235. members = self.memberships["Servers"][server.id]["Players"]
  236. return members
  237. else:
  238. return []
  239.  
  240. def save_system(self):
  241. dataIO.save_json("data/JumperCogs/casino/casino.json", self.memberships)
  242.  
  243. def check_server_settings(self, server):
  244. if server.id not in self.memberships["Servers"]:
  245. self.memberships["Servers"][server.id] = server_default
  246. self.save_system()
  247. print("Creating default casino settings for Server: {}".format(server.name))
  248. path = self.memberships["Servers"][server.id]
  249. return path
  250. else: # NOTE Will be moved to a cmd in future patch. Used to update JSON from older version
  251. path = self.memberships["Servers"][server.id]
  252.  
  253. try:
  254. if path["System Config"]["Version"] < self.patch:
  255. self.casino_patcher(path)
  256. path["System Config"]["Version"] = self.patch
  257. except KeyError:
  258. path["System Config"]["Version"] = self.patch
  259. self.casino_patcher(path)
  260.  
  261. return path
  262.  
  263. def casino_patcher(self, path):
  264.  
  265. if path["System Config"]["Version"] < 1.581:
  266. self.DICT_PATCH_1581(path)
  267.  
  268. if path["System Config"]["Version"] < 1.692:
  269. self.DICT_PATCH_1692(path)
  270.  
  271. if path["System Config"]["Version"] < 1.694:
  272. self.DICT_PATCH_1694(path)
  273.  
  274. if path["System Config"]["Version"] < 1.705:
  275. self.DICT_PATCH_16(path)
  276.  
  277. if path["System Config"]["Version"] < 1.706:
  278. self.DICT_PATCH_1694(path) # Fix for unix cd update failure
  279.  
  280. # Save changes and return updated dictionary.
  281. self.save_system()
  282.  
  283. def name_fix(self):
  284. servers = self.get_all_servers()
  285. removal = []
  286. for server in servers:
  287. try:
  288. server_obj = self.bot.get_server(server)
  289. self.name_bug_fix(server_obj)
  290. except AttributeError:
  291. removal.append(server)
  292. logger.info("WIPED SERVER: {} FROM CASINO".format(server))
  293. print("Removed server ID: {} from the list of servers, because the bot is no "
  294. "longer on that server.".format(server))
  295. for x in removal:
  296. self.memberships["Servers"].pop(x)
  297. self.save_system()
  298.  
  299. def name_bug_fix(self, server):
  300. players = self.get_server_memberships(server)
  301. for player in players:
  302. mobj = server.get_member(player)
  303. try:
  304. if players[player]["Name"] != mobj.name:
  305. players[player]["Name"] = mobj.name
  306. except AttributeError:
  307. print("Error updating name! {} is no longer on this server.".format(player))
  308.  
  309. def DICT_PATCH_GAMES(self, path):
  310.  
  311. # Check if player data has the war game, and if not add it.
  312. for player in path["Players"]:
  313. if "War Played" not in path["Players"][player]["Played"]:
  314. path["Players"][player]["Played"]["War Played"] = 0
  315. if "War Won" not in path["Players"][player]["Won"]:
  316. path["Players"][player]["Won"]["War Won"] = 0
  317. if "War" not in path["Players"][player]["Cooldowns"]:
  318. path["Players"][player]["Cooldowns"]["War"] = 0
  319. self.save_system()
  320.  
  321. def DICT_PATCH_1694(self, path):
  322. """This patch aimed at converting the old cooldown times into unix time."""
  323. print("DICT_Patch_1694 ran")
  324. for player in path["Players"]:
  325. try:
  326. for cooldown in path["Players"][player]["Cooldowns"]:
  327. s = path["Players"][player]["Cooldowns"][cooldown]
  328. convert = datetime.utcnow() - timedelta(seconds=s)
  329. path["Players"][player]["Cooldowns"][cooldown] = convert.isoformat()
  330. except TypeError:
  331. pass
  332. self.save_system()
  333.  
  334. def DICT_PATCH_1692(self, path):
  335. """Issues with memberships storing keys that are lower case.
  336. Fire bombing everyones memberships so I don't have nightmares.
  337. """
  338. path["Memberships"] = {}
  339. self.save_system()
  340.  
  341. def DICT_PATCH_16(self, path):
  342. if "Transfer Limit" not in path["System Config"]:
  343. transfer_dict = {"Transfer Limit": 1000, "Transfer Cooldown": 30}
  344. path["System Config"].update(transfer_dict)
  345.  
  346. for x in path["Players"]:
  347. if "Transfer" not in path["Players"][x]["Cooldowns"]:
  348. path["Players"][x]["Cooldowns"]["Transfer"] = 0
  349. self.save_system()
  350.  
  351. def DICT_PATCH_1581(self, path):
  352. # Fixes the name bug for older versions
  353. self.name_fix()
  354. # Add hi-lo to older versions
  355. if "Hi-Lo" not in path["Games"]:
  356. hl = {"Hi-Lo": {"Multiplier": 1.5, "Cooldown": 0, "Open": True, "Min": 20,
  357. "Max": 20}}
  358. path["Games"].update(hl)
  359.  
  360. # Add war to older versions
  361. if "War" not in path["Games"]:
  362. war = {"War": {"Multiplier": 1.5, "Cooldown": 0, "Open": True, "Min": 50,
  363. "Max": 100}}
  364. path["Games"].update(war)
  365.  
  366. # Add membership changes from patch 1.5 to older versions
  367. trash = ["Membership Lvl 0", "Membership Lvl 1", "Membership Lvl 2",
  368. "Membership Lvl 3"]
  369. new = {"Threshold Switch": False, "Threshold": 10000, "Default Payday": 100,
  370. "Payday Timer": 1200}
  371.  
  372. for k, v in new.items():
  373. if k not in path["System Config"]:
  374. path["System Config"][k] = v
  375.  
  376. if "Memberships" not in path:
  377. path["Memberships"] = {}
  378.  
  379. # Game access levels added
  380. for x in path["Games"].values():
  381. if "Access Level" not in x:
  382. x["Access Level"] = 0
  383.  
  384. if "Min" in path["Games"]["Allin"]:
  385. path["Games"]["Allin"].pop("Min")
  386.  
  387. if "Max" in path["Games"]["Allin"]:
  388. path["Games"]["Allin"].pop("Max")
  389.  
  390. for x in trash:
  391. if x in path["System Config"]:
  392. path["System Config"].pop(x)
  393.  
  394. for x in path["Players"]:
  395. if "CD" in path["Players"][x]:
  396. path["Players"][x]["Cooldowns"] = path["Players"][x].pop("CD")
  397. raw = [(x.split(" ", 1)[0], y) for x, y in
  398. path["Players"][x]["Cooldowns"].items()]
  399. raw.append(("Payday", 0))
  400. new_dict = dict(raw)
  401. path["Players"][x]["Cooldowns"] = new_dict
  402.  
  403. if "Membership" not in path["Players"][x]:
  404. path["Players"][x]["Membership"] = None
  405.  
  406. if "Pending" not in path["Players"][x]:
  407. path["Players"][x]["Pending"] = 0
  408. self.save_system()
  409.  
  410.  
  411. class PluralDict(dict):
  412. """This class is used to plural strings
  413.  
  414. You can plural strings based on the value input when using this class as a dictionary.
  415. """
  416. def __missing__(self, key):
  417. if '(' in key and key.endswith(')'):
  418. key, rest = key.split('(', 1)
  419. value = super().__getitem__(key)
  420. suffix = rest.rstrip(')').split(',')
  421. if len(suffix) == 1:
  422. suffix.insert(0, '')
  423. return suffix[0] if value <= 1 else suffix[1]
  424. raise KeyError(key)
  425.  
  426.  
  427. class Casino:
  428. """Play Casino minigames and earn chips that integrate with Economy!
  429.  
  430. Any user can join casino by using the casino join command. Casino uses hooks from economy to
  431. cash in/out chips. You are able to create your own casino name and chip name. Casino comes with
  432. 7 mini games that you can set min/max bets, multipliers, and access levels. Check out all of the
  433. admin settings by using commands in the setcasino group. For additional information please
  434. check out the wiki on my github.
  435.  
  436. """
  437. __slots__ = ['bot', 'file_path', 'version', 'legacy_available', 'legacy_path', 'legacy_system',
  438. 'casino_bank', 'cycle_task']
  439.  
  440. def __init__(self, bot):
  441. self.bot = bot
  442. try: # This allows you to port accounts from older versions of casino
  443. self.legacy_path = "data/casino/casino.json"
  444. self.legacy_system = dataIO.load_json(self.legacy_path)
  445. self.legacy_available = True
  446. except FileNotFoundError:
  447. self.legacy_available = False
  448. self.file_path = "data/JumperCogs/casino/casino.json"
  449. self.casino_bank = CasinoBank(bot, self.file_path)
  450. self.version = "1.7.10"
  451. self.cycle_task = bot.loop.create_task(self.membership_updater())
  452.  
  453. @commands.group(pass_context=True, no_pm=True)
  454. async def casino(self, ctx):
  455. """Casino Group Commands"""
  456.  
  457. if ctx.invoked_subcommand is None:
  458. await send_cmd_help(ctx)
  459.  
  460. @casino.command(name="purge", pass_context=True)
  461. @checks.is_owner()
  462. async def _purge_casino(self, ctx):
  463. """Removes all servers that the bot is no longer on.
  464. If your JSON file is getting rather large, utilize this
  465. command. It is possible that if your bot is on a ton of
  466. servers, there are many that it is no longer running on.
  467. This will remove them from the JSON file.
  468. """
  469. user = ctx.message.author
  470. servers = self.casino_bank.get_all_servers()
  471. purge_list = [x for x in servers if self.bot.get_server(x) is None]
  472. if not purge_list:
  473. return await self.bot.say("There are no servers for me to purge at this time.")
  474. await self.bot.say("I found {} server(s) I am no longer on. Would you like for me to "
  475. "delete their casino data?".format(len(purge_list)))
  476. response = await self.bot.wait_for_message(timeout=15, author=user)
  477.  
  478. if response is None:
  479. return await self.bot.say("You took too long to answer. Canceling purge.")
  480.  
  481. if response.content.title() == "Yes":
  482. for x in purge_list:
  483. servers.pop(x)
  484. self.casino_bank.save_system()
  485. await self.bot.say("{} server entries have been erased.".format(len(purge_list)))
  486. else:
  487. return await self.bot.say("Incorrect response. This is a yes or no question.")
  488.  
  489. @casino.command(name="forceupdate", pass_context=True)
  490. @checks.is_owner()
  491. async def _forceupdate_casino(self, ctx):
  492. """Force applies older patches
  493. This command will attempt to update your JSON with the
  494. new dictionary keys. If you are having issues with your JSON
  495. having a lot of key errors, namely Cooldown, then try using
  496. this command. THIS DOES NOT UPDATE CASINO
  497. """
  498.  
  499. server = ctx.message.server
  500. settings = self.casino_bank.check_server_settings(server)
  501. self.casino_bank.DICT_PATCH_1581(settings)
  502. self.casino_bank.DICT_PATCH_16(settings)
  503. self.casino_bank.DICT_PATCH_GAMES(settings)
  504. self.casino_bank.DICT_PATCH_1694(settings)
  505. await self.bot.say("Force applied three previous JSON updates. Please reload casino.")
  506.  
  507. @casino.command(name="memberships", pass_context=True)
  508. @commands.cooldown(1, 5, commands.BucketType.user)
  509. async def _memberships_casino(self, ctx):
  510. """Shows all memberships on the server."""
  511. server = ctx.message.server
  512. settings = self.casino_bank.check_server_settings(server)
  513. memberships = settings["Memberships"].keys()
  514. if memberships:
  515. await self.bot.say("Available Memberships:```\n{}```".format('\n'.join(memberships)))
  516. else:
  517. await self.bot.say("There are no memberships.")
  518.  
  519. @casino.command(name="join", pass_context=True)
  520. async def _join_casino(self, ctx):
  521. """Grants you membership access to the casino"""
  522. user = ctx.message.author
  523. settings = self.casino_bank.check_server_settings(user.server)
  524. try:
  525. self.casino_bank.create_account(user)
  526. except UserAlreadyRegistered:
  527. return await self.bot.say("{} already has a casino membership".format(user.name))
  528. else:
  529. name = settings["System Config"]["Casino Name"]
  530. await self.bot.say("Your membership has been approved! Welcome to {} Casino!\nAs a "
  531. "first time member we have credited your account with 100 free "
  532. "chips.\nHave fun!".format(name))
  533.  
  534. @casino.command(name="transfer", pass_context=True)
  535. @commands.cooldown(1, 5, commands.BucketType.user)
  536. async def _transfer_casino(self, ctx, user: discord.Member, chips: int):
  537. """Transfers chips to another player"""
  538. author = ctx.message.author
  539. settings = self.casino_bank.check_server_settings(author.server)
  540. chip_name = settings["System Config"]["Chip Name"]
  541. limit = settings["System Config"]["Transfer Limit"]
  542.  
  543. if not self.casino_bank.membership_exists(author):
  544. return await self.bot.say("{} is not registered to the casino.".format(author.name))
  545.  
  546. if not self.casino_bank.membership_exists(user):
  547. return await self.bot.say("{} is not registered to the casino.".format(user.name))
  548.  
  549. if chips > limit:
  550. return await self.bot.say("Your transfer cannot exceed the server limit of {} {} "
  551. "chips.".format(limit, chip_name))
  552.  
  553. chip_name = settings["System Config"]["Chip Name"]
  554. cooldown = self.check_cooldowns(user, "Transfer", settings)
  555.  
  556. if not cooldown:
  557. try:
  558. self.casino_bank.transfer_chips(author, user, chips)
  559. except NegativeChips:
  560. return await self.bot.say("An amount cannot be negative.")
  561. except SameSenderAndReceiver:
  562. return await self.bot.say("Sender and Reciever cannot be the same.")
  563. except BotNotAUser:
  564. return await self.bot.say("You can send chips to a bot.")
  565. except InsufficientChips:
  566. return await self.bot.say("Not enough chips to transfer.")
  567. else:
  568. logger.info("{}({}) transferred {} {} to {}({}).".format(author.name, author.id,
  569. chip_name, chips,
  570. user.name, user.id))
  571. await self.bot.say("{} transferred {} {} to {}.".format(author.name, chip_name, chips,
  572. user.name))
  573. else:
  574. await self.bot.say(cooldown)
  575.  
  576. @casino.command(name="acctransfer", pass_context=True)
  577. async def _acctransfer_casino(self, ctx):
  578. """Transfers account info from old casino. Limit 1 transfer per user"""
  579. user = ctx.message.author
  580. settings = self.casino_bank.check_server_settings(user.server)
  581.  
  582. if not self.casino_bank.membership_exists(user):
  583. msg = "I can't transfer data if you already have an account with the new casino."
  584. elif not self.legacy_available:
  585. msg = "No legacy file was found. Unable to perform membership transfers."
  586. elif user.id in self.legacy_system["Players"]:
  587. await self.bot.say("Account for {} found. Your casino data will be transferred to the "
  588. "{} server. After your data is transferred your old data will be "
  589. "deleted. I can only transfer data **one time**.\nDo you wish to "
  590. "transfer?".format(user.name, user.server.name))
  591. response = await self.bot.wait_for_message(timeout=15, author=user)
  592. if response is None:
  593. msg = "No response, transfer cancelled."
  594. elif response.content.title() == "No":
  595. msg = "Transfer cancelled."
  596. elif response.content.title() == "Yes":
  597. old_data = self.legacy_system["Players"][user.id]
  598. transfer = {user.id: old_data}
  599. settings["Players"].update(transfer)
  600. self.legacy_system["Players"].pop(user.id)
  601. dataIO.save_json(self.legacy_path, self.legacy_system)
  602. self.casino_bank.DICT_PATCH_1581(settings)
  603. self.casino_bank.DICT_PATCH_16(settings)
  604. self.casino_bank.DICT_PATCH_GAMES(settings)
  605. self.casino_bank.DICT_PATCH_1694(settings)
  606. self.casino_bank.save_system()
  607. msg = "Data transfer successful. You can now access your old casino data."
  608. else:
  609. msg = "Improper response. Please state yes or no. Cancelling transfer."
  610. else:
  611. msg = "Unable to locate your previous data."
  612. await self.bot.say(msg)
  613.  
  614. @casino.command(name="leaderboard", pass_context=True)
  615. @commands.cooldown(1, 5, commands.BucketType.user)
  616. async def _leaderboard_casino(self, ctx, sort="top"):
  617. """Displays Casino Leaderboard"""
  618. user = ctx.message.author
  619. self.casino_bank.check_server_settings(user.server)
  620. members = self.casino_bank.get_server_memberships(user.server)
  621.  
  622. if sort not in ["top", "bottom", "place"]:
  623. sort = "top"
  624.  
  625. if members:
  626. players = [(x["Name"], x["Chips"]) for x in members.values()]
  627. pos = [x + 1 for x, y in enumerate(players)]
  628. if sort == "bottom":
  629. style = sorted(players, key=itemgetter(1))
  630. rev_pos = list(reversed(pos))
  631. players, chips = zip(*style)
  632. data = list(zip(rev_pos, players, chips))
  633. elif sort == "place":
  634. style = sorted([[x["Name"], x["Chips"]] if x["Name"] != user.name
  635. else ["[" + x["Name"] + "]", x["Chips"]]
  636. for x in members.values()], key=itemgetter(1), reverse=True)
  637. players, chips = zip(*style)
  638. data = list(zip(pos, players, chips))
  639. else:
  640. style = sorted(players, key=itemgetter(1), reverse=True)
  641. players, chips = zip(*style)
  642. data = list(zip(pos, players, chips))
  643. headers = ["Rank", "Names", "Chips"]
  644. msg = await self.table_split(user, headers, data, sort)
  645. else:
  646. msg = "There are no casino players to show on the leaderboard."
  647. await self.bot.say(msg)
  648.  
  649. @casino.command(name="exchange", pass_context=True)
  650. @commands.cooldown(1, 5, commands.BucketType.user)
  651. async def _exchange_casino(self, ctx, currency: str, amount: int):
  652. """Exchange chips for credits and credits for chips"""
  653.  
  654. # Declare all variables here
  655. user = ctx.message.author
  656. settings = self.casino_bank.check_server_settings(user.server)
  657. bank = self.bot.get_cog('Economy').bank
  658. currency = currency.title()
  659. chip_rate = settings["System Config"]["Chip Rate"]
  660. credit_rate = settings["System Config"]["Credit Rate"]
  661. chip_multiple = Fraction(chip_rate).limit_denominator().denominator
  662. credit_multiple = Fraction(credit_rate).limit_denominator().denominator
  663. chip_name = settings["System Config"]["Chip Name"]
  664. casino_name = settings["System Config"]["Casino Name"]
  665.  
  666. # Logic checks
  667. if not self.casino_bank.membership_exists(user):
  668. return await self.bot.say("You need to register to the {} Casino. To register type "
  669. "`{}casino join`.".format(casino_name, ctx.prefix))
  670. if currency not in ["Chips", "Credits"]:
  671. return await self.bot.say("I can only exchange chips or credits, please specify one.")
  672.  
  673. # Logic for choosing chips
  674. elif currency == "Chips":
  675. if amount <= 0 and amount % credit_multiple != 0:
  676. return await self.bot.say("The amount must be higher than 0 and "
  677. "a multiple of {}.".format(credit_multiple))
  678. try:
  679. self.casino_bank.can_bet(user, amount)
  680. except InsufficientChips:
  681. return await self.bot.say("You don't have that many chips to exchange.")
  682. else:
  683. self.casino_bank.withdraw_chips(user, amount)
  684. credits = int(amount * credit_rate)
  685. bank.deposit_credits(user, credits)
  686. return await self.bot.say("I have exchanged {} {} chips into {} credits.\nThank "
  687. "you for playing at {} "
  688. "Casino.".format(amount, chip_name, credits, casino_name))
  689.  
  690. # Logic for choosing Credits
  691. elif currency == "Credits":
  692. if amount <= 0 and amount % chip_multiple != 0:
  693. return await self.bot.say("The amount must be higher than 0 and a multiple "
  694. "of {}.".format(chip_multiple))
  695. elif bank.can_spend(user, amount):
  696. bank.withdraw_credits(user, amount)
  697. chip_amount = int(amount * chip_rate)
  698. self.casino_bank.deposit_chips(user, chip_amount)
  699. await self.bot.say("I have exchanged {} credits for {} {} chips.\nEnjoy your time "
  700. "at {} Casino!".format(amount, chip_amount, chip_name,
  701. casino_name))
  702. else:
  703. await self.bot.say("You don't have that many credits to exchange.")
  704.  
  705. @casino.command(name="stats", pass_context=True)
  706. @commands.cooldown(1, 5, commands.BucketType.user)
  707. async def _stats_casino(self, ctx):
  708. """Shows your casino play stats"""
  709.  
  710. # Variables
  711. author = ctx.message.author
  712. settings = self.casino_bank.check_server_settings(author.server)
  713. chip_name = settings["System Config"]["Chip Name"]
  714. casino_name = settings["System Config"]["Casino Name"]
  715.  
  716. # Check for a membership and build the table.
  717. try:
  718. chip_balance = self.casino_bank.chip_balance(author)
  719. except UserNotRegistered:
  720. await self.bot.say("You need to register to the {} Casino. To register type `{}casino "
  721. "join`.".format(casino_name, ctx.prefix))
  722. else:
  723. pending_chips = settings["Players"][author.id]["Pending"]
  724. player = settings["Players"][author.id]
  725. wiki = "[Wiki](https://github.com/Redjumpman/Jumper-Cogs/wiki/Casino)"
  726. membership, benefits = self.get_benefits(settings, author.id)
  727. b_msg = ("Access Level: {Access}\nCooldown Reduction: {Cooldown Reduction}\n"
  728. "Payday: {Payday}".format(**benefits))
  729. description = ("{}\nMembership: {}\n{} Chips: "
  730. "{}".format(wiki, membership, chip_name, chip_balance))
  731. color = self.color_lookup(benefits["Color"])
  732.  
  733. # Build columns for the table
  734. games = list(sorted(settings["Games"]))
  735. played = [x[1] for x in sorted(player["Played"].items(), key=lambda tup: tup[0])]
  736. won = [x[1] for x in sorted(player["Won"].items(), key=lambda tup: tup[0])]
  737. cool_items = list(sorted(games + ["Payday"]))
  738. cooldowns = self.stats_cooldowns(settings, author, cool_items)
  739.  
  740. # Build embed
  741. embed = discord.Embed(colour=color, description=description)
  742. embed.title = "{} Casino".format(casino_name)
  743. embed.set_author(name=str(author), icon_url=author.avatar_url)
  744. embed.add_field(name="Benefits", value=b_msg)
  745. embed.add_field(name="Pending Chips", value=pending_chips, inline=False)
  746. embed.add_field(name="Games", value="```Prolog\n{}```".format("\n".join(games)))
  747. embed.add_field(name="Played",
  748. value="```Prolog\n{}```".format("\n".join(map(str, played))))
  749. embed.add_field(name="Won", value="```Prolog\n{}```".format("\n".join(map(str, won))))
  750. embed.add_field(name="Cooldown Items",
  751. value="```CSS\n{}```".format("\n".join(cool_items)))
  752. embed.add_field(name="Cooldown Remaining",
  753. value="```xl\n{}```".format("\n".join(cooldowns)))
  754.  
  755. await self.bot.say(embed=embed)
  756.  
  757. @casino.command(name="info", pass_context=True)
  758. @commands.cooldown(1, 5, commands.BucketType.user)
  759. async def _info_casino(self, ctx):
  760. """Shows information about the server casino"""
  761.  
  762. # Variables
  763. server = ctx.message.server
  764. settings = self.casino_bank.check_server_settings(server)
  765. players = len(self.casino_bank.get_server_memberships(server))
  766. memberships = len(settings["Memberships"])
  767. chip_exchange_rate = settings["System Config"]["Chip Rate"]
  768. credit_exchange_rate = settings["System Config"]["Credit Rate"]
  769. games = settings["Games"].keys()
  770.  
  771. if settings["System Config"]["Threshold Switch"]:
  772. threshold = settings["System Config"]["Threshold"]
  773. else:
  774. threshold = "None"
  775.  
  776. # Create the columns through list comprehensions
  777. multiplier = [subdict["Multiplier"] for subdict in settings["Games"].values()]
  778. min_bet = [subdict["Min"] if "Min" in subdict else "None"
  779. for subdict in settings["Games"].values()]
  780. max_bet = [subdict["Max"] if "Max" in subdict else "None"
  781. for subdict in settings["Games"].values()]
  782. cooldown = [subdict["Cooldown"] for subdict in settings["Games"].values()]
  783. cooldown_formatted = [self.time_format(x) for x in cooldown]
  784.  
  785. # Determine the ratio calculations for chips and credits
  786. chip_ratio = str(Fraction(chip_exchange_rate).limit_denominator()).replace("/", ":")
  787. credit_ratio = str(Fraction(credit_exchange_rate).limit_denominator()).replace("/", ":")
  788.  
  789. # If a fraction reduces to 1, we make it 1:1
  790. if chip_ratio == "1":
  791. chip_ratio = "1:1"
  792. if credit_ratio == "1":
  793. credit_ratio = "1:1"
  794.  
  795. # Build the table and send the message
  796. m = list(zip(games, multiplier, min_bet, max_bet, cooldown_formatted))
  797. m = sorted(m, key=itemgetter(0))
  798. t = tabulate(m, headers=["Game", "Multiplier", "Min Bet", "Max Bet", "Cooldown"])
  799. msg = ("```Python\n{}\n\nCredit Exchange Rate: {}\nChip Exchange Rate: {}\n"
  800. "Casino Members: {}\nServer Memberships: {}\nServer Threshold: "
  801. "{}```".format(t, credit_ratio, chip_ratio, players, memberships, threshold))
  802. print("THIS MESSAGE IS {} CHARACTERS".format(len(msg)))
  803. await self.bot.say(msg)
  804.  
  805. @casino.command(name="payday", pass_context=True)
  806. @commands.cooldown(1, 5, commands.BucketType.user)
  807. async def _payday_casino(self, ctx):
  808. """Gives you some chips"""
  809.  
  810. user = ctx.message.author
  811. settings = self.casino_bank.check_server_settings(user.server)
  812. casino_name = settings["System Config"]["Casino Name"]
  813. chip_name = settings["System Config"]["Chip Name"]
  814.  
  815. if not self.casino_bank.membership_exists(user):
  816. await self.bot.say("You need to register to the {} Casino. To register type `{}casino "
  817. "join`.".format(casino_name, ctx.prefix))
  818. else:
  819. cooldown = self.check_cooldowns(user, "Payday", settings)
  820. if not cooldown:
  821. if settings["Players"][user.id]["Membership"]:
  822. membership = settings["Players"][user.id]["Membership"]
  823. amount = settings["Memberships"][membership]["Payday"]
  824. self.casino_bank.deposit_chips(user, amount)
  825. msg = "You received {} {} chips.".format(amount, chip_name)
  826. else:
  827. payday = settings["System Config"]["Default Payday"]
  828. self.casino_bank.deposit_chips(user, payday)
  829. msg = "You received {} {} chips. Enjoy!".format(payday, chip_name)
  830. else:
  831. msg = cooldown
  832. await self.bot.say(msg)
  833.  
  834. @casino.command(name="balance", pass_context=True)
  835. @commands.cooldown(1, 5, commands.BucketType.user)
  836. async def _balance_casino(self, ctx):
  837. """Shows your number of chips"""
  838. user = ctx.message.author
  839. settings = self.casino_bank.check_server_settings(user.server)
  840. chip_name = settings["System Config"]["Chip Name"]
  841. casino_name = settings["System Config"]["Casino Name"]
  842. try:
  843. balance = self.casino_bank.chip_balance(user)
  844. except UserNotRegistered:
  845. await self.bot.say("You need to register to the {} Casino. To register type `{}casino "
  846. "join`.".format(casino_name, ctx.prefix))
  847. else:
  848. await self.bot.say("```Python\nYou have {} {} chips.```".format(balance, chip_name))
  849.  
  850. @commands.command(pass_context=True, no_pm=True, aliases=["hl", "hi-lo"])
  851. @commands.cooldown(1, 5, commands.BucketType.user)
  852. async def hilo(self, ctx, choice: str, bet: int):
  853. """Pick High, Low, Seven. Lo is < 7 Hi is > 7. 6x payout on 7"""
  854.  
  855. # Declare variables for the game.
  856. user = ctx.message.author
  857. settings = self.casino_bank.check_server_settings(user.server)
  858. chip_name = settings["System Config"]["Chip Name"]
  859. choice = choice.title()
  860. choices = ["Hi", "High", "Low", "Lo", "Seven", "7"]
  861.  
  862. # Run a logic check to determine if the user can play the game
  863. check = self.game_checks(settings, ctx.prefix, user, bet, "Hi-Lo", choice, choices)
  864. if check:
  865. msg = check
  866. else: # Run the game when the checks return None
  867. self.casino_bank.withdraw_chips(user, bet)
  868. settings["Players"][user.id]["Played"]["Hi-Lo Played"] += 1
  869. await self.bot.say("The dice hit the table and slowly fall into place...")
  870. die_one = random.randint(1, 6)
  871. die_two = random.randint(1, 6)
  872. result = die_one + die_two
  873. outcome = self.hl_outcome(result)
  874. await asyncio.sleep(2)
  875.  
  876. # Begin game logic to determine a win or loss
  877. msg = ("The dice landed on {} and {} \n".format(die_one, die_two))
  878. if choice in outcome:
  879. msg += ("Congratulations! The outcome was "
  880. "{} ({})!".format(outcome[0], outcome[2]))
  881. settings["Players"][user.id]["Won"]["Hi-Lo Won"] += 1
  882.  
  883. # Check for a 7 to give a 12x multiplier
  884. if outcome[2] == "Seven":
  885. amount = bet * 6
  886. msg += "\n**BONUS!** 6x multiplier for Seven!"
  887. else:
  888. amount = int(round(bet * settings["Games"]["Hi-Lo"]["Multiplier"]))
  889.  
  890. # Check if a threshold is set and withold chips if amount is exceeded
  891. if self.threshold_check(settings, amount):
  892. settings["Players"][user.id]["Pending"] = amount
  893. msg += ("```Your winnings exceeded the threshold set on this server. "
  894. "The amount of {} {} chips will be withheld until reviewed and "
  895. "released by an admin. Do not attempt to play additional games "
  896. "exceeding the threshold until this has been cleared.```"
  897. "".format(amount, chip_name, user.id))
  898. logger.info("{}({}) won {} chips exceeding the threshold. Game "
  899. "details:\nPlayer Choice: {}\nPlayer Bet: {}\nGame "
  900. "Outcome: {}\n[END OF REPORT]"
  901. "".format(user.name, user.id, amount, choice.ljust(10),
  902. str(bet).ljust(10), str(outcome[0]).ljust(10)))
  903. else:
  904. self.casino_bank.deposit_chips(user, amount)
  905. msg += "```Python\nYou just won {} {} chips.```".format(amount, chip_name)
  906. else:
  907. msg += "Sorry. The outcome was {} ({}).".format(outcome[0], outcome[2])
  908. # Save the results of the game
  909. self.casino_bank.save_system()
  910. # Send a message telling the user the outcome of this command
  911. await self.bot.say(msg)
  912.  
  913. @commands.command(pass_context=True, no_pm=True)
  914. @commands.cooldown(1, 5, commands.BucketType.user)
  915. async def cups(self, ctx, cup: int, bet: int):
  916. """Pick the cup that is hiding the gold coin. Choose 1, 2, 3, or 4"""
  917.  
  918. # Declare variables for the game.
  919. user = ctx.message.author
  920. settings = self.casino_bank.check_server_settings(user.server)
  921. choice = cup
  922. choices = [1, 2, 3, 4]
  923. chip_name = settings["System Config"]["Chip Name"]
  924.  
  925. # Run a logic check to determine if the user can play the game
  926. check = self.game_checks(settings, ctx.prefix, user, bet, "Cups", choice, choices)
  927. if check:
  928. msg = check
  929. else: # Run the game when the checks return None
  930. self.casino_bank.withdraw_chips(user, bet)
  931. settings["Players"][user.id]["Played"]["Cups Played"] += 1
  932. outcome = random.randint(1, 4)
  933. await self.bot.say("The cups start shuffling along the table...")
  934. await asyncio.sleep(3)
  935.  
  936. # Begin game logic to determine a win or loss
  937. if cup == outcome:
  938. amount = int(round(bet * settings["Games"]["Cups"]["Multiplier"]))
  939. settings["Players"][user.id]["Won"]["Cups Won"] += 1
  940. msg = "Congratulations! The coin was under cup {}!".format(outcome)
  941.  
  942. # Check if a threshold is set and withold chips if amount is exceeded
  943. if self.threshold_check(settings, amount):
  944. settings["Players"][user.id]["Pending"] = amount
  945. msg += ("Your winnings exceeded the threshold set on this server. "
  946. "The amount of {} {} chips will be withheld until reviewed and "
  947. "released by an admin. Do not attempt to play additional games "
  948. "exceeding the threshold until this has been cleared."
  949. "".format(amount, chip_name, user.id))
  950. logger.info("{}({}) won {} chips exceeding the threshold. Game "
  951. "details:\nPlayer Cup: {}\nPlayer Bet: {}\nGame "
  952. "Outcome: {}\n[END OF REPORT]"
  953. "".format(user.name, user.id, amount, str(cup).ljust(10),
  954. str(bet).ljust(10), str(outcome).ljust(10)))
  955. else:
  956. self.casino_bank.deposit_chips(user, amount)
  957. msg += "```Python\nYou just won {} {} chips.```".format(amount, chip_name)
  958. else:
  959. msg = "Sorry! The coin was under cup {}.".format(outcome)
  960. # Save the results of the game
  961. self.casino_bank.save_system()
  962. # Send a message telling the user the outcome of this command
  963. await self.bot.say(msg)
  964.  
  965. @commands.command(pass_context=True, no_pm=True)
  966. @commands.cooldown(1, 5, commands.BucketType.user)
  967. async def coin(self, ctx, choice: str, bet: int):
  968. """Bet on heads or tails"""
  969.  
  970. # Declare variables for the game.
  971. user = ctx.message.author
  972. settings = self.casino_bank.check_server_settings(user.server)
  973. choice = choice.title()
  974. choices = ["Heads", "Tails"]
  975. chip_name = settings["System Config"]["Chip Name"]
  976.  
  977. # Run a logic check to determine if the user can play the game
  978. check = self.game_checks(settings, ctx.prefix, user, bet, "Coin", choice, choices)
  979. if check:
  980. msg = check
  981. else: # Run the game when the checks return None
  982. self.casino_bank.withdraw_chips(user, bet)
  983. settings["Players"][user.id]["Played"]["Coin Played"] += 1
  984. outcome = random.choice(["Heads", "Tails"])
  985. await self.bot.say("The coin flips into the air...")
  986. await asyncio.sleep(2)
  987.  
  988. # Begin game logic to determine a win or loss
  989. if choice == outcome:
  990. amount = int(round(bet * settings["Games"]["Coin"]["Multiplier"]))
  991. msg = "Congratulations! The coin landed on {}!".format(outcome)
  992. settings["Players"][user.id]["Won"]["Coin Won"] += 1
  993.  
  994. # Check if a threshold is set and withold chips if amount is exceeded
  995. if self.threshold_check(settings, amount):
  996. settings["Players"][user.id]["Pending"] = amount
  997. msg += ("\nYour winnings exceeded the threshold set on this server. "
  998. "The amount of {} {} chips will be withheld until reviewed and "
  999. "released by an admin. Do not attempt to play additional games "
  1000. "exceeding the threshold until this has been cleared."
  1001. "".format(amount, chip_name, user.id))
  1002. logger.info("{}({}) won {} chips exceeding the threshold. Game "
  1003. "details:\nPlayer Choice: {}\nPlayer Bet: {}\nGame "
  1004. "Outcome: {}\n[END OF REPORT]"
  1005. "".format(user.name, user.id, amount, choice.ljust(10),
  1006. str(bet).ljust(10), outcome[0].ljust(10)))
  1007. else:
  1008. self.casino_bank.deposit_chips(user, amount)
  1009. msg += "```Python\nYou just won {} {} chips.```".format(amount, chip_name)
  1010. else:
  1011. msg = "Sorry! The coin landed on {}.".format(outcome)
  1012. # Save the results of the game
  1013. self.casino_bank.save_system()
  1014. # Send a message telling the user the outcome of this command
  1015. await self.bot.say(msg)
  1016.  
  1017. @commands.command(pass_context=True, no_pm=True)
  1018. @commands.cooldown(1, 5, commands.BucketType.user)
  1019. async def dice(self, ctx, bet: int):
  1020. """Roll 2, 7, 11 or 12 to win."""
  1021.  
  1022. # Declare variables for the game.
  1023. user = ctx.message.author
  1024. settings = self.casino_bank.check_server_settings(user.server)
  1025. chip_name = settings["System Config"]["Chip Name"]
  1026.  
  1027. # Run a logic check to determine if the user can play the game
  1028. check = self.game_checks(settings, ctx.prefix, user, bet, "Dice", 1, [1])
  1029. if check:
  1030. msg = check
  1031. else: # Run the game when the checks return None
  1032. self.casino_bank.withdraw_chips(user, bet)
  1033. settings["Players"][user.id]["Played"]["Dice Played"] += 1
  1034. await self.bot.say("The dice strike the back of the table and begin to tumble into "
  1035. "place...")
  1036. die_one = random.randint(1, 6)
  1037. die_two = random.randint(1, 6)
  1038. outcome = die_one + die_two
  1039. await asyncio.sleep(2)
  1040.  
  1041. # Begin game logic to determine a win or loss
  1042. msg = "The dice landed on {} and {} \n".format(die_one, die_two)
  1043. if outcome in [2, 7, 11, 12]:
  1044. amount = int(round(bet * settings["Games"]["Dice"]["Multiplier"]))
  1045. settings["Players"][user.id]["Won"]["Dice Won"] += 1
  1046.  
  1047. msg += "Congratulations! The dice landed on {}.".format(outcome)
  1048.  
  1049. # Check if a threshold is set and withold chips if amount is exceeded
  1050. if self.threshold_check(settings, amount):
  1051. settings["Players"][user.id]["Pending"] = amount
  1052. msg += ("\nYour winnings exceeded the threshold set on this server. "
  1053. "The amount of {} {} chips will be withheld until reviewed and "
  1054. "released by an admin. Do not attempt to play additional games "
  1055. "exceeding the threshold until this has been cleared."
  1056. "".format(amount, chip_name, user.id))
  1057. logger.info("{}({}) won {} chips exceeding the threshold. Game "
  1058. "details:\nPlayer Bet: {}\nGame "
  1059. "Outcome: {}\n[END OF FILE]".format(user.name, user.id, amount,
  1060. str(bet).ljust(10),
  1061. str(outcome[0]).ljust(10)))
  1062. else:
  1063. self.casino_bank.deposit_chips(user, amount)
  1064. msg += "```Python\nYou just won {} {} chips.```".format(amount, chip_name)
  1065. else:
  1066. msg += "Sorry! The result was {}.".format(outcome)
  1067. # Save the results of the game
  1068. self.casino_bank.save_system()
  1069. # Send a message telling the user the outcome of this command
  1070. await self.bot.say(msg)
  1071.  
  1072. @commands.command(pass_context=True, no_pm=True)
  1073. @commands.cooldown(1, 5, commands.BucketType.user)
  1074. async def war(self, ctx, bet: int):
  1075. """Modified War Card Game."""
  1076.  
  1077. # Declare Variables for the game.
  1078. user = ctx.message.author
  1079. settings = self.casino_bank.check_server_settings(user.server)
  1080.  
  1081. # Run a logic check to determine if the user can play the game
  1082. check = self.game_checks(settings, ctx.prefix, user, bet, "War", 1, [1])
  1083. if check:
  1084. msg = check
  1085. else: # Run the game when the checks return None
  1086. self.casino_bank.withdraw_chips(user, bet)
  1087. settings["Players"][user.id]["Played"]["War Played"] += 1
  1088. deck = main_deck[:] # Make a copy of the deck so we can remove cards that are drawn
  1089. outcome, player_card, dealer_card, amount = await self.war_game(user, settings, deck,
  1090. bet)
  1091. msg = self.war_results(settings, user, outcome, player_card, dealer_card, amount)
  1092. await self.bot.say(msg)
  1093.  
  1094. @commands.command(pass_context=True, no_pm=True, aliases=["bj", "21"])
  1095. @commands.cooldown(1, 5, commands.BucketType.user)
  1096. async def blackjack(self, ctx, bet: int):
  1097. """Modified Blackjack."""
  1098.  
  1099. # Declare variables for the game.
  1100. user = ctx.message.author
  1101. settings = self.casino_bank.check_server_settings(user.server)
  1102.  
  1103. # Run a logic check to determine if the user can play the game
  1104. check = self.game_checks(settings, ctx.prefix, user, bet, "Blackjack", 1, [1])
  1105. if check:
  1106. msg = check
  1107. else: # Run the game when the checks return None
  1108. self.casino_bank.withdraw_chips(user, bet)
  1109. settings["Players"][user.id]["Played"]["BJ Played"] += 1
  1110. deck = main_deck[:] # Make a copy of the deck so we can remove cards that are drawn
  1111. dhand = self.dealer(deck)
  1112. ph, dh, amt = await self.blackjack_game(dhand, user, bet, deck)
  1113. msg = self.blackjack_results(settings, user, amt, ph, dh)
  1114. # Send a message telling the user the outcome of this command
  1115. await self.bot.say(msg)
  1116.  
  1117. @commands.command(pass_context=True, no_pm=True)
  1118. @commands.cooldown(1, 5, commands.BucketType.user)
  1119. async def allin(self, ctx, multiplier: int):
  1120. """It's all or nothing. Bets everything you have."""
  1121.  
  1122. # Declare variables for the game.
  1123. user = ctx.message.author
  1124. settings = self.casino_bank.check_server_settings(user.server)
  1125. chip_name = settings["System Config"]["Chip Name"]
  1126.  
  1127. if not self.casino_bank.membership_exists(user):
  1128. return await self.bot.say("You need to register. Type "
  1129. "{}casino join.".format(ctx.prefix))
  1130.  
  1131. # Run a logic check to determine if the user can play the game.
  1132. check = self.game_checks(settings, ctx.prefix, user, 0, "Allin", 1, [1])
  1133. if check:
  1134. msg = check
  1135. else: # Run the game when the checks return None.
  1136. # Setup the game to determine an outcome.
  1137. settings["Players"][user.id]["Played"]["Allin Played"] += 1
  1138. amount = int(round(multiplier * settings["Players"][user.id]["Chips"]))
  1139. balance = self.casino_bank.chip_balance(user)
  1140. outcome = random.randint(0, multiplier + 1)
  1141. self.casino_bank.withdraw_chips(user, balance)
  1142. await self.bot.say("You put all your chips into the machine and pull the lever...")
  1143. await asyncio.sleep(3)
  1144.  
  1145. # Begin game logic to determine a win or loss.
  1146. if outcome == 0:
  1147. self.casino_bank.deposit_chips(user, amount)
  1148. msg = "```Python\nJackpot!! You just won {} {} chips!!```".format(amount, chip_name)
  1149. settings["Players"][user.id]["Won"]["Allin Won"] += 1
  1150. else:
  1151. msg = ("Sorry! Your all or nothing gamble failed and you lost "
  1152. "all your {} chips.".format(chip_name))
  1153. # Save the results of the game
  1154. self.casino_bank.save_system()
  1155. # Send a message telling the user the outcome of this command
  1156. await self.bot.say(msg)
  1157.  
  1158. @casino.command(name="version")
  1159. @checks.admin_or_permissions(manage_server=True)
  1160. async def _version_casino(self):
  1161. """Shows current Casino version"""
  1162. await self.bot.say("You are currently running Casino version {}.".format(self.version))
  1163.  
  1164. @casino.command(name="cdreset", pass_context=True)
  1165. @checks.admin_or_permissions(manage_server=True)
  1166. async def _cdreset_casino(self, ctx):
  1167. """Resets all cooldowns on the server"""
  1168. server = ctx.message.server
  1169. settings = self.casino_bank.check_server_settings(server)
  1170. cd_dict = {"Dice": 0, "Cups": 0, "Coin": 0, "Allin": 0, "Hi-Lo": 0, "War": 0,
  1171. "Blackjack": 0, "Payday": 0}
  1172.  
  1173. for player in settings["Players"]:
  1174. settings["Players"][player]["Cooldowns"] = cd_dict
  1175.  
  1176. self.casino_bank.save_system()
  1177. await self.bot.say("Cooldowns have been reset for all users on this server.")
  1178.  
  1179. @casino.command(name="removemembership", pass_context=True)
  1180. @checks.admin_or_permissions(manage_server=True)
  1181. async def _removemembership_casino(self, ctx, *, membership):
  1182. """Remove a casino membership"""
  1183. author = ctx.message.author
  1184. settings = self.casino_bank.check_server_settings(author.server)
  1185.  
  1186. if membership in settings["Memberships"]:
  1187. settings["Memberships"].pop(membership)
  1188. msg = "{} removed from the list of membership.".format(membership)
  1189. else:
  1190. msg = "Could not find a membership with that name."
  1191.  
  1192. await self.bot.say(msg)
  1193.  
  1194. @casino.command(name="createmembership", pass_context=True)
  1195. @checks.admin_or_permissions(manage_server=True)
  1196. async def _createmembership_casino(self, ctx):
  1197. """Add a casino membership to reward continued play"""
  1198.  
  1199. # Declare variables
  1200. author = ctx.message.author
  1201. settings = self.casino_bank.check_server_settings(author.server)
  1202. cancel = ctx.prefix + "cancel"
  1203. requirement_list = ["Days On Server", "Credits", "Chips", "Role"]
  1204. colors = ["blue", "red", "green", "orange", "purple", "yellow", "turquoise", "teal",
  1205. "magenta", "pink", "white"]
  1206. server_roles = [r.name for r in ctx.message.server.roles if r.name != "Bot"]
  1207.  
  1208. # Various checks for the different questions
  1209. check1 = lambda m: m.content.isdigit() and int(m.content) > 0 or m.content == cancel
  1210. check2 = lambda m: m.content.isdigit() or m.content == cancel
  1211. check3 = lambda m: m.content.title() in requirement_list or m.content == cancel
  1212. check4 = lambda m: m.content.isdigit() or m.content in server_roles or m.content == cancel
  1213. check5 = lambda m: m.content.lower() in colors or m.content == cancel
  1214.  
  1215. start = ("Welcome to the membership creation process. This will create a membership to "
  1216. "provide benefits to your members such as reduced cooldowns and access levels.\n"
  1217. "You may cancel this process at anytime by typing {}cancel. Let's begin with the "
  1218. "first question.\n\nWhat is the name of this membership? Examples: Silver, Gold, "
  1219. "and Diamond.".format(ctx.prefix))
  1220.  
  1221. # Begin creation process
  1222. await self.bot.say(start)
  1223. name = await self.bot.wait_for_message(timeout=35, author=author)
  1224.  
  1225. if name is None:
  1226. await self.bot.say("You took too long. Cancelling membership creation.")
  1227. return
  1228.  
  1229. if name.content == cancel:
  1230. await self.bot.say("Membership creation cancelled.")
  1231. return
  1232.  
  1233. if name.content.title() in settings["Memberships"]:
  1234. await self.bot.say("A membership with that name already exists. Cancelling creation.")
  1235. return
  1236.  
  1237. await self.bot.say("What is the color for this membership? This color appears in the "
  1238. "{}casino stats command.\nPlease pick from these colors: "
  1239. "```{}```".format(ctx.prefix, ", ".join(colors)))
  1240. color = await self.bot.wait_for_message(timeout=35, author=author, check=check5)
  1241.  
  1242. if color is None:
  1243. await self.bot.say("You took too long. Cancelling membership creation.")
  1244. return
  1245.  
  1246. if color.content == cancel:
  1247. await self.bot.say("Membership creation cancelled.")
  1248. return
  1249.  
  1250. await self.bot.say("What is the payday amount for this membership?")
  1251. payday = await self.bot.wait_for_message(timeout=35, author=author, check=check1)
  1252.  
  1253. if payday is None:
  1254. await self.bot.say("You took too long. Cancelling membership creation.")
  1255. return
  1256.  
  1257. if payday.content == cancel:
  1258. await self.bot.say("Membership creation cancelled.")
  1259. return
  1260.  
  1261. await self.bot.say("What is the cooldown reduction for this membership in seconds? 0 for "
  1262. "none")
  1263. reduction = await self.bot.wait_for_message(timeout=35, author=author, check=check2)
  1264.  
  1265. if reduction is None:
  1266. await self.bot.say("You took too long. Cancelling membership creation.")
  1267. return
  1268.  
  1269. if reduction.content == cancel:
  1270. await self.bot.say("membership creation cancelled.")
  1271. return
  1272.  
  1273. await self.bot.say("What is the access level for this membership? 0 is the default access "
  1274. "level for new members. Access levels can be used to restrict access to "
  1275. "games. See `{}setcasino access` for more info.".format(ctx.prefix))
  1276.  
  1277. access = await self.bot.wait_for_message(timeout=35, author=author, check=check1)
  1278.  
  1279. if access is None:
  1280. await self.bot.say("You took too long. Cancelling membership creation.")
  1281. return
  1282.  
  1283. if access.content == cancel:
  1284. await self.bot.say("Membership creation cancelled.")
  1285. return
  1286.  
  1287. if int(access.content) in [x["Access"] for x in settings["Memberships"].values()]:
  1288. await self.bot.say("You cannot have memberships with the same access level. Cancelling "
  1289. "creation.")
  1290. return
  1291.  
  1292. await self.bot.say("What is the requirement for this membership? Available options are:```"
  1293. "Days on server, Credits, Chips, or Role```Which would you "
  1294. "like set? You can always remove and add additional requirements later"
  1295. "using `{0}setcasino addrequirements` and "
  1296. "`{0}setcasino removerequirements`.".format(ctx.prefix))
  1297. req_type = await self.bot.wait_for_message(timeout=35, author=author, check=check3)
  1298.  
  1299. if req_type is None:
  1300. await self.bot.say("You took too long. Cancelling membership creation.")
  1301. return
  1302.  
  1303. if req_type.content == cancel:
  1304. await self.bot.say("Membership creation cancelled.")
  1305. return
  1306.  
  1307. await self.bot.say("What is the number of days, chips, credits or role name you would like "
  1308. "set?")
  1309. req_val = await self.bot.wait_for_message(timeout=35, author=author, check=check4)
  1310.  
  1311. if req_val is None:
  1312. await self.bot.say("You took too long. Cancelling membership creation.")
  1313. return
  1314.  
  1315. if req_val.content == cancel:
  1316. await self.bot.say("Membership creation cancelled.")
  1317. return
  1318. else:
  1319.  
  1320. if req_val.content.isdigit():
  1321. req_val = int(req_val.content)
  1322. else:
  1323. req_val = req_val.content
  1324.  
  1325. params = [name.content, color.content, payday.content, reduction.content,
  1326. access.content, req_val]
  1327. msg = ("Membership successfully created. Please review the details below.\n"
  1328. "```Name: {0}\nColor: {1}\nPayday: {2}\nCooldown Reduction: {3}\n"
  1329. "Access Level: {4}\n".format(*params))
  1330. msg += "Requirement: {} {}```".format(req_val, req_type.content.title())
  1331.  
  1332. memberships = {"Payday": int(payday.content), "Access": int(access.content),
  1333. "Cooldown Reduction": int(reduction.content), "Color": color.content,
  1334. "Requirements": {req_type.content.title(): req_val}}
  1335. settings["Memberships"][name.content.title()] = memberships
  1336. self.casino_bank.save_system()
  1337. await self.bot.say(msg)
  1338.  
  1339. @casino.command(name="reset", pass_context=True)
  1340. @checks.admin_or_permissions(manage_server=True)
  1341. async def _reset_casino(self, ctx):
  1342. """Resets casino to default settings. Keeps user data"""
  1343.  
  1344. user = ctx.message.author
  1345. settings = self.casino_bank.check_server_settings(user.server)
  1346. await self.bot.say("This will reset casino to it's default settings and keep player data.\n"
  1347. "Do you wish to reset casino settings?")
  1348. response = await self.bot.wait_for_message(timeout=15, author=user)
  1349.  
  1350. if response is None:
  1351. msg = "No response, reset cancelled."
  1352. elif response.content.title() == "No":
  1353. msg = "Cancelling reset."
  1354. elif response.content.title() == "Yes":
  1355. settings["System Config"] = server_default["System Config"]
  1356. settings["Games"] = server_default["Games"]
  1357. self.casino_bank.save_system()
  1358. msg = "Casino settings reset to default."
  1359. else:
  1360. msg = "Improper response. Cancelling reset."
  1361. await self.bot.say(msg)
  1362.  
  1363. @casino.command(name="toggle", pass_context=True)
  1364. @checks.admin_or_permissions(manage_server=True)
  1365. async def _toggle_casino(self, ctx):
  1366. """Opens and closes the casino"""
  1367.  
  1368. server = ctx.message.server
  1369. settings = self.casino_bank.check_server_settings(server)
  1370. casino_name = settings["System Config"]["Casino Name"]
  1371.  
  1372. if settings["System Config"]["Casino Open"]:
  1373. settings["System Config"]["Casino Open"] = False
  1374. msg = "The {} Casino is now closed.".format(casino_name)
  1375. else:
  1376. settings["System Config"]["Casino Open"] = True
  1377. msg = "The {} Casino is now open!".format(casino_name)
  1378. self.casino_bank.save_system()
  1379. await self.bot.say(msg)
  1380.  
  1381. @casino.command(name="approve", pass_context=True)
  1382. @checks.admin_or_permissions(manage_server=True)
  1383. async def _approve_casino(self, ctx, user: discord.Member):
  1384. """Approve a user's pending chips."""
  1385. author = ctx.message.author
  1386. settings = self.casino_bank.check_server_settings(author.server)
  1387. chip_name = settings["System Config"]["Chip Name"]
  1388. if self.casino_bank.membership_exists(user):
  1389. amount = settings["Players"][user.id]["Pending"]
  1390. if amount > 0:
  1391. await self.bot.say("{} has a pending amount of {}. Do you wish to approve this "
  1392. "amount?".format(user.name, amount))
  1393. response = await self.bot.wait_for_message(timeout=15, author=author)
  1394.  
  1395. if response is None:
  1396. await self.bot.say("You took too long. Cancelling pending chip approval.")
  1397. return
  1398.  
  1399. if response.content.title() in ["No", "Cancel", "Stop"]:
  1400. await self.bot.say("Cancelling pending chip approval.")
  1401. return
  1402.  
  1403. if response.content.title() in ["Yes", "Approve"]:
  1404. await self.bot.say("{} approved the pending chips. Sending {} {} chips to "
  1405. " {}.".format(author.name, amount, chip_name, user.name))
  1406. self.casino_bank.deposit_chips(user, amount)
  1407. else:
  1408. await self.bot.say("Incorrect response. Cancelling pending chip approval.")
  1409. return
  1410. else:
  1411. await self.bot.say("{} does not have any chips pending.".format(user.name))
  1412.  
  1413. @casino.command(name="removeuser", pass_context=True)
  1414. @checks.admin_or_permissions(manage_server=True)
  1415. async def _removeuser_casino(self, ctx, user: discord.Member):
  1416. """Remove a user from casino"""
  1417. author = ctx.message.author
  1418. self.casino_bank.check_server_settings(author.server)
  1419.  
  1420. if not self.casino_bank.membership_exists(user):
  1421. msg = "This user is not a member of the casino."
  1422. else:
  1423. await self.bot.say("Are you sure you want to remove player data for {}? Type {} to "
  1424. "confirm.".format(user.name, user.name))
  1425. response = await self.bot.wait_for_message(timeout=15, author=author)
  1426. if response is None:
  1427. msg = "No response. Player removal cancelled."
  1428. elif response.content.title() == user.name:
  1429. self.casino_bank.remove_membership(user)
  1430. msg = "{}\'s casino data has been removed by {}.".format(user.name, author.name)
  1431. else:
  1432. msg = "Incorrect name. Cancelling player removal."
  1433. await self.bot.say(msg)
  1434.  
  1435. @casino.command(name="wipe", pass_context=True)
  1436. @checks.is_owner()
  1437. async def _wipe_casino(self, ctx, *, servername: str):
  1438. """Wipe casino server data. Case Sensitive"""
  1439. user = ctx.message.author
  1440. servers = self.casino_bank.get_all_servers()
  1441. server_list = [self.bot.get_server(x).name for x in servers
  1442. if hasattr(self.bot.get_server(x), 'name')]
  1443. fmt_list = ["{}: {}".format(idx + 1, x) for idx, x in enumerate(server_list)]
  1444. try:
  1445. server = [self.bot.get_server(x) for x in servers
  1446. if self.bot.get_server(x).name == servername][0]
  1447. except AttributeError:
  1448. msg = ("A server with that name could not be located.\n**List of "
  1449. "Servers:**")
  1450. if len(fmt_list) > 25:
  1451. fmt_list = fmt_list[:25]
  1452. msg += "\n\n{}".format('\n'.join(fmt_list))
  1453. msg += "\nThere are too many server names to display, displaying first 25."
  1454. else:
  1455. msg += "\n\n{}".format('\n'.join(fmt_list))
  1456.  
  1457. return await self.bot.say(msg)
  1458.  
  1459. await self.bot.say("This will wipe casino server data.**WARNING** ALL PLAYER DATA WILL "
  1460. "BE DESTROYED.\nDo you wish to wipe {}?".format(server.name))
  1461. response = await self.bot.wait_for_message(timeout=15, author=user)
  1462.  
  1463. if response is None:
  1464. msg = "No response, casino wipe cancelled."
  1465. elif response.content.title() == "No":
  1466. msg = "Cancelling casino wipe."
  1467. elif response.content.title() == "Yes":
  1468. await self.bot.say("To confirm type the server name: {}".format(server.name))
  1469. response = await self.bot.wait_for_message(timeout=15, author=user)
  1470. if response is None:
  1471. msg = "No response, casino wipe cancelled."
  1472. elif response.content == server.name:
  1473. self.casino_bank.wipe_caisno_server(server)
  1474. msg = "Casino wiped."
  1475. else:
  1476. msg = "Incorrect server name. Cancelling casino wipe."
  1477. else:
  1478. msg = "Improper response. Cancelling casino wipe."
  1479.  
  1480. await self.bot.say(msg)
  1481.  
  1482. @commands.group(pass_context=True, no_pm=True)
  1483. async def setcasino(self, ctx):
  1484. """Configures Casino Options"""
  1485. if ctx.invoked_subcommand is None:
  1486. await send_cmd_help(ctx)
  1487.  
  1488. @setcasino.command(name="transferlimit", pass_context=True)
  1489. @checks.admin_or_permissions(manage_server=True)
  1490. async def _xferlimit_setcasino(self, ctx, limit: int):
  1491. """This is the limit of chips a player can transfer at one time.
  1492.  
  1493. Remember, that without a cooldown, a player can still use this command
  1494. over and over. This is just to prevent a transfer of outrageous amounts.
  1495.  
  1496. """
  1497. author = ctx.message.author
  1498. settings = self.casino_bank.check_server_settings(author.server)
  1499.  
  1500. if limit > 0:
  1501. settings["System Config"]["Transfer Limit"] = limit
  1502. msg = "{} set transfer limit to {}.".format(author.name, limit)
  1503. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1504. self.casino_bank.save_system()
  1505. else:
  1506. msg = "Limit must be higher than 0."
  1507.  
  1508. await self.bot.say(msg)
  1509.  
  1510. @setcasino.command(name="transfercd", pass_context=True)
  1511. @checks.admin_or_permissions(manage_server=True)
  1512. async def _xcdlimit_setcasino(self, ctx, seconds: int):
  1513. """Set the cooldown for transferring chips.
  1514.  
  1515. There is already a five second cooldown in place. Use this to prevent
  1516. users from circumventing the transfer limit through spamming. Default
  1517. is set to 30 seconds.
  1518.  
  1519. """
  1520. author = ctx.message.author
  1521. settings = self.casino_bank.check_server_settings(author.server)
  1522.  
  1523. if seconds > 0:
  1524. settings["System Config"]["Transfer Cooldown"] = seconds
  1525. time_fmt = self.time_format(seconds)
  1526. msg = "{} set transfer cooldown to {}.".format(author.name, time_fmt)
  1527. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1528. self.casino_bank.save_system()
  1529. else:
  1530. msg = "Seconds must be higher than 0."
  1531.  
  1532. await self.bot.say(msg)
  1533.  
  1534. @setcasino.command(name="threshold", pass_context=True)
  1535. @checks.admin_or_permissions(manage_server=True)
  1536. async def _threshold_setcasino(self, ctx, threshold: int):
  1537. """Players that exceed this amount require an admin to approve the payout"""
  1538. author = ctx.message.author
  1539. settings = self.casino_bank.check_server_settings(author.server)
  1540.  
  1541. if threshold > 0:
  1542. settings["System Config"]["Threshold"] = threshold
  1543. msg = "{} set payout threshold to {}.".format(author.name, threshold)
  1544. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1545. self.casino_bank.save_system()
  1546. else:
  1547. msg = "Threshold amount needs to be higher than 0."
  1548.  
  1549. await self.bot.say(msg)
  1550.  
  1551. @setcasino.command(name="thresholdtoggle", pass_context=True)
  1552. @checks.admin_or_permissions(manage_server=True)
  1553. async def _threshholdtoggle_setcasino(self, ctx):
  1554. """Turns on a chip win limit"""
  1555. author = ctx.message.author
  1556. settings = self.casino_bank.check_server_settings(author.server)
  1557.  
  1558. if settings["System Config"]["Threshold Switch"]:
  1559. msg = "{} turned the threshold OFF.".format(author.name)
  1560. settings["System Config"]["Threshold Switch"] = False
  1561. else:
  1562. msg = "{} turned the threshold ON.".format(author.name)
  1563. settings["System Config"]["Threshold Switch"] = True
  1564.  
  1565. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1566. self.casino_bank.save_system()
  1567. await self.bot.say(msg)
  1568.  
  1569. @setcasino.command(name="payday", pass_context=True)
  1570. @checks.admin_or_permissions(manage_server=True)
  1571. async def _payday_setcasino(self, ctx, amount: int):
  1572. """Set the default payday amount with no membership
  1573.  
  1574. This amount is what users who have no membership will receive. If the
  1575. user has a membership it will be based on what payday amount that was set
  1576. for it.
  1577. """
  1578.  
  1579. author = ctx.message.author
  1580. settings = self.casino_bank.check_server_settings(author.server)
  1581. chip_name = settings["System Config"]["Chip Name"]
  1582.  
  1583. if amount >= 0:
  1584. settings["System Config"]["Default Payday"] = amount
  1585. self.casino_bank.save_system()
  1586. msg = "{} set the default payday to {} {} chips.".format(author.name, amount, chip_name)
  1587. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1588. else:
  1589. msg = "You cannot set a negative number to payday."
  1590.  
  1591. await self.bot.say(msg)
  1592.  
  1593. @setcasino.command(name="paydaytimer", pass_context=True)
  1594. @checks.admin_or_permissions(manage_server=True)
  1595. async def _paydaytimer_setcasino(self, ctx, seconds: int):
  1596. """Set the cooldown on payday
  1597.  
  1598. This timer is not affected by cooldown reduction from membership.
  1599. """
  1600.  
  1601. author = ctx.message.author
  1602. settings = self.casino_bank.check_server_settings(author.server)
  1603.  
  1604. if seconds >= 0:
  1605. settings["System Config"]["Payday Timer"] = seconds
  1606. self.casino_bank.save_system()
  1607. time_set = self.time_format(seconds)
  1608. msg = "{} set the default payday to {}.".format(author.name, time_set)
  1609. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1610. else:
  1611. msg = ("You cannot set a negative number to payday timer. That would be like going back"
  1612. " in time. Which would be totally cool, but I don't understand the physics of "
  1613. "how it might apply in this case. One would assume you would go back in time to "
  1614. "the point in which you could receive a payday, but it is actually quite the "
  1615. "opposite. You would go back to the point where you were about to claim a "
  1616. "payday and thus claim it again, but unfortunately your total would not receive "
  1617. "a net gain, because you are robbing from yourself. Next time think before you "
  1618. "do something so stupid.")
  1619.  
  1620. await self.bot.say(msg)
  1621.  
  1622. @setcasino.command(name="multiplier", pass_context=True)
  1623. @checks.admin_or_permissions(manage_server=True)
  1624. async def _multiplier_setcasino(self, ctx, game: str, multiplier: float):
  1625. """Sets the payout multiplier for casino games"""
  1626. author = ctx.message.author
  1627. settings = self.casino_bank.check_server_settings(author.server)
  1628.  
  1629. if game.title() not in c_games:
  1630. msg = "This game does not exist. Please pick from: {}".format(", ".join(c_games))
  1631. elif multiplier > 0:
  1632. multiplier = float(abs(multiplier))
  1633. settings["Games"][game.title()]["Multiplier"] = multiplier
  1634. self.casino_bank.save_system()
  1635. msg = "Now setting the payout multiplier for {} to {}".format(game, multiplier)
  1636. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1637. else:
  1638. msg = "Multiplier needs to be higher than 0."
  1639.  
  1640. await self.bot.say(msg)
  1641.  
  1642. @setcasino.command(name="access", pass_context=True)
  1643. @checks.admin_or_permissions(manage_server=True)
  1644. async def _access_setcasino(self, ctx, game: str, access: int):
  1645. """Set the access level for a game. Default is 0. Used with membership."""
  1646.  
  1647. author = ctx.message.author
  1648. settings = self.casino_bank.check_server_settings(author.server)
  1649. game = game.title()
  1650.  
  1651. if game not in c_games:
  1652. msg = "This game does not exist. Please pick from: {}".format(", ".join(c_games))
  1653. elif access >= 0:
  1654. settings["Games"][game.title()]["Access Level"] = access
  1655. self.casino_bank.save_system()
  1656. msg = "{} changed the access level for {} to {}.".format(author.name, game, access)
  1657. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1658. else:
  1659. msg = "Access level must be higher than 0."
  1660.  
  1661. await self.bot.say(msg)
  1662.  
  1663. @setcasino.command(name="reqadd", pass_context=True)
  1664. @checks.admin_or_permissions(manage_server=True)
  1665. async def _reqadd_setcasino(self, ctx, *, membership):
  1666. """Add a requirement to a membership"""
  1667.  
  1668. # Declare variables
  1669. author = ctx.message.author
  1670. settings = self.casino_bank.check_server_settings(author.server)
  1671. cancel_message = "You took too long to respond. Cancelling requirement addition."
  1672. requirement_options = ["Days On Server", "Credits", "Chips", "Role"]
  1673. server_roles = [r.name for r in ctx.message.server.roles if r.name != "Bot"]
  1674.  
  1675. # Message checks
  1676. check1 = lambda m: m.content.title() in requirement_options
  1677. check2 = lambda m: m.content.isdigit() and int(m.content) > 0
  1678. check3 = lambda m: m.content in server_roles
  1679.  
  1680. # Begin logic
  1681. if membership not in settings["Memberships"]:
  1682. await self.bot.say("This membership does not exist.")
  1683. else:
  1684.  
  1685. await self.bot.say("Which of these requirements would you like to add to the {} "
  1686. " membership?```{}.```NOTE: You cannot have multiple requirements of"
  1687. " the same type.".format(membership, ', '.join(requirement_options)))
  1688. rsp = await self.bot.wait_for_message(timeout=15, author=author, check=check1)
  1689.  
  1690. if rsp is None:
  1691. await self.bot.say(cancel_message)
  1692. return
  1693.  
  1694. else:
  1695. # Determine amount for DoS, Credits, or Chips
  1696. if rsp.content.title() != "Role":
  1697. name = rsp.content.split(' ', 1)[0]
  1698. await self.bot.say("How many {} are required?".format(name))
  1699. reply = await self.bot.wait_for_message(timeout=15, author=author, check=check2)
  1700.  
  1701. if reply is None:
  1702. await self.bot.say(cancel_message)
  1703. return
  1704. else:
  1705. await self.bot.say("Adding the requirement of {} {} to the membership "
  1706. "{}.".format(reply.content, rsp.content, membership))
  1707. reply = int(reply.content)
  1708.  
  1709. # Determine the role for the requirement
  1710. else:
  1711. await self.bot.say("Which role would you like set? This role must already be "
  1712. "set on server.")
  1713. reply = await self.bot.wait_for_message(timeout=15, author=author, check=check3)
  1714.  
  1715. if reply is None:
  1716. await self.bot.say(cancel_message)
  1717. return
  1718. else:
  1719. await self.bot.say("Adding the requirement role of {} to the membership "
  1720. "{}.".format(reply.content, membership))
  1721. reply = reply.content
  1722.  
  1723. # Add and save the requirement
  1724. key = rsp.content.title()
  1725. settings["Memberships"][membership]["Requirements"][key] = reply
  1726. self.casino_bank.save_system()
  1727.  
  1728. @setcasino.command(name="reqremove", pass_context=True)
  1729. @checks.admin_or_permissions(manage_server=True)
  1730. async def _reqremove_setcasino(self, ctx, *, membership):
  1731. """Remove a requirement to a membership"""
  1732.  
  1733. # Declare variables
  1734. author = ctx.message.author
  1735. settings = self.casino_bank.check_server_settings(author.server)
  1736.  
  1737. if membership not in settings["Memberships"]:
  1738. await self.bot.say("This membership does not exist.")
  1739. else: # Membership was found.
  1740. current_requirements = settings["Memberships"][membership]["Requirements"].keys()
  1741.  
  1742. if not current_requirements:
  1743. return await self.bot.say("This membership has no requirements.")
  1744.  
  1745. check = lambda m: m.content.title() in current_requirements
  1746.  
  1747. await self.bot.say("The current requirements for this membership are:\n```{}```Which "
  1748. "would you like to remove?".format(", ".join(current_requirements)))
  1749. resp = await self.bot.wait_for_message(timeout=15, author=author, check=check)
  1750.  
  1751. if resp is None:
  1752. return await self.bot.say("You took too long. Cancelling requirement removal.")
  1753. else:
  1754. settings["Memberships"][membership]["Requirements"].pop(resp.content.title())
  1755. self.casino_bank.save_system()
  1756. await self.bot.say("{} requirement removed from {}.".format(resp.content.title(),
  1757. membership))
  1758.  
  1759. @setcasino.command(name="balance", pass_context=True)
  1760. @checks.admin_or_permissions(manage_server=True)
  1761. async def _balance_setcasino(self, ctx, user: discord.Member, chips: int):
  1762. """Sets a Casino member's chip balance"""
  1763. author = ctx.message.author
  1764. settings = self.casino_bank.check_server_settings(author.server)
  1765. chip_name = settings["System Config"]["Chip Name"]
  1766. casino_name = settings["System Config"]["Casino Name"]
  1767. try:
  1768. self.casino_bank.set_chips(user, chips)
  1769. except NegativeChips:
  1770. return await self.bot.say("Chips must be higher than 0.")
  1771. except UserNotRegistered:
  1772. return await self.bot.say("You need to register to the {} Casino. To register type "
  1773. "`{}casino join`.".format(casino_name, ctx.prefix))
  1774. else:
  1775. logger.info("SETTINGS CHANGED {}({}) set {}({}) chip balance to "
  1776. "{}".format(author.name, author.id, user.name, user.id, chips))
  1777. await self.bot.say("```Python\nSetting the chip balance of {} to "
  1778. "{} {} chips.```".format(user.name, chips, chip_name))
  1779.  
  1780. @setcasino.command(name="exchange", pass_context=True)
  1781. @checks.admin_or_permissions(manage_server=True)
  1782. async def _exchange_setcasino(self, ctx, rate: float, currency: str):
  1783. """Sets the exchange rate for chips or credits"""
  1784. author = ctx.message.author
  1785. settings = self.casino_bank.check_server_settings(author.server)
  1786.  
  1787. if rate <= 0:
  1788. msg = "Rate must be higher than 0. Default is 1."
  1789. elif currency.title() == "Chips":
  1790. settings["System Config"]["Chip Rate"] = rate
  1791. logger.info("{}({}) changed the chip rate to {}".format(author.name, author.id, rate))
  1792. self.casino_bank.save_system()
  1793. msg = "Setting the exchange rate for credits to chips to {}.".format(rate)
  1794. elif currency.title() == "Credits":
  1795. settings["System Config"]["Credit Rate"] = rate
  1796. logger.info("SETTINGS CHANGED {}({}) changed the credit rate to "
  1797. "{}".format(author.name, author.id, rate))
  1798. self.casino_bank.save_system()
  1799. msg = "Setting the exchange rate for chips to credits to {}.".format(rate)
  1800. else:
  1801. msg = "Please specify chips or credits"
  1802.  
  1803. await self.bot.say(msg)
  1804.  
  1805. @setcasino.command(name="name", pass_context=True)
  1806. @checks.admin_or_permissions(manage_server=True)
  1807. async def _name_setcasino(self, ctx, *, name: str):
  1808. """Sets the name of the Casino."""
  1809. author = ctx.message.author
  1810. settings = self.casino_bank.check_server_settings(author.server)
  1811. settings["System Config"]["Casino Name"] = name
  1812. self.casino_bank.save_system()
  1813. msg = "Changed the casino name to {}.".format(name)
  1814. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1815. await self.bot.say(msg)
  1816.  
  1817. @setcasino.command(name="chipname", pass_context=True)
  1818. @checks.admin_or_permissions(manage_server=True)
  1819. async def _chipname_setcasino(self, ctx, *, name: str):
  1820. """Sets the name of your Casino chips."""
  1821. author = ctx.message.author
  1822. settings = self.casino_bank.check_server_settings(author.server)
  1823. settings["System Config"]["Chip Name"] = name
  1824. self.casino_bank.save_system()
  1825. msg = ("Changed the name of your chips to {0}.\nTest Display:\n"
  1826. "```Python\nCongratulations, you just won 50 {0} chips.```".format(name))
  1827. logger.info("SETTINGS CHANGED {}({}) chip name set to "
  1828. "{}".format(author.name, author.id, name))
  1829.  
  1830. await self.bot.say(msg)
  1831.  
  1832. @setcasino.command(name="cooldown", pass_context=True)
  1833. @checks.admin_or_permissions(manage_server=True)
  1834. async def _cooldown_setcasino(self, ctx, game, seconds: int):
  1835. """Set the cooldown period for casino games"""
  1836. author = ctx.message.author
  1837. settings = self.casino_bank.check_server_settings(author.server)
  1838.  
  1839. if game.title() not in c_games:
  1840. msg = "This game does not exist. Please pick from: {}".format(", ".join(c_games))
  1841. else:
  1842. settings["Games"][game.title()]["Cooldown"] = seconds
  1843. time_set = self.time_format(seconds)
  1844. self.casino_bank.save_system()
  1845. msg = "Setting the cooldown period for {} to {}.".format(game, time_set)
  1846. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1847.  
  1848. await self.bot.say(msg)
  1849.  
  1850. @setcasino.command(name="min", pass_context=True)
  1851. @checks.admin_or_permissions(manage_server=True)
  1852. async def _min_setcasino(self, ctx, game, minbet: int):
  1853. """Set the minimum bet to play a game"""
  1854. author = ctx.message.author
  1855. settings = self.casino_bank.check_server_settings(author.server)
  1856. min_games = [x for x in c_games if x != "Allin"]
  1857.  
  1858. if game.title() not in min_games:
  1859. msg = "This game does not exist. Please pick from: {}".format(", ".join(min_games))
  1860. elif minbet < 0:
  1861. msg = "You need to set a minimum bet higher than 0."
  1862. elif minbet < settings["Games"][game.title()]["Max"]:
  1863. settings["Games"][game.title()]["Min"] = minbet
  1864. chips = settings["System Config"]["Chip Name"]
  1865. self.casino_bank.save_system()
  1866. msg = ("Setting the minimum bet for {} to {} {} "
  1867. "chips.".format(game.title(), minbet, chips))
  1868. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1869. else:
  1870. maxbet = settings["Games"][game.title()]["Max"]
  1871. msg = ("The minimum bet can't bet set higher than the maximum bet of "
  1872. "{} for {}.".format(maxbet, game.title()))
  1873.  
  1874. await self.bot.say(msg)
  1875.  
  1876. @setcasino.command(name="max", pass_context=True)
  1877. @checks.admin_or_permissions(manage_server=True)
  1878. async def _max_setcasino(self, ctx, game, maxbet: int):
  1879. """Set the maximum bet to play a game"""
  1880. author = ctx.message.author
  1881. settings = self.casino_bank.check_server_settings(author.server)
  1882. max_games = [x for x in c_games if x != "Allin"]
  1883.  
  1884. if game.title() not in max_games:
  1885. msg = "This game does not exist. Please pick from: {}".format(", ".join(max_games))
  1886. elif maxbet <= 0:
  1887. msg = "You need to set a maximum bet higher than 0."
  1888. elif maxbet > settings["Games"][game.title()]["Min"]:
  1889. settings["Games"][game.title()]["Max"] = maxbet
  1890. chips = settings["System Config"]["Chip Name"]
  1891. self.casino_bank.save_system()
  1892. msg = ("Setting the maximum bet for {} to {} {} "
  1893. "chips.".format(game.title(), maxbet, chips))
  1894. logger.info("SETTINGS CHANGED {}({}) {}".format(author.name, author.id, msg))
  1895. else:
  1896. minbet = settings["Games"][game.title()]["Min"]
  1897. msg = "The max bet needs be higher than the minimum bet of {}.".format(minbet)
  1898.  
  1899. await self.bot.say(msg)
  1900.  
  1901. async def table_split(self, user, headers, data, sort):
  1902. groups = [data[i:i + 20] for i in range(0, len(data), 20)]
  1903. pages = len(groups)
  1904.  
  1905. if sort == "place":
  1906. name = "[{}]".format(user.name)
  1907. page = next((idx for idx, sub in enumerate(groups) for tup in sub if name in tup), None)
  1908. if not page:
  1909. page = 0
  1910. table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
  1911. msg = ("```ini\n{}``````Python\nYou are viewing page {} of {}. "
  1912. "{} casino members.```".format(table, page + 1, pages, len(data)))
  1913. return msg
  1914. elif pages == 1:
  1915. page = 0
  1916. table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
  1917. msg = ("```ini\n{}``````Python\nYou are viewing page 1 of {}. "
  1918. "{} casino members```".format(table, pages, len(data)))
  1919. return msg
  1920.  
  1921. await self.bot.say("There are {} pages of high scores. "
  1922. "Which page would you like to display?".format(pages))
  1923. response = await self.bot.wait_for_message(timeout=15, author=user)
  1924. if response is None:
  1925. page = 0
  1926. table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
  1927. msg = ("```ini\n{}``````Python\nYou are viewing page {} of {}. "
  1928. "{} casino members.```".format(table, page + 1, pages, len(data)))
  1929. return msg
  1930. else:
  1931. try:
  1932. page = int(response.content) - 1
  1933. table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
  1934. msg = ("```ini\n{}``````Python\nYou are viewing page {} of {}. "
  1935. "{} casino members.```".format(table, page + 1, pages, len(data)))
  1936. return msg
  1937. except ValueError:
  1938. await self.bot.say("Sorry your response was not a number. Defaulting to page 1")
  1939. page = 0
  1940. table = tabulate(groups[page], headers=headers, numalign="left", tablefmt="simple")
  1941. msg = ("```ini\n{}``````Python\nYou are viewing page 1 of {}. "
  1942. "{} casino members```".format(table, pages, len(data)))
  1943. return msg
  1944.  
  1945. async def membership_updater(self):
  1946. """Updates user membership based on requirements every 5 minutes"""
  1947. await self.bot.wait_until_ready()
  1948. try:
  1949. await asyncio.sleep(15)
  1950. bank = self.bot.get_cog('Economy').bank
  1951. while True:
  1952. servers = self.casino_bank.get_all_servers()
  1953. for server in servers:
  1954. try:
  1955. server_obj = self.bot.get_server(server)
  1956. settings = self.casino_bank.check_server_settings(server_obj)
  1957. except AttributeError:
  1958. continue
  1959. else:
  1960. user_path = self.casino_bank.get_server_memberships(server_obj)
  1961. users = [server_obj.get_member(user) for user in user_path
  1962. if server_obj.get_member(user) is not None] # Check for None
  1963. if users:
  1964. for user in users:
  1965. membership = self.gather_requirements(settings, user, bank)
  1966. settings["Players"][user.id]["Membership"] = membership
  1967. else:
  1968. continue
  1969. self.casino_bank.save_system()
  1970. await asyncio.sleep(300) # Wait 5 minutes
  1971. except asyncio.CancelledError:
  1972. pass
  1973.  
  1974. async def war_game(self, user, settings, deck, amount):
  1975. player_card, dealer_card, pc, dc = self.war_draw(deck)
  1976. multiplier = settings["Games"]["War"]["Multiplier"]
  1977.  
  1978. await self.bot.say("The dealer shuffles the deck and deals 1 card face down to the player "
  1979. "and dealer...")
  1980. await asyncio.sleep(2)
  1981. await self.bot.say("**FLIP!**")
  1982. await asyncio.sleep(1)
  1983.  
  1984. if pc > dc:
  1985. outcome = "Win"
  1986. amount = int(amount * multiplier)
  1987. elif dc > pc:
  1988. outcome = "Loss"
  1989. else:
  1990. check = lambda m: m.content.title() in ["War", "Surrender", "Ffs"]
  1991. await self.bot.say("The player and dealer are both showing a **{}**!\nTHIS MEANS WAR! "
  1992. "You may choose to surrender and forfeit half your bet, or you can "
  1993. "go to war.\nYour bet will be doubled, but you will only win on "
  1994. "half the bet, the rest will be pushed.".format(player_card))
  1995. choice = await self.bot.wait_for_message(timeout=15, author=user, check=check)
  1996.  
  1997. if choice is None or choice.content.title() in ["Surrender", "Ffs"]:
  1998. outcome = "Surrender"
  1999. amount = int(amount / 2)
  2000. elif choice.content.title() == "War":
  2001. self.casino_bank.withdraw_chips(user, amount)
  2002. player_card, dealer_card, pc, dc = self.burn_three(deck)
  2003.  
  2004. await self.bot.say("The dealer burns three cards and deals two cards face down...")
  2005. await asyncio.sleep(3)
  2006. await self.bot.say("**FLIP!**")
  2007.  
  2008. if pc >= dc:
  2009. outcome = "Win"
  2010. amount = int(amount * multiplier + amount)
  2011. else:
  2012. outcome = "Loss"
  2013. else:
  2014. await self.bot.say("Improper response. You are being forced to forfeit.")
  2015. outcome = "Surrender"
  2016. amount = int(amount / 2)
  2017.  
  2018. return outcome, player_card, dealer_card, amount
  2019.  
  2020. async def blackjack_game(self, dh, user, amount, deck):
  2021. # Setup dealer and player starting hands
  2022. ph = self.draw_two(deck)
  2023. count = self.count_hand(ph)
  2024. # checks used to ensure the player uses the correct input
  2025. check = lambda m: m.content.title() in ["Hit", "Stay", "Double"]
  2026. check2 = lambda m: m.content.title() in ["Hit", "Stay"]
  2027.  
  2028. # End the game if the player has 21 in the starting hand.
  2029. if count == 21:
  2030. return ph, dh, amount
  2031.  
  2032. msg = ("{}\nYour cards: {}\nYour score: {}\nThe dealer shows: "
  2033. "{}\nHit, stay, or double?".format(user.mention, ", ".join(ph), count, dh[0]))
  2034. await self.bot.say(msg)
  2035. choice = await self.bot.wait_for_message(timeout=15, author=user, check=check)
  2036.  
  2037. # Stop the blackjack game if the player chooses stay or double.
  2038. if choice is None or choice.content.title() == "Stay":
  2039. return ph, dh, amount
  2040. elif choice.content.title() == "Double":
  2041. # Create a try/except block to catch when people are dumb and don't have enough chips
  2042. try:
  2043. self.casino_bank.withdraw_chips(user, amount)
  2044. amount = amount * 2
  2045. ph = self.draw_card(ph, deck)
  2046. count = self.count_hand(ph)
  2047. return ph, dh, amount
  2048. except InsufficientChips:
  2049. await self.bot.say("Not enough chips. Please choose hit or stay.")
  2050. choice2 = await self.bot.wait_for_message(timeout=15, author=user, check=check2)
  2051.  
  2052. if choice2 is None or choice2.content.title() == "Stay":
  2053. return ph, dh, amount
  2054.  
  2055. elif choice2.content.title() == "Hit":
  2056. # This breaks PEP8 for DRY but I didn't want to create a sperate coroutine.
  2057. while count < 21:
  2058. ph = self.draw_card(ph, deck)
  2059. count = self.count_hand(ph)
  2060.  
  2061. if count >= 21:
  2062. break
  2063. msg = ("{}\nYour cards: {}\nYour score: {}\nThe dealer shows: "
  2064. "{}\nHit or stay?".format(user.mention, ", ".join(ph), count, dh[0]))
  2065. await self.bot.say(msg)
  2066. resp = await self.bot.wait_for_message(timeout=15, author=user,
  2067. check=check2)
  2068.  
  2069. if resp is None or resp.content.title() == "Stay":
  2070. break
  2071. else:
  2072. continue
  2073. # Return player hand & dealer hand when count >= 21 or the player picks stay.
  2074. return ph, dh, amount
  2075.  
  2076. # Continue game logic in a loop until the player's count is 21 or bust.
  2077. elif choice.content.title() == "Hit":
  2078. while count < 21:
  2079. ph = self.draw_card(ph, deck)
  2080. count = self.count_hand(ph)
  2081.  
  2082. if count >= 21:
  2083. break
  2084. msg = ("{}\nYour cards: {}\nYour score: {}\nThe dealer shows: "
  2085. "{}\nHit or stay?".format(user.mention, ", ".join(ph), count, dh[0]))
  2086. await self.bot.say(msg)
  2087. response = await self.bot.wait_for_message(timeout=15, author=user, check=check2)
  2088.  
  2089. if response is None or response.content.title() == "Stay":
  2090. break
  2091. else:
  2092. continue
  2093. # Return player hand and dealer hand when count is 21 or greater or player picks stay.
  2094. return ph, dh, amount
  2095.  
  2096. def war_results(self, settings, user, outcome, player_card, dealer_card, amount):
  2097. chip_name = settings["System Config"]["Chip Name"]
  2098. msg = ("======**{}**======\nPlayer Card: {}"
  2099. "\nDealer Card: {}\n".format(user.name, player_card, dealer_card))
  2100. if outcome == "Win":
  2101. settings["Players"][user.id]["Won"]["War Won"] += 1
  2102. # Check if a threshold is set and withold chips if amount is exceeded
  2103. if self.threshold_check(settings, amount):
  2104. settings["Players"][user.id]["Pending"] = amount
  2105. msg += ("Your winnings exceeded the threshold set on this server. "
  2106. "The amount of {} {} chips will be withheld until reviewed and "
  2107. "released by an admin. Do not attempt to play additional games "
  2108. "exceeding the threshold until this has been cleared."
  2109. "".format(amount, chip_name, user.id))
  2110. logger.info("{}({}) won {} chips exceeding the threshold. Game "
  2111. "details:\nPlayer Bet: {}\nGame "
  2112. "Outcome: {}\n[END OF FILE]".format(user.name, user.id, amount,
  2113. str(amount).ljust(10),
  2114. str(outcome[0]).ljust(10)))
  2115. else:
  2116. self.casino_bank.deposit_chips(user, amount)
  2117. msg += ("**\*\*\*\*\*\*Winner!\*\*\*\*\*\***\n```Python\nYou just won {} {} "
  2118. "chips.```".format(amount, chip_name))
  2119.  
  2120. elif outcome == "Loss":
  2121. msg += "======House Wins!======"
  2122. else:
  2123. self.casino_bank.deposit_chips(user, amount)
  2124. msg = ("======**{}**======\n:flag_white: Surrendered :flag_white:\n==================\n"
  2125. "{} {} chips returned.".format(user.name, amount, chip_name))
  2126.  
  2127. # Save results and return appropriate outcome message.
  2128. self.casino_bank.save_system()
  2129. return msg
  2130.  
  2131. def blackjack_results(self, settings, user, amount, ph, dh):
  2132. chip_name = settings["System Config"]["Chip Name"]
  2133. dc = self.count_hand(dh)
  2134. pc = self.count_hand(ph)
  2135. msg = ("======**{}**======\nYour hand: {}\nYour score: {}\nDealer's hand: {}\nDealer's "
  2136. "score: {}\n".format(user.name, ", ".join(ph), pc, ", ".join(dh), dc))
  2137.  
  2138. if dc > 21 and pc <= 21 or dc < pc <= 21:
  2139. settings["Players"][user.id]["Won"]["BJ Won"] += 1
  2140. total = int(round(amount * settings["Games"]["Blackjack"]["Multiplier"]))
  2141. # Check if a threshold is set and withold chips if amount is exceeded
  2142. if self.threshold_check(settings, total):
  2143. settings["Players"][user.id]["Pending"] = total
  2144. msg = ("Your winnings exceeded the threshold set on this server. "
  2145. "The amount of {} {} chips will be withheld until reviewed and "
  2146. "released by an admin. Do not attempt to play additional games "
  2147. "exceeding the threshold until this has been cleared."
  2148. "".format(total, chip_name, user.id))
  2149. logger.info("{}({}) won {} chips exceeding the threshold. Game "
  2150. "details:\nPlayer Bet: {}\nGame\n"
  2151. "[END OF FILE]".format(user.name, user.id, total, str(total).ljust(10)))
  2152. else:
  2153. msg += ("**\*\*\*\*\*\*Winner!\*\*\*\*\*\***\n```Python\nYou just "
  2154. "won {} {} chips.```".format(total, chip_name))
  2155. self.casino_bank.deposit_chips(user, total)
  2156. elif pc > 21:
  2157. msg += "======BUST!======"
  2158. elif dc == pc and dc <= 21 and pc <= 21:
  2159. msg += ("======Pushed======\nReturned {} {} chips to your "
  2160. "account.".format(amount, chip_name))
  2161. amount = int(round(amount))
  2162. self.casino_bank.deposit_chips(user, amount)
  2163. elif dc > pc and dc <= 21:
  2164. msg += "======House Wins!======".format(user.name)
  2165. # Save results and return appropriate outcome message.
  2166. self.casino_bank.save_system()
  2167. return msg
  2168.  
  2169. def draw_two(self, deck):
  2170. hand = random.sample(deck, 2)
  2171. deck.remove(hand[0])
  2172. deck.remove(hand[1])
  2173. return hand
  2174.  
  2175. def draw_card(self, hand, deck):
  2176. card = random.choice(deck)
  2177. deck.remove(card)
  2178. hand.append(card)
  2179. return hand
  2180.  
  2181. def count_hand(self, hand):
  2182. count = sum([bj_values[x] for x in hand if x in bj_values])
  2183. count += sum([1 if x == 'Ace' and count + 11 > 21 else 11
  2184. if x == 'Ace' and hand.count('Ace') == 1 else 1
  2185. if x == 'Ace' and hand.count('Ace') > 1 else 0 for x in hand])
  2186. return count
  2187.  
  2188. def dealer(self, deck):
  2189. dh = self.draw_two(deck)
  2190. count = self.count_hand(dh)
  2191.  
  2192. # forces hit if ace in first two cards
  2193. if 'Ace' in dh:
  2194. dh = self.draw_card(dh, deck)
  2195. count = self.count_hand(dh)
  2196.  
  2197. # defines maximum hit score X
  2198. while count < 16:
  2199. self.draw_card(dh, deck)
  2200. count = self.count_hand(dh)
  2201. return dh
  2202.  
  2203. def war_draw(self, deck):
  2204. player_card = random.choice(deck)
  2205. deck.remove(player_card)
  2206. dealer_card = random.choice(deck)
  2207. pc = war_values[player_card]
  2208. dc = war_values[dealer_card]
  2209. return player_card, dealer_card, pc, dc
  2210.  
  2211. def burn_three(self, deck):
  2212. burn_cards = random.sample(deck, 3)
  2213.  
  2214. for x in burn_cards:
  2215. deck.remove(x)
  2216.  
  2217. player_card = random.choice(deck)
  2218. deck.remove(player_card)
  2219. dealer_card = random.choice(deck)
  2220. pc = war_values[player_card]
  2221. dc = war_values[dealer_card]
  2222.  
  2223. return player_card, dealer_card, pc, dc
  2224.  
  2225. def gather_requirements(self, settings, user, bank):
  2226. # Declare variables
  2227. path = settings["Memberships"]
  2228. memberships = settings["Memberships"]
  2229. memberships_met = []
  2230. # Loop through the memberships and their requirements
  2231. for membership in memberships:
  2232. req_switch = False
  2233. for req in path[membership]["Requirements"]:
  2234.  
  2235. # If the requirement is a role, run role logic
  2236. if req == "Role":
  2237. role = path[membership]["Requirements"]["Role"]
  2238. if role in [r.name for r in user.roles]:
  2239. req_switch = True
  2240. else:
  2241. req_switch = False
  2242. # If the requirement is a credits, run credit logic
  2243. elif req == "Credits":
  2244. if bank.account_exists(user):
  2245. user_credits = bank.get_balance(user)
  2246. if user_credits >= int(path[membership]["Requirements"]["Credits"]):
  2247. req_switch = True
  2248. else:
  2249. req_switch = False
  2250. else:
  2251. req_switch = False
  2252.  
  2253. # If the requirement is a chips, run chip logic
  2254. elif req == "Chips":
  2255. balance = self.casino_bank.chip_balance(user)
  2256. if balance >= int(path[membership]["Requirements"][req]):
  2257. req_switch = True
  2258. else:
  2259. req_switch = False
  2260.  
  2261. # If the requirement is a DoS, run DoS logic
  2262. elif req == "Days On Server":
  2263. dos = (datetime.utcnow() - user.joined_at).days
  2264. if dos >= path[membership]["Requirements"]["Days On Server"]:
  2265. req_switch = True
  2266. else:
  2267. req_switch = False
  2268.  
  2269. # You have to meet all the requirements to qualify for the membership
  2270. if req_switch:
  2271. memberships_met.append((membership, path[membership]["Access"]))
  2272.  
  2273. # Returns the membership with the highest access value
  2274. if memberships_met:
  2275. try:
  2276. membership = max(memberships_met, key=itemgetter(1))[0]
  2277. return membership
  2278. except (ValueError, TypeError):
  2279. return
  2280.  
  2281. else: # Returns none if the user has not qualified for any memberships
  2282. return
  2283.  
  2284. def get_benefits(self, settings, player):
  2285. payday = settings["System Config"]["Default Payday"]
  2286. benefits = {"Cooldown Reduction": 0, "Access": 0, "Payday": payday, "Color": "grey"}
  2287. membership = settings["Players"][player]["Membership"]
  2288.  
  2289. if membership:
  2290. if membership in settings["Memberships"]:
  2291. benefits = settings["Memberships"][membership]
  2292. else:
  2293. settings["Players"][player]["Membership"] = None
  2294. self.casino_bank.save_system()
  2295. membership = None
  2296.  
  2297. return membership, benefits
  2298.  
  2299. def threshold_check(self, settings, amount):
  2300. if settings["System Config"]["Threshold Switch"]:
  2301. if amount > settings["System Config"]["Threshold"]:
  2302. return True
  2303. else:
  2304. return False
  2305. else:
  2306. return False
  2307.  
  2308. def hl_outcome(self, dicetotal):
  2309. choices = [(1, "Lo", "Low"), (2, "Lo", "Low"), (3, "Lo", "Low"), (4, "Lo", "Low"),
  2310. (5, "Lo", "Low"), (6, "Lo", "Low"), (7, "7", "Seven"), (8, "Hi", "High"),
  2311. (9, "Hi", "High"), (10, "Hi", "High"), (11, "Hi", "High"), (12, "Hi", "High")]
  2312. outcome = choices[dicetotal - 1]
  2313. return outcome
  2314.  
  2315. def minmax_check(self, bet, game, settings):
  2316. mi = settings["Games"][game]["Min"]
  2317. mx = settings["Games"][game]["Max"]
  2318.  
  2319. if mi <= bet <= mx:
  2320. return None
  2321. else:
  2322. if mi != mx:
  2323. msg = ("Your bet needs to be {} or higher, but cannot exceed the "
  2324. "maximum of {} chips.".format(mi, mx))
  2325. else:
  2326. msg = ("Your bet needs to be exactly {}.".format(mi))
  2327. return msg
  2328.  
  2329. def stats_cooldowns(self, settings, user, cd_list):
  2330. user_membership = settings["Players"][user.id]["Membership"]
  2331. reduction = 0
  2332.  
  2333. # Check for cooldown reduction, if the membership was removed, set the user back to None.
  2334. try:
  2335. if user_membership:
  2336. reduction = settings["Memberships"][user_membership]["Cooldown Reduction"]
  2337. except KeyError:
  2338. settings["Players"][user.id]["Membership"] = None
  2339. self.casino_bank.save_system()
  2340.  
  2341. # Begin cooldown logic calculation
  2342. cooldowns = []
  2343. for method in cd_list:
  2344. user_time = settings["Players"][user.id]["Cooldowns"][method]
  2345.  
  2346. # Check if method is for a game or for payday
  2347. if method in c_games:
  2348. base = settings["Games"][method]["Cooldown"]
  2349. else:
  2350. reduction = 0
  2351. base = settings["System Config"]["Payday Timer"]
  2352.  
  2353. # Begin cooldown logic calculation
  2354. if user_time == 0: # For new accounts
  2355. cooldowns.append("<<Ready to Play!")
  2356. elif (datetime.utcnow() - parser.parse(user_time)).seconds + reduction < base:
  2357. ut = parser.parse(user_time)
  2358. seconds = abs((datetime.utcnow() - ut).seconds - base - reduction)
  2359. remaining = self.time_format(seconds, brief=True)
  2360. cooldowns.append(remaining)
  2361. else:
  2362. cooldowns.append("<<Ready to Play!")
  2363. return cooldowns
  2364.  
  2365. def check_cooldowns(self, user, method, settings):
  2366. user_time = settings["Players"][user.id]["Cooldowns"][method]
  2367. user_membership = settings["Players"][user.id]["Membership"]
  2368. reduction = 0
  2369.  
  2370. # Check for cooldown reduction, if the membership was removed, set the user back to None.
  2371. try:
  2372. if user_membership:
  2373. reduction = settings["Memberships"][user_membership]["Cooldown Reduction"]
  2374. except KeyError:
  2375. settings["Players"][user.id]["Membership"] = None
  2376. self.casino_bank.save_system()
  2377. # Check if method is for a game or for payday
  2378. if method in c_games:
  2379. base = settings["Games"][method]["Cooldown"]
  2380. elif method == "Payday":
  2381. reduction = 0
  2382. base = settings["System Config"]["Payday Timer"]
  2383. else:
  2384. reduction = 0
  2385. base = settings["System Config"]["Transfer Cooldown"]
  2386.  
  2387. # Begin cooldown logic calculation
  2388. if user_time == 0: # For new accounts
  2389. settings["Players"][user.id]["Cooldowns"][method] = datetime.utcnow().isoformat()
  2390. self.casino_bank.save_system()
  2391. return None
  2392. elif (datetime.utcnow() - parser.parse(user_time)).seconds + reduction < base:
  2393. seconds = abs((datetime.utcnow() - parser.parse(user_time)).seconds - base - reduction)
  2394. remaining = self.time_format(seconds)
  2395. msg = "{} is still on a cooldown. You still have: {}".format(method, remaining)
  2396. return msg
  2397. else:
  2398. settings["Players"][user.id]["Cooldowns"][method] = datetime.utcnow().isoformat()
  2399. self.casino_bank.save_system()
  2400. return None
  2401.  
  2402. def access_calculator(self, settings, user):
  2403. user_membership = settings["Players"][user.id]["Membership"]
  2404.  
  2405. if user_membership is None:
  2406. return 0
  2407. else:
  2408. if user_membership in settings["Memberships"]:
  2409. access = settings["Memberships"][user_membership]["Access"]
  2410. return access
  2411. else:
  2412. settings["Players"][user.id]["Membership"] = None
  2413. self.casino_bank.save_system()
  2414. return 0
  2415.  
  2416. def game_checks(self, settings, prefix, user, bet, game, choice, choices):
  2417. casino_name = settings["System Config"]["Casino Name"]
  2418. game_access = settings["Games"][game]["Access Level"]
  2419. # Allin does not require a minmax check, so we set it to None if Allin.
  2420. if game != "Allin":
  2421. minmax_fail = self.minmax_check(bet, game, settings)
  2422. else:
  2423. minmax_fail = None
  2424. bet = int(settings["Players"][user.id]["Chips"])
  2425. # Check for membership first.
  2426. try:
  2427. self.casino_bank.can_bet(user, bet)
  2428. except UserNotRegistered:
  2429. msg = ("You need to register to the {} Casino. To register type `{}casino "
  2430. "join`.".format(casino_name, prefix))
  2431. return msg
  2432. except InsufficientChips:
  2433. msg = "You do not have enough chips to cover the bet."
  2434. return msg
  2435.  
  2436. # Check if casino json file has the hi-lo game, and if not add it.
  2437. if "Hi-Lo Played" not in settings["Players"][user.id]["Played"]:
  2438. self.player_update(settings["Players"][user.id], hilo_data)
  2439.  
  2440. if "War Played" not in settings["Players"][user.id]["Played"]:
  2441. self.player_update(settings["Players"][user.id], war_data)
  2442.  
  2443. user_access = self.access_calculator(settings, user)
  2444. # Begin logic to determine if the game can be played.
  2445. if choice not in choices:
  2446. msg = "Incorrect response. Accepted response are:\n{}".format(", ".join(choices))
  2447. return msg
  2448. elif not settings["System Config"]["Casino Open"]:
  2449. msg = "The {} Casino is closed.".format(casino_name)
  2450. return msg
  2451. elif game_access > user_access:
  2452. msg = ("{} requires an access level of {}. Your current access level is {}. Obtain a "
  2453. "higher membership to play this game.")
  2454. return msg
  2455. elif minmax_fail:
  2456. msg = minmax_fail
  2457. return msg
  2458. else:
  2459. cd_check = self.check_cooldowns(user, game, settings)
  2460. # Cooldowns are checked last incase another check failed.
  2461. return cd_check
  2462.  
  2463. def color_lookup(self, color):
  2464. color = color.lower()
  2465. colors = {"blue": 0x3366FF, "red": 0xFF0000, "green": 0x00CC33, "orange": 0xFF6600,
  2466. "purple": 0xA220BD, "yellow": 0xFFFF00, "teal": 0x009999, "magenta": 0xBA2586,
  2467. "turquoise": 0x00FFFF, "grey": 0x666666, "pink": 0xFE01D1, "white": 0xFFFFFF}
  2468. color = colors[color]
  2469. return color
  2470.  
  2471. def player_update(self, player_data, new_game, path=None):
  2472. """Helper function to add new data into the player's data"""
  2473.  
  2474. if path is None:
  2475. path = []
  2476. for key in new_game:
  2477. if key in player_data:
  2478. if isinstance(player_data[key], dict) and isinstance(new_game[key], dict):
  2479. self.player_update(player_data[key], new_game[key], path + [str(key)])
  2480. elif player_data[key] == new_game[key]:
  2481. pass
  2482. else:
  2483. raise Exception("Conflict at {}".format("".join(path + [str(key)])))
  2484. else:
  2485. player_data[key] = new_game[key]
  2486. self.casino_bank.save_system()
  2487.  
  2488. def time_format(self, seconds, brief=False):
  2489. # Calculate the time and input into a dict to plural the strings later.
  2490. m, s = divmod(seconds, 60)
  2491. h, m = divmod(m, 60)
  2492. data = PluralDict({'hour': h, 'minute': m, 'second': s})
  2493.  
  2494. # Determine the remaining time.
  2495. if not brief:
  2496. if h > 0:
  2497. fmt = "{hour} hour{hour(s)}"
  2498. if data["minute"] > 0 and data["second"] > 0:
  2499. fmt += ", {minute} minute{minute(s)}, and {second} second{second(s)}"
  2500. if data["second"] > 0 == data["minute"]:
  2501. fmt += ", and {second} second{second(s)}"
  2502. msg = fmt.format_map(data)
  2503. elif h == 0 and m > 0:
  2504. if data["second"] == 0:
  2505. fmt = "{minute} minute{minute(s)}"
  2506. else:
  2507. fmt = "{minute} minute{minute(s)}, and {second} second{second(s)}"
  2508. msg = fmt.format_map(data)
  2509. elif m == 0 and h == 0 and s > 0:
  2510. fmt = "{second} second{second(s)}"
  2511. msg = fmt.format_map(data)
  2512. else:
  2513. msg = "None"
  2514. # Return remaining time.
  2515. else:
  2516.  
  2517. if h > 0:
  2518. msg = "{0}h"
  2519. if m > 0 and s > 0:
  2520. msg += ", {1}m, and {2}s"
  2521.  
  2522. elif s > 0 and m == 0:
  2523. msg += "and {2}s"
  2524. elif h == 0 and m > 0:
  2525. if s == 0:
  2526. msg = "{1}m"
  2527. else:
  2528. msg = "{1}m and {2}s"
  2529. elif m == 0 and h == 0 and s > 0:
  2530. msg = "{2}s"
  2531. else:
  2532. msg = "None"
  2533. return msg.format(h, m, s)
  2534.  
  2535. def __unload(self):
  2536. self.cycle_task.cancel()
  2537. self.casino_bank.save_system()
  2538.  
  2539.  
  2540. def check_folders():
  2541. if not os.path.exists("data/JumperCogs/casino"):
  2542. print("Creating data/JumperCogs/casino folder...")
  2543. os.makedirs("data/JumperCogs/casino")
  2544.  
  2545.  
  2546. def check_files():
  2547. system = {"Servers": {}}
  2548.  
  2549. f = "data/JumperCogs/casino/casino.json"
  2550. if not dataIO.is_valid_json(f):
  2551. print("Creating default casino.json...")
  2552. dataIO.save_json(f, system)
  2553.  
  2554.  
  2555. def setup(bot):
  2556. global logger
  2557. check_folders()
  2558. check_files()
  2559. logger = logging.getLogger("red.casino")
  2560. if logger.level == 0:
  2561. logger.setLevel(logging.INFO)
  2562. # Rotates to a new file every 10mb, up to 5
  2563. handler = logging.handlers.RotatingFileHandler(filename='data/JumperCogs/casino/casino.log',
  2564. encoding='utf-8', backupCount=5,
  2565. maxBytes=100000)
  2566. handler.setFormatter(logging.Formatter('%(asctime)s %(name)-12s %(message)s',
  2567. datefmt="[%d/%m/%Y %H:%M]"))
  2568. logger.addHandler(handler)
  2569. if not tabulateAvailable:
  2570. raise RuntimeError("You need to run 'pip3 install tabulate'")
  2571. elif not dateutilAvailable:
  2572. raise RuntimeError("You need to install the library python-dateutil.")
  2573. else:
  2574. bot.add_cog(Casino(bot))
Add Comment
Please, Sign In to add comment