algorithmpokerpot

Distributing side pots in poker


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.


Solution

  • 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