mirror of
https://github.com/wlinator/luminara.git
synced 2024-10-02 20:23:12 +00:00
commit
4fbfc6e05d
5 changed files with 258 additions and 282 deletions
|
@ -17,6 +17,7 @@ RUN pip install --no-cache-dir poetry && \
|
||||||
pip cache purge
|
pip cache purge
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN rm -rf .venv
|
||||||
|
|
||||||
ENV LANG=en_US.UTF-8
|
ENV LANG=en_US.UTF-8
|
||||||
ENV LC_ALL=en_US.UTF-8
|
ENV LC_ALL=en_US.UTF-8
|
||||||
|
|
|
@ -22,5 +22,9 @@
|
||||||
"flowers": "https://i.imgur.com/79XfsbS.png",
|
"flowers": "https://i.imgur.com/79XfsbS.png",
|
||||||
"teapot": "https://i.imgur.com/wFsgSnr.png",
|
"teapot": "https://i.imgur.com/wFsgSnr.png",
|
||||||
"muffin": "https://i.imgur.com/hSauh7K.png"
|
"muffin": "https://i.imgur.com/hSauh7K.png"
|
||||||
|
},
|
||||||
|
"other": {
|
||||||
|
"cloud": "https://i.imgur.com/rc68c43.png",
|
||||||
|
"trophy": "https://i.imgur.com/dvIIr2G.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,6 +32,23 @@
|
||||||
"birthday_upcoming_description_line": "🎂 {0} - {1}",
|
"birthday_upcoming_description_line": "🎂 {0} - {1}",
|
||||||
"birthday_upcoming_no_birthdays": "there are no upcoming birthdays in this server.",
|
"birthday_upcoming_no_birthdays": "there are no upcoming birthdays in this server.",
|
||||||
"birthday_upcoming_no_birthdays_author": "No Upcoming Birthdays",
|
"birthday_upcoming_no_birthdays_author": "No Upcoming Birthdays",
|
||||||
|
"blackjack_bet": "Bet ${0}",
|
||||||
|
"blackjack_busted": "Busted..",
|
||||||
|
"blackjack_dealer_busted": "The dealer busted. You won!",
|
||||||
|
"blackjack_dealer_hand": "**Dealer**\nScore: {0}\n*Hand: {1}*",
|
||||||
|
"blackjack_dealer_hidden": "??",
|
||||||
|
"blackjack_deck_shuffled": "deck shuffled",
|
||||||
|
"blackjack_description": "You | Score: {0}\nDealer | Score: {1}",
|
||||||
|
"blackjack_error": "I.. don't know if you won?",
|
||||||
|
"blackjack_error_description": "This is an error, please report it.",
|
||||||
|
"blackjack_footer": "Game finished",
|
||||||
|
"blackjack_lost": "You lost **${0}**.",
|
||||||
|
"blackjack_lost_generic": "You lost..",
|
||||||
|
"blackjack_player_hand": "**You**\nScore: {0}\n*Hand: {1}*",
|
||||||
|
"blackjack_title": "BlackJack",
|
||||||
|
"blackjack_won_21": "You won with a score of 21!",
|
||||||
|
"blackjack_won_natural": "You won with a natural hand!",
|
||||||
|
"blackjack_won_payout": "You won **${0}**.",
|
||||||
"boost_default_description": "Thanks for boosting, **{0}**!!",
|
"boost_default_description": "Thanks for boosting, **{0}**!!",
|
||||||
"boost_default_title": "New Booster",
|
"boost_default_title": "New Booster",
|
||||||
"case_case_field": "Case:",
|
"case_case_field": "Case:",
|
||||||
|
@ -127,6 +144,7 @@
|
||||||
"error_birthdays_disabled_author": "Birthdays Disabled",
|
"error_birthdays_disabled_author": "Birthdays Disabled",
|
||||||
"error_birthdays_disabled_description": "birthdays are disabled in this server.",
|
"error_birthdays_disabled_description": "birthdays are disabled in this server.",
|
||||||
"error_birthdays_disabled_footer": "Contact a mod to enable them.",
|
"error_birthdays_disabled_footer": "Contact a mod to enable them.",
|
||||||
|
"error_blackjack_game_error": "something went wrong while playing blackjack.",
|
||||||
"error_boost_image_url_invalid": "the image URL must end with `.jpg` or `.png`.",
|
"error_boost_image_url_invalid": "the image URL must end with `.jpg` or `.png`.",
|
||||||
"error_bot_missing_permissions_author": "Bot Missing Permissions",
|
"error_bot_missing_permissions_author": "Bot Missing Permissions",
|
||||||
"error_bot_missing_permissions_description": "Lumi lacks the required permissions to run this command.",
|
"error_bot_missing_permissions_description": "Lumi lacks the required permissions to run this command.",
|
||||||
|
@ -134,6 +152,7 @@
|
||||||
"error_command_cooldown_description": "try again in **{0:02d}:{1:02d}**.",
|
"error_command_cooldown_description": "try again in **{0:02d}:{1:02d}**.",
|
||||||
"error_command_not_found": "No command called \"{0}\" found.",
|
"error_command_not_found": "No command called \"{0}\" found.",
|
||||||
"error_image_url_invalid": "invalid image URL.",
|
"error_image_url_invalid": "invalid image URL.",
|
||||||
|
"error_invalid_bet": "the bet you entered is invalid.",
|
||||||
"error_invalid_duration": "Invalid duration: {0}",
|
"error_invalid_duration": "Invalid duration: {0}",
|
||||||
"error_invalid_duration_author": "Invalid Duration",
|
"error_invalid_duration_author": "Invalid Duration",
|
||||||
"error_invalid_duration_description": "Please provide a valid duration between 1 minute and 30 days.",
|
"error_invalid_duration_description": "Please provide a valid duration between 1 minute and 30 days.",
|
||||||
|
@ -145,6 +164,7 @@
|
||||||
"error_no_case_found_description": "no case found with that ID.",
|
"error_no_case_found_description": "no case found with that ID.",
|
||||||
"error_no_private_message_author": "Guild Only",
|
"error_no_private_message_author": "Guild Only",
|
||||||
"error_no_private_message_description": "this command can only be used in servers.",
|
"error_no_private_message_description": "this command can only be used in servers.",
|
||||||
|
"error_not_enough_cash": "you don't have enough cash.",
|
||||||
"error_not_owner_author": "Owner Only",
|
"error_not_owner_author": "Owner Only",
|
||||||
"error_not_owner_description": "this command requires Lumi ownership permissions.",
|
"error_not_owner_description": "this command requires Lumi ownership permissions.",
|
||||||
"error_out_of_time": "you ran out of time.",
|
"error_out_of_time": "you ran out of time.",
|
||||||
|
@ -262,4 +282,4 @@
|
||||||
"xp_level": "Level {0}",
|
"xp_level": "Level {0}",
|
||||||
"xp_progress": "Progress to next level",
|
"xp_progress": "Progress to next level",
|
||||||
"xp_server_rank": "Server Rank: #{0}"
|
"xp_server_rank": "Server Rank: #{0}"
|
||||||
}
|
}
|
|
@ -84,6 +84,10 @@ class Constants:
|
||||||
TEAPOT_ART = ART["juicybblue"]["teapot"]
|
TEAPOT_ART = ART["juicybblue"]["teapot"]
|
||||||
MUFFIN_ART = ART["juicybblue"]["muffin"]
|
MUFFIN_ART = ART["juicybblue"]["muffin"]
|
||||||
|
|
||||||
|
# other art
|
||||||
|
CLOUD_ART = ART["other"]["cloud"]
|
||||||
|
TROPHY_ART = ART["other"]["trophy"]
|
||||||
|
|
||||||
# birthdays
|
# birthdays
|
||||||
BIRTHDAY_MESSAGES = JsonCache.read_json("birthday")["birthday_messages"]
|
BIRTHDAY_MESSAGES = JsonCache.read_json("birthday")["birthday_messages"]
|
||||||
BIRTHDAY_MONTHS = JsonCache.read_json("birthday")["months"]
|
BIRTHDAY_MONTHS = JsonCache.read_json("birthday")["months"]
|
||||||
|
|
|
@ -1,332 +1,279 @@
|
||||||
import random
|
import random
|
||||||
from datetime import datetime
|
from typing import List, Tuple
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
import pytz
|
import pytz
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
from lib import interaction
|
from lib import interaction
|
||||||
from lib.constants import CONST
|
from lib.constants import CONST
|
||||||
from lib.exceptions.LumiExceptions import LumiException
|
from lib.exceptions.LumiExceptions import LumiException
|
||||||
from services.currency_service import Currency
|
from services.currency_service import Currency
|
||||||
from services.stats_service import BlackJackStats
|
from services.stats_service import BlackJackStats
|
||||||
|
from lib.embed_builder import EmbedBuilder
|
||||||
|
|
||||||
est = pytz.timezone("US/Eastern")
|
EST = pytz.timezone("US/Eastern")
|
||||||
active_blackjack_games = {}
|
ACTIVE_BLACKJACK_GAMES: dict[int, bool] = {}
|
||||||
|
|
||||||
|
Card = str
|
||||||
|
Hand = List[Card]
|
||||||
|
|
||||||
|
|
||||||
async def cmd(ctx, bet: int):
|
async def cmd(ctx: commands.Context, bet: int) -> None:
|
||||||
"""
|
if ctx.author.id in ACTIVE_BLACKJACK_GAMES:
|
||||||
status states:
|
|
||||||
0 = game start
|
|
||||||
1 = player busted
|
|
||||||
2 = player won with 21 (after hit)
|
|
||||||
3 = dealer busted
|
|
||||||
4 = dealer won
|
|
||||||
5 = player won with 21 (blackjack)
|
|
||||||
"""
|
|
||||||
|
|
||||||
# check if the player already has an active blackjack going
|
|
||||||
if ctx.author.id in active_blackjack_games:
|
|
||||||
raise LumiException(CONST.STRINGS["error_already_playing_blackjack"])
|
raise LumiException(CONST.STRINGS["error_already_playing_blackjack"])
|
||||||
|
|
||||||
# Currency handler
|
currency = Currency(ctx.author.id)
|
||||||
ctx_currency = Currency(ctx.author.id)
|
if bet > currency.balance:
|
||||||
|
raise LumiException(CONST.STRINGS["error_not_enough_cash"])
|
||||||
|
if bet <= 0:
|
||||||
|
raise LumiException(CONST.STRINGS["error_invalid_bet"])
|
||||||
|
|
||||||
# check if the user has enough cash
|
ACTIVE_BLACKJACK_GAMES[ctx.author.id] = True
|
||||||
player_balance = ctx_currency.balance
|
|
||||||
if bet > player_balance:
|
|
||||||
raise commands.BadArgument("you don't have enough cash.")
|
|
||||||
elif bet <= 0:
|
|
||||||
raise commands.BadArgument("the bet you entered is invalid.")
|
|
||||||
|
|
||||||
active_blackjack_games[ctx.author.id] = True
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
deck = get_new_deck()
|
await play_blackjack(ctx, currency, bet)
|
||||||
multiplier = float(CONST.BLACKJACK["reward_multiplier"])
|
|
||||||
|
|
||||||
player_hand = [deal_card(deck), deal_card(deck)]
|
|
||||||
dealer_hand = [deal_card(deck)]
|
|
||||||
# calculate initial hands
|
|
||||||
player_hand_value = calculate_hand_value(player_hand)
|
|
||||||
dealer_hand_value = calculate_hand_value(dealer_hand)
|
|
||||||
|
|
||||||
status = 0 if player_hand_value != 21 else 5
|
|
||||||
view = interaction.BlackJackButtons(ctx)
|
|
||||||
playing_embed = False
|
|
||||||
|
|
||||||
while status == 0:
|
|
||||||
if not playing_embed:
|
|
||||||
await ctx.respond(
|
|
||||||
embed=blackjack_show(
|
|
||||||
ctx,
|
|
||||||
Currency.format_human(bet),
|
|
||||||
player_hand,
|
|
||||||
dealer_hand,
|
|
||||||
player_hand_value,
|
|
||||||
dealer_hand_value,
|
|
||||||
),
|
|
||||||
view=view,
|
|
||||||
content=ctx.author.mention,
|
|
||||||
)
|
|
||||||
|
|
||||||
playing_embed = True
|
|
||||||
|
|
||||||
await view.wait()
|
|
||||||
|
|
||||||
if view.clickedHit:
|
|
||||||
# player draws a card & value is calculated
|
|
||||||
player_hand.append(deal_card(deck))
|
|
||||||
player_hand_value = calculate_hand_value(player_hand)
|
|
||||||
|
|
||||||
if player_hand_value > 21:
|
|
||||||
status = 1
|
|
||||||
break
|
|
||||||
elif player_hand_value == 21:
|
|
||||||
status = 2
|
|
||||||
break
|
|
||||||
|
|
||||||
elif view.clickedStand:
|
|
||||||
# player stands, dealer draws cards until he wins OR busts
|
|
||||||
while dealer_hand_value <= player_hand_value:
|
|
||||||
dealer_hand.append(deal_card(deck))
|
|
||||||
dealer_hand_value = calculate_hand_value(dealer_hand)
|
|
||||||
|
|
||||||
status = 3 if dealer_hand_value > 21 else 4
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# timed out
|
|
||||||
ctx_currency.take_balance(bet)
|
|
||||||
ctx_currency.push()
|
|
||||||
raise LumiException(CONST.STRINGS["error_out_of_time_economy"])
|
|
||||||
|
|
||||||
# refresh
|
|
||||||
view = interaction.BlackJackButtons(ctx)
|
|
||||||
embed = blackjack_show(
|
|
||||||
ctx,
|
|
||||||
Currency.format_human(bet),
|
|
||||||
player_hand,
|
|
||||||
dealer_hand,
|
|
||||||
player_hand_value,
|
|
||||||
dealer_hand_value,
|
|
||||||
)
|
|
||||||
|
|
||||||
await ctx.edit(embed=embed, view=view, content=ctx.author.mention)
|
|
||||||
|
|
||||||
"""
|
|
||||||
At this point the game has concluded, generate a final output & backend
|
|
||||||
"""
|
|
||||||
|
|
||||||
payout = bet * multiplier if status != 5 else bet * 2
|
|
||||||
is_won = status not in [1, 4]
|
|
||||||
|
|
||||||
embed = blackjack_finished(
|
|
||||||
ctx,
|
|
||||||
Currency.format_human(bet),
|
|
||||||
player_hand_value,
|
|
||||||
dealer_hand_value,
|
|
||||||
Currency.format_human(payout),
|
|
||||||
status,
|
|
||||||
)
|
|
||||||
|
|
||||||
if playing_embed:
|
|
||||||
await ctx.edit(embed=embed, view=None, content=ctx.author.mention)
|
|
||||||
else:
|
|
||||||
await ctx.respond(embed=embed, view=None, content=ctx.author.mention)
|
|
||||||
|
|
||||||
# change balance
|
|
||||||
# if status == 1 or status == 4:
|
|
||||||
if not is_won:
|
|
||||||
ctx_currency.take_balance(bet)
|
|
||||||
ctx_currency.push()
|
|
||||||
|
|
||||||
# push stats (low priority)
|
|
||||||
stats = BlackJackStats(
|
|
||||||
user_id=ctx.author.id,
|
|
||||||
is_won=False,
|
|
||||||
bet=bet,
|
|
||||||
payout=0,
|
|
||||||
hand_player=player_hand,
|
|
||||||
hand_dealer=dealer_hand,
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
ctx_currency.add_balance(payout)
|
|
||||||
ctx_currency.push()
|
|
||||||
|
|
||||||
# push stats (low priority)
|
|
||||||
stats = BlackJackStats(
|
|
||||||
user_id=ctx.author.id,
|
|
||||||
is_won=True,
|
|
||||||
bet=bet,
|
|
||||||
payout=payout,
|
|
||||||
hand_player=player_hand,
|
|
||||||
hand_dealer=dealer_hand,
|
|
||||||
)
|
|
||||||
|
|
||||||
stats.push()
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# await ctx.respond(embed=GenericErrors.default_exception(ctx))
|
raise LumiException(CONST.STRINGS["error_blackjack_game_error"]) from e
|
||||||
logger.error("Something went wrong in the blackjack command: ", e)
|
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# remove player from active games list
|
del ACTIVE_BLACKJACK_GAMES[ctx.author.id]
|
||||||
del active_blackjack_games[ctx.author.id]
|
|
||||||
|
|
||||||
|
|
||||||
def blackjack_show(
|
async def play_blackjack(ctx: commands.Context, currency: Currency, bet: int) -> None:
|
||||||
ctx,
|
deck = get_new_deck()
|
||||||
bet,
|
player_hand, dealer_hand = initial_deal(deck)
|
||||||
player_hand,
|
multiplier = float(CONST.BLACKJACK["reward_multiplier"])
|
||||||
dealer_hand,
|
|
||||||
player_hand_value,
|
|
||||||
dealer_hand_value,
|
|
||||||
):
|
|
||||||
current_time = datetime.now(est).strftime("%I:%M %p")
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="BlackJack",
|
|
||||||
color=discord.Color.dark_orange(),
|
|
||||||
)
|
|
||||||
|
|
||||||
embed.description = (
|
player_value = calculate_hand_value(player_hand)
|
||||||
f"**You**\n"
|
status = 5 if player_value == 21 else 0
|
||||||
f"Score: {player_hand_value}\n"
|
view = interaction.BlackJackButtons(ctx)
|
||||||
f"*Hand: {' + '.join(player_hand)}*\n\n"
|
playing_embed = False
|
||||||
)
|
|
||||||
|
|
||||||
if len(dealer_hand) < 2:
|
while status == 0:
|
||||||
embed.description += (
|
dealer_value = calculate_hand_value(dealer_hand)
|
||||||
f"**Dealer**\n"
|
|
||||||
f"Score: {dealer_hand_value}\n"
|
embed = create_game_embed(
|
||||||
f"*Hand: {dealer_hand[0]} + ??*"
|
ctx,
|
||||||
|
bet,
|
||||||
|
player_hand,
|
||||||
|
dealer_hand,
|
||||||
|
player_value,
|
||||||
|
dealer_value,
|
||||||
)
|
)
|
||||||
|
if not playing_embed:
|
||||||
|
await ctx.respond(embed=embed, view=view, content=ctx.author.mention)
|
||||||
|
playing_embed = True
|
||||||
|
else:
|
||||||
|
await ctx.edit(embed=embed, view=view)
|
||||||
|
|
||||||
|
await view.wait()
|
||||||
|
|
||||||
|
if view.clickedHit:
|
||||||
|
player_hand.append(deal_card(deck))
|
||||||
|
player_value = calculate_hand_value(player_hand)
|
||||||
|
if player_value > 21:
|
||||||
|
status = 1
|
||||||
|
break
|
||||||
|
elif player_value == 21:
|
||||||
|
status = 2
|
||||||
|
break
|
||||||
|
elif view.clickedStand:
|
||||||
|
status = dealer_play(deck, dealer_hand, player_value)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
currency.take_balance(bet)
|
||||||
|
currency.push()
|
||||||
|
raise LumiException(CONST.STRINGS["error_out_of_time_economy"])
|
||||||
|
|
||||||
|
view = interaction.BlackJackButtons(ctx)
|
||||||
|
|
||||||
|
await handle_game_end(
|
||||||
|
ctx,
|
||||||
|
currency,
|
||||||
|
bet,
|
||||||
|
player_hand,
|
||||||
|
dealer_hand,
|
||||||
|
status,
|
||||||
|
multiplier,
|
||||||
|
playing_embed,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def initial_deal(deck: List[Card]) -> Tuple[Hand, Hand]:
|
||||||
|
return [deal_card(deck) for _ in range(2)], [deal_card(deck)]
|
||||||
|
|
||||||
|
|
||||||
|
def dealer_play(deck: List[Card], dealer_hand: Hand, player_value: int) -> int:
|
||||||
|
while calculate_hand_value(dealer_hand) <= player_value:
|
||||||
|
dealer_hand.append(deal_card(deck))
|
||||||
|
return 3 if calculate_hand_value(dealer_hand) > 21 else 4
|
||||||
|
|
||||||
|
|
||||||
|
async def handle_game_end(
|
||||||
|
ctx: commands.Context,
|
||||||
|
currency: Currency,
|
||||||
|
bet: int,
|
||||||
|
player_hand: Hand,
|
||||||
|
dealer_hand: Hand,
|
||||||
|
status: int,
|
||||||
|
multiplier: float,
|
||||||
|
playing_embed: bool,
|
||||||
|
) -> None:
|
||||||
|
player_value = calculate_hand_value(player_hand)
|
||||||
|
dealer_value = calculate_hand_value(dealer_hand)
|
||||||
|
payout = bet * (2 if status == 5 else multiplier)
|
||||||
|
is_won = status not in [1, 4]
|
||||||
|
|
||||||
|
embed = create_end_game_embed(ctx, bet, player_value, dealer_value, payout, status)
|
||||||
|
|
||||||
|
if playing_embed:
|
||||||
|
await ctx.edit(embed=embed, view=None)
|
||||||
else:
|
else:
|
||||||
embed.description += (
|
await ctx.respond(embed=embed, view=None, content=ctx.author.mention)
|
||||||
f"**Dealer | Score: {dealer_hand_value}**\n"
|
|
||||||
f"*Hand: {' + '.join(dealer_hand)}*"
|
|
||||||
)
|
|
||||||
|
|
||||||
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
|
currency.add_balance(payout) if is_won else currency.take_balance(bet)
|
||||||
embed.set_footer(
|
currency.push()
|
||||||
text=f"Bet ${bet} • deck shuffled • Today at {current_time}",
|
|
||||||
icon_url="https://i.imgur.com/96jPPXO.png",
|
BlackJackStats(
|
||||||
|
user_id=ctx.author.id,
|
||||||
|
is_won=is_won,
|
||||||
|
bet=bet,
|
||||||
|
payout=payout if is_won else 0,
|
||||||
|
hand_player=player_hand,
|
||||||
|
hand_dealer=dealer_hand,
|
||||||
|
).push()
|
||||||
|
|
||||||
|
|
||||||
|
def create_game_embed(
|
||||||
|
ctx: commands.Context,
|
||||||
|
bet: int,
|
||||||
|
player_hand: Hand,
|
||||||
|
dealer_hand: Hand,
|
||||||
|
player_value: int,
|
||||||
|
dealer_value: int,
|
||||||
|
) -> discord.Embed:
|
||||||
|
player_hand_str = " + ".join(player_hand)
|
||||||
|
dealer_hand_str = f"{dealer_hand[0]} + " + (
|
||||||
|
CONST.STRINGS["blackjack_dealer_hidden"]
|
||||||
|
if len(dealer_hand) < 2
|
||||||
|
else " + ".join(dealer_hand[1:])
|
||||||
)
|
)
|
||||||
|
|
||||||
if thumbnail_url := None:
|
description = (
|
||||||
embed.set_thumbnail(url=thumbnail_url)
|
f"{CONST.STRINGS['blackjack_player_hand'].format(player_value, player_hand_str)}\n\n"
|
||||||
|
f"{CONST.STRINGS['blackjack_dealer_hand'].format(dealer_value, dealer_hand_str)}"
|
||||||
return embed
|
|
||||||
|
|
||||||
|
|
||||||
def blackjack_finished(ctx, bet, player_hand_value, dealer_hand_value, payout, status):
|
|
||||||
current_time = datetime.now(est).strftime("%I:%M %p")
|
|
||||||
thumbnail_url = None
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
|
||||||
title="BlackJack",
|
|
||||||
)
|
|
||||||
embed.description = (
|
|
||||||
f"You | Score: {player_hand_value}\n" f"Dealer | Score: {dealer_hand_value}"
|
|
||||||
)
|
|
||||||
embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
|
|
||||||
embed.set_footer(
|
|
||||||
text=f"Game finished • Today at {current_time}",
|
|
||||||
icon_url="https://i.imgur.com/96jPPXO.png",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if status == 1:
|
footer_text = (
|
||||||
name = "Busted.."
|
f"{CONST.STRINGS['blackjack_bet'].format(Currency.format_human(bet))} • "
|
||||||
value = f"You lost **${bet}**."
|
f"{CONST.STRINGS['blackjack_deck_shuffled']}"
|
||||||
thumbnail_url = "https://i.imgur.com/rc68c43.png"
|
)
|
||||||
color = discord.Color.red()
|
|
||||||
|
|
||||||
elif status == 2:
|
return EmbedBuilder.create_embed(
|
||||||
name = "You won with a score of 21!"
|
ctx,
|
||||||
value = f"You won **${payout}**."
|
title=CONST.STRINGS["blackjack_title"],
|
||||||
thumbnail_url = "https://i.imgur.com/dvIIr2G.png"
|
color=discord.Colour.embed_background(),
|
||||||
color = discord.Color.green()
|
description=description,
|
||||||
|
footer_text=footer_text,
|
||||||
|
footer_icon_url=CONST.MUFFIN_ART,
|
||||||
|
show_name=False,
|
||||||
|
hide_timestamp=True,
|
||||||
|
)
|
||||||
|
|
||||||
elif status == 3:
|
|
||||||
name = "The dealer busted. You won!"
|
|
||||||
value = f"You won **${payout}**."
|
|
||||||
thumbnail_url = "https://i.imgur.com/dvIIr2G.png"
|
|
||||||
color = discord.Color.green()
|
|
||||||
|
|
||||||
elif status == 4:
|
def create_end_game_embed(
|
||||||
name = "You lost.."
|
ctx: commands.Context,
|
||||||
value = f"You lost **${bet}**."
|
bet: int,
|
||||||
thumbnail_url = "https://i.imgur.com/rc68c43.png"
|
player_value: int,
|
||||||
color = discord.Color.red()
|
dealer_value: int,
|
||||||
|
payout: int,
|
||||||
|
status: int,
|
||||||
|
) -> discord.Embed:
|
||||||
|
embed = EmbedBuilder.create_embed(
|
||||||
|
ctx,
|
||||||
|
title=CONST.STRINGS["blackjack_title"],
|
||||||
|
color=discord.Colour.embed_background(),
|
||||||
|
description=CONST.STRINGS["blackjack_description"].format(
|
||||||
|
player_value,
|
||||||
|
dealer_value,
|
||||||
|
),
|
||||||
|
footer_text=CONST.STRINGS["blackjack_footer"],
|
||||||
|
footer_icon_url=CONST.MUFFIN_ART,
|
||||||
|
show_name=False,
|
||||||
|
)
|
||||||
|
|
||||||
elif status == 5:
|
result = {
|
||||||
name = "You won with a natural hand!"
|
1: (
|
||||||
value = f"You won **${payout}**."
|
CONST.STRINGS["blackjack_busted"],
|
||||||
thumbnail_url = "https://i.imgur.com/dvIIr2G.png"
|
CONST.STRINGS["blackjack_lost"].format(Currency.format_human(bet)),
|
||||||
color = discord.Color.green()
|
discord.Color.red(),
|
||||||
|
CONST.CLOUD_ART,
|
||||||
else:
|
),
|
||||||
name = "I.. don't know if you won?"
|
2: (
|
||||||
value = "This is an error, please report it."
|
CONST.STRINGS["blackjack_won_21"],
|
||||||
color = discord.Color.red()
|
CONST.STRINGS["blackjack_won_payout"].format(Currency.format_human(payout)),
|
||||||
|
discord.Color.green(),
|
||||||
|
CONST.TROPHY_ART,
|
||||||
|
),
|
||||||
|
3: (
|
||||||
|
CONST.STRINGS["blackjack_dealer_busted"],
|
||||||
|
CONST.STRINGS["blackjack_won_payout"].format(Currency.format_human(payout)),
|
||||||
|
discord.Color.green(),
|
||||||
|
CONST.TROPHY_ART,
|
||||||
|
),
|
||||||
|
4: (
|
||||||
|
CONST.STRINGS["blackjack_lost_generic"],
|
||||||
|
CONST.STRINGS["blackjack_lost"].format(Currency.format_human(bet)),
|
||||||
|
discord.Color.red(),
|
||||||
|
CONST.CLOUD_ART,
|
||||||
|
),
|
||||||
|
5: (
|
||||||
|
CONST.STRINGS["blackjack_won_natural"],
|
||||||
|
CONST.STRINGS["blackjack_won_payout"].format(Currency.format_human(payout)),
|
||||||
|
discord.Color.green(),
|
||||||
|
CONST.TROPHY_ART,
|
||||||
|
),
|
||||||
|
}.get(
|
||||||
|
status,
|
||||||
|
(
|
||||||
|
CONST.STRINGS["blackjack_error"],
|
||||||
|
CONST.STRINGS["blackjack_error_description"],
|
||||||
|
discord.Color.red(),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
name, value, color, thumbnail_url = result
|
||||||
|
embed.add_field(name=name, value=value, inline=False)
|
||||||
|
embed.colour = color
|
||||||
if thumbnail_url:
|
if thumbnail_url:
|
||||||
embed.set_thumbnail(url=thumbnail_url)
|
embed.set_thumbnail(url=thumbnail_url)
|
||||||
|
|
||||||
embed.add_field(
|
|
||||||
name=name,
|
|
||||||
value=value,
|
|
||||||
inline=False,
|
|
||||||
)
|
|
||||||
embed.colour = color
|
|
||||||
|
|
||||||
return embed
|
return embed
|
||||||
|
|
||||||
|
|
||||||
def get_new_deck():
|
def get_new_deck() -> List[Card]:
|
||||||
suits = CONST.BLACKJACK["deck_suits"]
|
deck = [
|
||||||
ranks = CONST.BLACKJACK["deck_ranks"]
|
rank + suit
|
||||||
deck = []
|
for suit in CONST.BLACKJACK["deck_suits"]
|
||||||
for suit in suits:
|
for rank in CONST.BLACKJACK["deck_ranks"]
|
||||||
for rank in ranks:
|
]
|
||||||
deck.append(rank + suit)
|
|
||||||
random.shuffle(deck)
|
random.shuffle(deck)
|
||||||
return deck
|
return deck
|
||||||
|
|
||||||
|
|
||||||
def deal_card(deck):
|
def deal_card(deck: List[Card]) -> Card:
|
||||||
return deck.pop()
|
return deck.pop()
|
||||||
|
|
||||||
|
|
||||||
def calculate_hand_value(hand):
|
def calculate_hand_value(hand: Hand) -> int:
|
||||||
value = 0
|
value = sum(
|
||||||
has_ace = False
|
10 if rank in "JQK" else 11 if rank == "A" else int(rank)
|
||||||
aces_count = 0
|
for card in hand
|
||||||
|
for rank in card[:-1]
|
||||||
for card in hand:
|
)
|
||||||
if card is None:
|
aces = sum(card[0] == "A" for card in hand)
|
||||||
continue
|
while value > 21 and aces:
|
||||||
|
value -= 10
|
||||||
rank = card[:-1]
|
aces -= 1
|
||||||
|
|
||||||
if rank.isdigit():
|
|
||||||
value += int(rank)
|
|
||||||
|
|
||||||
elif rank in ["J", "Q", "K"]:
|
|
||||||
value += 10
|
|
||||||
|
|
||||||
elif rank == "A":
|
|
||||||
value += 11
|
|
||||||
has_ace = True
|
|
||||||
aces_count += 1
|
|
||||||
|
|
||||||
"""
|
|
||||||
An Ace will have a value of 11 unless that would give a player
|
|
||||||
or the dealer a score in excess of 21; in which case, it has a value of 1
|
|
||||||
"""
|
|
||||||
if value > 21 and has_ace:
|
|
||||||
value -= 10 * aces_count
|
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
Loading…
Reference in a new issue