0

Hi I am developing a poker application and I am having some trouble distributing side pots.

The main issue is that I don't know how to distribute chips of players who have folded(dead chips).

Now my code does the following:

  1. Get the minimum bet of the all-in players.
  2. Multiply it by the number of players who have bet more than that amount.
  3. Give the pot to the winner(s) between the players who have bet more than the amount.
  4. Substract the all-in bet to the following side pots.
  5. Repeat number 1 until there are no more pots to distribute.

This is working when all players go all-in, but if one folds things get tricky.

For instance:

A bet(200). 

B all-in (80). 

C all-in (400). 

A folds. 

B wins the hand. 

So the first pot will be B(80) + C(80) and the remaining will be given to C.

A: +0.

B: +80.

C: +520.

Clearly doing something wrong here as B has the right to fight for 80 chips that A has bet.

angelmc
  • 23
  • 2
  • Welcome to Stack Overflow. Please take the [tour](https://stackoverflow.com/tour), read about what's on-topic in the [help center](https://stackoverflow.com/help/on-topic), and read [How to Ask a Good Question](https://stackoverflow.com/help/how-to-ask) as well as [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – Ivo Mori Jul 01 '20 at 08:18
  • *Now my code does the following* – please include your `code` (the relevant parts for your question). – Ivo Mori Jul 01 '20 at 08:20
  • 4
    I don't agree with the closure of this question. angelmc clearly stated what their code was doing and gave a concrete example of how it was wrong. Seeing the actual code wouldn't clarify the problem in any way (which is the specific algorithm rather than the code itself). – Paul Hankin Jul 01 '20 at 08:59
  • Obviously, no code was required to give an answer as you @PaulHankin gave one. I cannot vote to re-open the question – so I hope you voted to re-open it. – Ivo Mori Jul 01 '20 at 10:53

2 Answers2

2

Consider the nth chip from each player's bet. The players eligible for that chip are those that haven't folded, and have bet at least n. Divide the chip between the eligible players that hold the best hand.

In your example:

A 200 fold
B 80  call  [best hand]
C 400 call
  • Chips 1-80 from A have 2 eligible players (B and C) and B has the best hand. So B takes 80.
  • Chips 81-200 from A have 1 eligible player (C). C takes 120.
  • Chips 1-80 from B have 2 eligible players (B and C) and B has the best hand. So B takes 80.
  • Chips 1-80 from C have 2 eligible players (B and C) and B has the best hand. So B takes 80.
  • Chips 81-400 from C have 1 eligible player (C). C takes 320.

Overall, B takes 240 and C takes 440.

I wrote the description as working chip by chip, but you can optimize (as I did in the worked example) by considering ranges of chips cut at the bet sizes of all players that didn't fold (ie: at 80 and 400 in your example).

Paul Hankin
  • 54,811
  • 11
  • 92
  • 118
1

This code should handle all situations, and it handles distributing chips to folded players. I'm guessing your code has been completed for a LONG time, but I wasn't able to find code examples on StackOverflow that made sense when I was working on this poker side pot problem, so I'm sharing my own...

using System;
using System.Collections.Generic;

public class Player
{
    public ulong potCommitment;
    public uint handStrength;
    public ulong chipsRemaining;
    public bool folded = false;
    public Player(ulong pc, uint hs, ulong chipsBehind, bool isFolded): this(pc, hs, chipsBehind)
    {
        folded = isFolded;
    }

    public Player(ulong pc, uint hs, ulong chipsBehind)
    {
        potCommitment = pc;
        handStrength = hs;
        chipsRemaining = chipsBehind;
    }
}

public class Program
{
    public static List<Player> winners = new List<Player>();
    public static List<Player> players = new List<Player>();
    public static void Main()
    {
        players.Add(new Player(200, 60, 0, true));
        players.Add(new Player(80, 100, 0));
        players.Add(new Player(400, 85, 0, false));
        
        // Loop through players until no unclaimed chips in pot.
        while (PotChipsRemaining(players) > 0)
            PayOutWinners(CalculateAndSortWinners(players), players);

        // Refund players if remaining chips in pot (bigger/folded stacks)
        foreach (var player in players)
        {
            player.chipsRemaining += player.potCommitment;
            player.potCommitment = 0;
        }

        Console.WriteLine($"***********************\nFinal results:");
        PotChipsRemaining(players);
    }

    public static List<Player> CalculateAndSortWinners(List<Player> playersInHand)
    {
        uint highHand = 0;
        // Get highHand, skipping folded and empty pots
        foreach (var player in players) if (player.potCommitment > 0 && !player.folded)
        {
            if (player.handStrength > highHand)
            {
                winners.Clear();
                highHand = player.handStrength;
                winners.Add(player);
            }
            else if (player.handStrength == highHand)
            {
                winners.Add(player);
            }
        }

        winners.Sort((x, y) => x.potCommitment.CompareTo(y.potCommitment));
        return winners;
    }

    public static void PayOutWinners(List<Player> winners, List<Player> playersInHand)
    {
        ulong collectedSidePot;
        ulong currentCommitment, collectionAmount;
        List<Player> paidWinners = new List<Player>();
        foreach (var playerPot in winners)
        {
            collectedSidePot = 0;
            currentCommitment = playerPot.potCommitment;
            // Collect from all players who have money in pot
            foreach (var player in playersInHand) if (player.potCommitment > 0)
                {
                    collectionAmount = Math.Min(currentCommitment, player.potCommitment);
                    player.potCommitment -= collectionAmount;
                    collectedSidePot += collectionAmount;
                }

            int winnersToPay = 0;
            Console.WriteLine($"winners.count {winners.Count}");
            
            foreach (var player in winners) if (paidWinners.IndexOf(player) == -1) winnersToPay++;

            Console.WriteLine($"collectedSidePot: {collectedSidePot}  winnersToPay: {winnersToPay}");
            
            // Pay unpaid winners, tip dealer with remainders...
            foreach (var player in winners) if (paidWinners.IndexOf(player) == -1)
            {
                player.chipsRemaining += collectedSidePot / (ulong)winnersToPay;
                if (player.potCommitment <= 0)
                {
                    paidWinners.Add(player);
                    Console.WriteLine($"Player {players.IndexOf(player)} paid out.");
                }
            }
        }
        winners.Clear();
    }

    // Only count potchips for unfolded players. Also prints status to Console.
    public static ulong PotChipsRemaining(List<Player> playersInHand)
    {
        ulong tally = 0;
        foreach (var player in playersInHand) if (!player.folded)
            {
                Console.WriteLine($"Player {players.IndexOf(player)} chips: {player.chipsRemaining}  Commitment: {player.potCommitment} \tHandStrength: {player.handStrength}\tFolded: {player.folded}");
                tally += player.potCommitment;
            }

        foreach (var player in playersInHand) if (player.folded)
                Console.WriteLine($"Player {players.IndexOf(player)} chips: {player.chipsRemaining}  Commitment: {player.potCommitment} \tHandStrength: {player.handStrength}\tFolded: {player.folded}");

        return tally;
    }
}

Based on your example, I get this result:

Final results:
Player A chips: 0      HandStrength: 60    Folded: True
Player B chips: 240    HandStrength: 100   Folded: False
Player C chips: 440    HandStrength: 85    Folded: False

if you have any questions let me know.

Here's the fiddle, so scenarios can be tested: https://dotnetfiddle.net/P0wgR5

  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 12 '21 at 00:48