Losing money on win

Question: I’ve recently released a blackjack bot but there’s one problem which happens randomly and makes you lose way more than you’ve actually bet even though you’ve won (it happens if you lose too)

I’ve looked through the code myself to see if I could find any errors which might fix it but I haven’t and I have no clue where it could be coming from

Images of the error happening:


Repl link: https://replit.com/@chaosok/IdenticalLavishIntroductory

Blackjack command code:

class BlackjackView(discord.ui.View):
  def __init__(self, bot, ctx, bet, dealer_hand, dealer_total, player_hand, player_total, message):
      super().__init__()
      self.ctx = ctx
      self.bot = bot
      self.bet = bet
      self.dealer_hand = dealer_hand
      self.dealer_total = dealer_total
      self.player_hand = player_hand
      self.player_total = player_total
      self.message = message
      self.author_id = ctx.author.id

  async def interaction_check(self, interaction):
      if interaction.user.id != self.author_id:
          embed = discord.Embed(title="", description="This blackjack game isn't yours.", color=discord.Color.red())
          await interaction.response.send_message(embed=embed, ephemeral=True)
          return False
      return True

  @discord.ui.button(label="Hit", style=discord.ButtonStyle.green)
  async def hit_button_callback(self, interaction, button):
      await interaction.response.defer()
      self.player_hand.append(draw_card())
      self.player_total = calculate_total(self.player_hand)
      embed = self.message.embeds[0]
      embed.set_field_at(0, name=f"Your Cards: {self.player_total}", value=format_hand(self.player_hand), inline=False)
      await self.message.edit(embed=embed)

      if self.player_total > 21:
          await handle_loss(self.bot, self.ctx, self.bet, self.dealer_hand, self.dealer_total, self.player_hand,
                            self.player_total, self.message)
          self.stop()

  @discord.ui.button(label="Stand", style=discord.ButtonStyle.red)
  async def stand_button_callback(self, interaction, button):
      await interaction.response.defer()
      while self.dealer_total < 17:
          self.dealer_hand.append(draw_card())
          self.dealer_total = calculate_total(self.dealer_hand)

      embed = self.message.embeds[0]
      embed.set_field_at(1, name=f"Dealer's Cards: {self.dealer_total}", value=format_hand(self.dealer_hand),
                          inline=False)
      await self.message.edit(embed=embed)

      if self.dealer_total >= 17:
          if self.dealer_total > 21 or self.player_total > self.dealer_total:
              await handle_win(self.bot, self.ctx, self.bet, self.dealer_hand, self.dealer_total, self.player_hand,
                               self.player_total, self.message)
          elif self.player_total > 21 or self.player_total < self.dealer_total:
              await handle_loss(self.bot, self.ctx, self.bet, self.dealer_hand, self.dealer_total, self.player_hand,
                                self.player_total, self.message)
          else:
              await handle_tie(self.bot, self.ctx, self.bet, self.dealer_hand, self.dealer_total, self.player_hand,
                               self.player_total, self.message)
          self.stop()

@bot.command(name="blackjack", aliases=["bj"])
async def blackjack(ctx, bet: str):
    author_id = str(ctx.author.id)
    player_hand = [draw_card(), draw_card()]
    dealer_hand = [draw_card(), draw_card()]
    player_total = calculate_total(player_hand)
    dealer_total = calculate_total(dealer_hand[1:])

    try:
        with open('accounts.json', 'r') as f:
            accounts = json.load(f)
    except FileNotFoundError:
        accounts = {}

    if author_id not in accounts:
      embed = discord.Embed(description="You don't have an account. Use the ,open command to create one.", color=0xe69f23)
      await ctx.send(embed=embed)
      return

    try:
      if bet.lower() == 'all':
          bet_amount = accounts[author_id]['balance']
      elif bet.lower() == 'half':
          bet_amount = accounts[author_id]['balance'] // 2
      elif 'e' in bet.lower():
          bet_amount = float(bet)
      else:
          bet_amount = int(bet)
    except ValueError:
      embed = discord.Embed(description="Invalid bet amount.", color=discord.Color.red())
      await ctx.send(embed=embed)
      return

    if bet_amount <= 0:
      embed = discord.Embed(description="Invalid bet amount. Please provide a bet greater than zero.", color=discord.Color.red())
      await ctx.send(embed=embed)
      return

    if accounts[author_id]['balance'] < bet_amount:
      embed = discord.Embed(description="You don't have enough balance to place this bet.", color=discord.Color.red())
      await ctx.send(embed=embed)
      return

    embed = discord.Embed(title="", color=0x232428)
    embed.add_field(name=f"Your Cards: {player_total}", value=format_hand(player_hand), inline=False)
    embed.add_field(name=f"Dealer's Cards: {dealer_total}", value=f"{format_hand(dealer_hand[1:])} ??? ", inline=False)
    embed.add_field(name="Result", value="In progress", inline=False)
    embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
    embed.set_thumbnail(url="https://i.imgur.com/JBPnaZz.png")

    message = await ctx.send(embed=embed)
    view = BlackjackView(bot, ctx, bet_amount, dealer_hand, dealer_total, player_hand, player_total, message)
    await message.edit(view=view)

    try:
        accounts[author_id]['balance'] -= bet_amount
        with open('accounts.json', 'w') as f:
            json.dump(accounts, f)
    except KeyError:
        await ctx.send("You don't have enough balance to place this bet.")
        return
    except Exception as e:
        await ctx.send(f"An error occurred: {e}")
        return

