예제 #1
0
        public static CacheError ReturnUncalledBets(databaseCacheClient clientCache)
        {
            if (clientCache.getActivePositionsLeftToAct().Length != 0)
            {
                return(new CacheError(CacheError.ErrorType.ActionError, clientCache.TableId, clientCache.getCurrentHandId(), null, "Cannot end hand with players still to act"));
            }

            long[] playerIdsInHand =
                (from ha in clientCache.getAllHandActions()
                 where ha.handId == clientCache.getCurrentHandId()
                 where ha.actionType == PokerAction.Fold || ha.actionType == PokerAction.Call ||
                 ha.actionType == PokerAction.Raise || ha.actionType == PokerAction.BigBlind
                 select ha.playerId).Distinct().ToArray();

            decimal max1 = 0, max2 = 0, temp;
            long    max1ID = -1;

            for (int i = 0; i < playerIdsInHand.Count(); i++)
            {
                temp = clientCache.getTotalPlayerMoneyInPot(playerIdsInHand[i]);

                if (temp > max1)
                {
                    max2   = max1;
                    max1   = temp;
                    max1ID = playerIdsInHand[i];
                }
                else if (temp > max2)
                {
                    max2 = temp;
                }
            }

            if (max1 > max2)
            {
                var result = clientCache.newHandAction(max1ID, PokerAction.ReturnBet, max1 - max2);

                if (result != CacheError.noError)
                {
                    return(result);
                }
            }

            return(CacheError.noError);
        }
