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