def draw_card():
  cards = [
      (1, '<:ACE:1222736603525546104>'), (2, '<:TWO:1222736601461821550>'), 
      (3, '<:THREE:1222736640955650048>'), (4, '<:FOUR:1222736598161166357>'), 
      (5, '<:FIVE:1222736597028573285>'), (6, '<:SIX:1222736581467705455>'), 
      (7, '<:SEVEN:1222736595434737696>'), (8, '<:EIGHT:1222736594424041573>'), 
      (9, '<:NINE:1222736593329328189>'), (10, '<:TEN:1222736592158855218>'), 
      (10, '<:JACK:1222736587935322242>'), (10, '<:QUEEN:1222736589575295100>'), 
      (10, '<:KING:1222736590510493851>')
  ]
  return random.choice(cards)

def calculate_total(hand):
  total = sum(card[0] for card in hand) 
  num_aces = len([card for card in hand if card[0] == 1])
  while total <= 11 and num_aces > 0:
      total += 10
      num_aces -= 1
  return total

def format_hand(hand):
  return " ".join(card[1] for card in hand) 

async def handle_win(bot, ctx, bet, dealer_hand, dealer_total, player_hand, player_total, message):
  author_id = str(ctx.author.id)
  with open('accounts.json', 'r') as f:
      accounts = json.load(f)

  accounts[author_id]['balance'] += bet * 2
  new_balance = "{:,}".format(accounts[author_id]['balance'])

  with open('accounts.json', 'w') as f:
      json.dump(accounts, f)

  embed = discord.Embed(title="", color=0x232428)
  embed.add_field(name=f"Your Cards: {player_total}", value=f"{format_hand(player_hand)}", inline=False)
  embed.add_field(name=f"Dealer's Cards: {dealer_total}", value=format_hand(dealer_hand), inline=False)
  embed.add_field(name="Result", value=f"You won! Your new balance is: **{new_balance}**", inline=False)
  embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
  embed.set_thumbnail(url="https://i.imgur.com/JBPnaZz.png")
  await message.edit(embed=embed)

async def handle_loss(bot, ctx, bet, dealer_hand, dealer_total, player_hand, player_total, message):
  author_id = str(ctx.author.id)
  with open('accounts.json', 'r') as f:
      accounts = json.load(f)

  new_balance = "{:,}".format(accounts[author_id]['balance'])

  with open('accounts.json', 'w') as f:
      json.dump(accounts, f)

  embed = discord.Embed(title="", color=0x232428)
  embed.add_field(name=f"Your Cards: {player_total}", value=f"{format_hand(player_hand)}", inline=False)
  embed.add_field(name=f"Dealer's Cards: {dealer_total}", value=format_hand(dealer_hand), inline=False)
  embed.add_field(name="Result", value=f"You lost. Your new balance is: **{new_balance}**", inline=False)
  embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
  embed.set_thumbnail(url="https://i.imgur.com/JBPnaZz.png")
  await message.edit(embed=embed)

async def handle_tie(bot, ctx, bet, dealer_hand, dealer_total, player_hand, player_total, message):
  author_id = str(ctx.author.id)
  with open('accounts.json', 'r') as f:
      accounts = json.load(f)

  accounts[author_id]['balance'] += bet
  save_accounts(accounts)

  new_balance = "{:,}".format(accounts[author_id]['balance'])

  embed = discord.Embed(title="", color=0x232428)
  embed.add_field(name=f"Your Cards: {player_total}", value=f"{format_hand(player_hand)}", inline=False)
  embed.add_field(name=f"Dealer's Cards: {dealer_total}", value=format_hand(dealer_hand), inline=False)
  embed.add_field(name="Result", value=f"The hand is a push. Your balance remains: **{new_balance}**", inline=False)
  embed.set_author(name=ctx.author.name, icon_url=ctx.author.avatar.url)
  embed.set_thumbnail(url="https://i.imgur.com/JBPnaZz.png")
  await message.edit(embed=embed)

Did you solve it yet?

Sorry for the late reply, no I have not

the code looks good to me, I suggest you to put some logging/print/discord embed msg that shows internal variables value and account.json value for you to understand if it just got some unexpected value that caused this to happen
or at least you can use that way to find out which line done something it shouldnt

2 Likes

Use the logging system and focus on your handle_win , handle_loss , and handle_tie functions.