예제 #2
0
        public static CacheError AwardPot(databaseCacheClient clientCache, PokerRakeDelegate rakeCalculator, DateTime actionTime, int numCompletedHands)
        {
            #region awardPot

            if (clientCache.getActivePositions().Length > 1 && clientCache.getBettingRound() != 3)
            {
                return(new CacheError(CacheError.ErrorType.ActionError, clientCache.TableId, clientCache.getCurrentHandId(), null, "Cannot return bets or award pot with more than 1 player in hand unless all table cards are known"));
            }

            List <playerHandValue> playerHandValues = new List <playerHandValue>();
            //Last thing is to implement at sidepots and returned bets

            //For each player that is all in, work out how much they put in the pot
            //Determine how many individuals were in the pot when that player last bet
            //The sidepot for that player is their money * number players

            //Rank all the remaning players hands in order to correctly dish out the pot
            //We are going to ignore side pots for now ;)
            var activePositions    = clientCache.getActivePositions();
            var currentHandDetails = clientCache.getCurrentHandDetails();

            long[] satInPlayerIDs = clientCache.getSatInPlayerIds();

            long[] playerIdsInHand =
                (from ha in clientCache.getAllHandActions()
                 where ha.handId == clientCache.getCurrentHandId()
                 where ha.actionType == PokerAction.Fold || ha.actionType == PokerAction.Call ||
                 ha.actionType == PokerAction.Raise || ha.actionType == PokerAction.BigBlind
                 select ha.playerId).Distinct().ToArray();

            decimal[] allBetAmounts = new decimal[playerIdsInHand.Length];
            for (int i = 0; i < allBetAmounts.Length; i++)
            {
                allBetAmounts[i] = clientCache.getTotalPlayerMoneyInPot(playerIdsInHand[i]);
            }

            //Determine each positions HandValueObject
            for (int i = 0; i < playerIdsInHand.Length; i++)
            {
                long    playerId         = playerIdsInHand[i];
                string  playerName       = clientCache.getPlayerName(playerId);
                byte    playerPosition   = clientCache.getPlayerPosition(playerId);
                decimal playerMoneyInPot = clientCache.getTotalPlayerMoneyInPot(playerId);
                decimal maxWinAmount     = 0;
                int     playerHandValue  = 0;
                bool    hasFolded        = true;

                if (satInPlayerIDs.Contains(playerId) && activePositions.Contains(playerPosition))
                {
                    hasFolded = false;

                    if (activePositions.Length == 1)
                    {
                        playerHandValue = 100;
                    }
                    else if (clientCache.getPlayerHoleCards(playerId).holeCard1 == (byte)Card.NoCard)
                    {
                        playerHandValue = 0;
                    }
                    else
                    {
                        //if (GPAJob == null)
                        playerHandValue = HandRank.GetHandRank((Card)clientCache.getPlayerHoleCards(playerId).holeCard1, (Card)clientCache.getPlayerHoleCards(playerId).holeCard2, (Card)currentHandDetails.tableCard1, (Card)currentHandDetails.tableCard2, (Card)currentHandDetails.tableCard3, (Card)currentHandDetails.tableCard4, (Card)currentHandDetails.tableCard5);
                        //else
                        //    playerHandValue = GPAJob.HoleCardValues[numCompletedHands][playerPosition];
                    }

                    //Work out the maximum this player could win
                    for (int j = 0; j < allBetAmounts.Length; j++)
                    {
                        decimal result = allBetAmounts[j] - playerMoneyInPot;
                        if (result <= 0)
                        {
                            maxWinAmount += allBetAmounts[j];
                        }
                        else
                        {
                            maxWinAmount += playerMoneyInPot;
                        }
                    }
                }

                //Add this information to playerHandValues
                playerHandValues.Add(new playerHandValue(playerHandValue, playerId, playerName, playerMoneyInPot, maxWinAmount, hasFolded));
            }

            decimal deadBlindMoney = clientCache.getDeadBlindMoneyInPot();

            foreach (var handValue in playerHandValues)
            {
                if (handValue.maximumWinableAmount > 0)
                {
                    handValue.maximumWinableAmount += deadBlindMoney;
                }
            }

            //Sort ascending on maximum winable amount ascending.
            playerHandValues.Sort();

            //Linq version of sort from when sort didn't work in mono. See comments in CompareTo method in playerHandValue class

            /*
             * playerHandValues = (from values in playerHandValues
             *                  orderby values.maximumWinableAmount ascending
             *                  select values).ToList();
             */

            List <decimal> potAmounts = new List <decimal>();
            decimal        totalPot   = 0.0m;

            for (int i = 0; i < playerHandValues.Count; i++)
            {
                if (playerHandValues[i].maximumWinableAmount == 0.0m)
                {
                    continue;
                }

                if (playerHandValues[i].maximumWinableAmount > totalPot)
                {
                    potAmounts.Add(playerHandValues[i].maximumWinableAmount - totalPot);

                    totalPot = playerHandValues[i].maximumWinableAmount;
                }
            }

            int potIndex = 0;

            //Go through each player
            for (int i = 0; i < playerHandValues.Count; i++)
            {
                //if they cannot win any money continue the loop
                if (playerHandValues[i].maximumWinableAmount == 0.0m)
                {
                    continue;
                }

                //if there is a contested pot we need to do some thinking
                if (i < playerHandValues.Count - 1)
                {
                    //Work out the pot amount for this stage
                    decimal potAmount = playerHandValues[i].maximumWinableAmount;

                    //next work out the rake for this pot
                    decimal rake = rakeCalculator(clientCache, potAmounts, potIndex);

                    //Next go through each player with at least this amount to win and see how many winners of this pot there are
                    int winningRank = 0, winnerCount = 0;
                    for (int j = i; j < playerHandValues.Count; j++)
                    {
                        //if hand value of player is greatest than that found so far we have a new possible winner
                        if (playerHandValues[j].handValue > winningRank)
                        {
                            winningRank = playerHandValues[j].handValue;
                            winnerCount = 1;
                        }//if rank is equal to winning rank so far we have another winnner
                        else if (playerHandValues[j].handValue == winningRank && playerHandValues[j].maximumWinableAmount > 0)
                        {
                            winnerCount++;
                        }
                    }

                    //Now we know how many winners there are calculate amount each should get
                    decimal winAmountPerWinner = ((decimal)((int)(100 * (potAmount - rake) / winnerCount))) / 100.0m;

                    //work out odd cents number so we can give those to the players closest to dealer
                    int numberOddCents = (int)((potAmount - rake - winnerCount * winAmountPerWinner) * 100);

                    //Now do the rake if greater than 0
                    CacheError result = CacheError.noError;

                    if (rake > 0)
                    {
                        result = clientCache.newHandAction(clientCache.getPlayerId(clientCache.getCurrentHandDetails().dealerPosition), PokerAction.TableRake, rake);
                        if (result != CacheError.noError)
                        {
                            return(result);
                        }
                    }

                    playerHandValue[] winners;

                    //Get a list of winners and order by dealer distance if we have odd cents
                    if (numberOddCents != 0)
                    {
                        winners =
                            (from players in playerHandValues
                             where players.handValue == winningRank && players.maximumWinableAmount > 0
                             orderby clientCache.getActivePlayerDistanceToDealer(players.playerId) ascending
                             select players).ToArray();
                    }
                    else
                    {
                        winners =
                            (from players in playerHandValues
                             where players.handValue == winningRank && players.maximumWinableAmount > 0
                             select players).ToArray();
                    }

                    //go through each winner and award them their share of the pot adding a cent if there are still odd
                    //cents to dish out
                    for (int j = 0; j < winners.Count(); j++)
                    {
                        if (numberOddCents > 0)
                        {
                            result = clientCache.newHandAction(winners[j].playerId, PokerAction.WinPot, winAmountPerWinner + 0.01m);

                            numberOddCents--;
                        }
                        else
                        {
                            result = clientCache.newHandAction(winners[j].playerId, PokerAction.WinPot, winAmountPerWinner);
                        }

                        if (result != CacheError.noError)
                        {
                            return(result);
                        }
                    }

                    //now go through each player thats left and reduce their maximumWinablePot by this pot value
                    for (int j = i; j < playerHandValues.Count; j++)
                    {
                        playerHandValues[j].maximumWinableAmount -= potAmount;
                    }

                    potIndex++;
                }
                else
                {
                    //if we get here there must be extra pot to hand out to the last player

                    decimal    potAmount = playerHandValues[i].maximumWinableAmount;
                    decimal    rake      = rakeCalculator(clientCache, potAmounts, potIndex);
                    CacheError result;

                    result = clientCache.newHandAction(playerHandValues[i].playerId, PokerAction.WinPot, potAmount - rake);
                    if (result != CacheError.noError)
                    {
                        return(result);
                    }

                    if (rake > 0)
                    {
                        result = clientCache.newHandAction(clientCache.getPlayerId(clientCache.getCurrentHandDetails().dealerPosition), PokerAction.TableRake, rake);
                        if (result != CacheError.noError)
                        {
                            return(result);
                        }
                    }

                    playerHandValues[i].maximumWinableAmount -= potAmount;

                    potIndex++;
                }
            }

            //At this point the entire point must have been awarded
            //We want to break here instead of cause a cache error so that we can find out what the problem was!!
            decimal totalAwardedAmounts =
                (from wins in clientCache.getAllHandActions()
                 where wins.handId == clientCache.getCurrentHandId() && (wins.actionType == PokerAction.WinPot || wins.actionType == PokerAction.TableRake)
                 select wins.actionValue).Sum();

            if (totalAwardedAmounts != clientCache.getCurrentHandDetails().potValue)
            {
                return(new CacheError(CacheError.ErrorType.AmountInvalid, clientCache.TableId, clientCache.getCurrentHandId(), null, "The full pot amount has not been awarded."));
            }

            #endregion awardPot

            return(CacheError.noError);
        }