Beispiel #1
0
        //public override ActionType GetAction(GameState gameState, out int amount)
        //{
        //    amount = gameState.CallAmount;
        //    return ActionType.Call;
        //}

        // This doesn't try to calc every possible combination of turn and river cards (as too many and too slow)
        // Instead it looks at turn card and then calcs two chances to get this . It doesn't consider drawing two cards to improve hand as these are unlikely and unlikely to change probs much
        public override double EstProbWinningShowdown(GameState gameState)
        {
            int          numUnseen      = gameState.UnseenCards.Count;
            HandAndBoard myHandAndBoard = gameState.MyHandAndBoard;

            Card[] opponentHoleCards = new Card[2];
            Dictionary <string, double> opponentHands       = new Dictionary <string, double>();
            Dictionary <string, Hand>   myBestHandAfterDraw = new Dictionary <string, Hand>();

            // Loop through all possible hands for opponent
            for (int i = 0; i < numUnseen; i++)
            {
                opponentHoleCards[0] = gameState.UnseenCards[i];

                for (int j = i + 1; j < numUnseen; j++)
                {
                    // Evaluate opponents hand
                    opponentHoleCards[1] = gameState.UnseenCards[j];
                    PocketCards opponentPocketCards = new PocketCards(opponentHoleCards[0], opponentHoleCards[1]);

                    HandAndBoard oppHandAndBoard = new HandAndBoard();
                    oppHandAndBoard.HoleCards = opponentPocketCards;
                    oppHandAndBoard.Board     = gameState.Board;
                    oppHandAndBoard.Evaluate();

                    int[]        results = new int[3];
                    int          result;
                    HandAndBoard lowHand, highHand;

                    // Work out who is winning at the moment (before any card is drawn)
                    result = myHandAndBoard.CurrentBestHand.Compare(oppHandAndBoard.CurrentBestHand);

                    if (result < 0)
                    {
                        // opponent is currently winning
                        lowHand  = myHandAndBoard;
                        highHand = oppHandAndBoard;
                    }
                    else
                    {
                        // I'm currently winning (or tie)
                        lowHand  = oppHandAndBoard;
                        highHand = myHandAndBoard;
                    }

                    // Get a list of cards that could change the result (ie low hand outdraws the high hand). Still need to check this list as high hand could improve as well.
                    List <Card> unseenList       = gameState.UnseenCards.Where(p => p.ValueStr() != opponentHoleCards[0].ValueStr() && p.ValueStr() != opponentHoleCards[1].ValueStr()).ToList();
                    List <Card> drawCardsToCheck = GetCardsThatCouldChangeResult(unseenList, lowHand, highHand);

                    // award wins/tie for all draw cards that don't change result
                    results[result + 1] = unseenList.Count - drawCardsToCheck.Count;

                    // for each possible card that could change the result check what the result would be
                    foreach (Card draw in drawCardsToCheck)
                    {
                        List <Card> drawBoard = new List <Card>(gameState.Board);
                        drawBoard.Add(draw);

                        Hand   myBestHand;
                        string drawCardValue = draw.ValueStr();

                        if (myBestHandAfterDraw.ContainsKey(drawCardValue))
                        {
                            myBestHand = myBestHandAfterDraw[drawCardValue];
                        }
                        else
                        {
                            myBestHand = Hand.FindPlayersBestHand(gameState.MyCards.CardList, drawBoard);
                            myBestHandAfterDraw.Add(drawCardValue, myBestHand);
                        }

                        Hand opponentBestHand = Hand.FindPlayersBestHand(opponentHoleCards, drawBoard);
                        results[myBestHand.Compare(opponentBestHand) + 1]++;
                    }

                    double probBeatingOpponentHand = 0;

                    // double probBeatingOpponentHand = (results[2] + results[1] / 2.0) / (results[0] + results[1] + results[2]);
                    if (result < 0)
                    {
                        // opponent currently winning. I need to hit draw card in one of next two cards
                        // or opponent needs to hit two cards that are not ones that win it for me

                        // !!! is this the correct way to handle ties?
                        double winsForOpponent = results[0] + results[1] / 2.0;
                        double cardsRemaining  = unseenList.Count;

                        probBeatingOpponentHand = 1 - ((winsForOpponent / cardsRemaining) * ((winsForOpponent - 1) / (cardsRemaining - 1)));
                    }
                    else
                    {
                        // tie or I am currently winning. Opponent needs to hit draw card in one of next two cards
                        // or I need to hit two cards that are not ones that win it for opponent
                        double winsForMe      = results[2] + results[1] / 2.0;
                        double cardsRemaining = unseenList.Count;

                        probBeatingOpponentHand = (winsForMe / cardsRemaining) * ((winsForMe - 1) / (cardsRemaining - 1));
                    }

                    string opponentHandString = opponentHoleCards[0].ValueStr() + opponentHoleCards[1].ValueStr();
                    opponentHands.Add(opponentHandString, probBeatingOpponentHand);
                }
            }

            // !!! This bit is common to flop/turn/river - should not be duplicated
            double estimate = 1;

            foreach (PlayerProfile p in gameState.ActiveOpponents())
            {
                double probBeatingThisOpponent = 0;

                foreach (KeyValuePair <string, double> kvp in opponentHands)
                {
                    probBeatingThisOpponent += kvp.Value * p.PointsForPossibleHands.PointsForHand(kvp.Key);
                }

                probBeatingThisOpponent /= p.PointsForPossibleHands.TotalPoints;

                estimate *= probBeatingThisOpponent;
            }

            return(estimate);
        }
        public double EstProbWinningShowdownFastMethod(GameState gameState)
        {
            int          numUnseen      = gameState.UnseenCards.Count;
            HandAndBoard myHandAndBoard = gameState.MyHandAndBoard;

            Card[] opponentHoleCards = new Card[2];
            Dictionary <string, double> opponentHands      = new Dictionary <string, double>();
            Dictionary <string, Hand>   myBestHandForRiver = new Dictionary <string, Hand>();

            // Loop through all possible hands for opponent
            for (int i = 0; i < numUnseen; i++)
            {
                opponentHoleCards[0] = gameState.UnseenCards[i];

                for (int j = i + 1; j < numUnseen; j++)
                {
                    // Evaluate opponents hand
                    opponentHoleCards[1] = gameState.UnseenCards[j];
                    PocketCards opponentPocketCards = new PocketCards(opponentHoleCards[0], opponentHoleCards[1]);

                    HandAndBoard oppHandAndBoard = new HandAndBoard();
                    oppHandAndBoard.HoleCards = opponentPocketCards;
                    oppHandAndBoard.Board     = gameState.Board;
                    oppHandAndBoard.Evaluate();

                    int[]        results = new int[3];
                    int          result;
                    HandAndBoard lowHand, highHand;

                    // Work out who is winning at the moment (before the river card is drawn)
                    result = myHandAndBoard.CurrentBestHand.Compare(oppHandAndBoard.CurrentBestHand);

                    if (result < 0)
                    {
                        // opponent is currently winning
                        lowHand  = myHandAndBoard;
                        highHand = oppHandAndBoard;
                    }
                    else
                    {
                        // I'm currently winning (or tie)
                        lowHand  = oppHandAndBoard;
                        highHand = myHandAndBoard;
                    }

                    // Get a list of cards that could change the result (ie low hand outdraws the high hand). Still need to check this list as high hand could improve as well.
                    List <Card> unseenList        = gameState.UnseenCards.Where(p => p.ValueStr() != opponentHoleCards[0].ValueStr() && p.ValueStr() != opponentHoleCards[1].ValueStr()).ToList();
                    List <Card> riverCardsToCheck = GetCardsThatCouldChangeResult(unseenList, lowHand, highHand);

                    // award wins/tie for all river cards that don't change result
                    results[result + 1] = unseenList.Count - riverCardsToCheck.Count;

                    // for each possible rivercard that could change the result check what the result would be
                    foreach (Card river in riverCardsToCheck)
                    {
                        List <Card> riverBoard = new List <Card>(gameState.Board);
                        riverBoard.Add(river);

                        Hand   myBestHand;
                        string riverCardValue = river.ValueStr();

                        if (myBestHandForRiver.ContainsKey(riverCardValue))
                        {
                            myBestHand = myBestHandForRiver[riverCardValue];
                        }
                        else
                        {
                            myBestHand = Hand.FindPlayersBestHand(gameState.MyCards.CardList, riverBoard);
                            myBestHandForRiver.Add(riverCardValue, myBestHand);
                        }

                        Hand opponentBestHand = Hand.FindPlayersBestHand(opponentHoleCards, riverBoard);
                        results[myBestHand.Compare(opponentBestHand) + 1]++;
                    }

                    double probBeatingOpponentHand = (results[2] + results[1] / 2.0) / (results[0] + results[1] + results[2]);
                    string opponentHandString      = opponentHoleCards[0].ValueStr() + opponentHoleCards[1].ValueStr();
                    opponentHands.Add(opponentHandString, probBeatingOpponentHand);
                }
            }

            // !!! This bit is common to preflop/flop/turn/river - should not be duplicated
            double estimate = 1;

            foreach (PlayerProfile p in gameState.ActiveOpponents())
            {
                double probBeatingThisOpponent = 0;

                foreach (KeyValuePair <string, double> kvp in opponentHands)
                {
                    probBeatingThisOpponent += kvp.Value * p.PointsForPossibleHands.PointsForHand(kvp.Key);
                }

                probBeatingThisOpponent /= p.PointsForPossibleHands.TotalPoints;

                estimate *= probBeatingThisOpponent;
            }

            return(estimate);
        }
Beispiel #3
0
        public virtual List <Card> GetCardsThatCouldChangeResult(List <Card> unseenCards, HandAndBoard lowHand, HandAndBoard highHand)
        {
            List <Card> cards            = new List <Card>();
            PocketCards lowPocketCards   = lowHand.HoleCards;
            Hand        lowCurrBestHand  = lowHand.CurrentBestHand;
            Hand        highCurrBestHand = lowHand.CurrentBestHand;
            EHandType   lowCurrHandType  = lowCurrBestHand.HandRank();
            EHandType   highCurrHandType = highCurrBestHand.HandRank();

            // if low hand has a straight draw and high hand <= straight then add cards that would give the low hand a straight
            if (lowHand.IsStraightDraw && highHand.CurrentBestHand.HandRank() <= EHandType.HandStraight)
            {
                foreach (ERankType rank in lowHand.RanksToMakeStraight)
                {
                    cards.AddRange(unseenCards.Where(p => p.Rank == rank));
                }
            }

            // if low hand has a flush draw and high hand <= flush then add cards that would give the low hand a flush
            if (lowHand.IsFlushDraw && highHand.CurrentBestHand.HandRank() <= EHandType.HandFlush)
            {
                cards.AddRange(unseenCards.Where(p => p.Suit == lowHand.SuitToMakeFlush));
            }

/*
 *          // This should be covered by above (!!! unless high hand > flush)
 *          // if low hand has a straight flush draw then add cards that would give the low hand a straight flush
 *          if(lowHand.IsStraightFlushDraw)
 *          {
 *              foreach(Card c in lowHand.CardsToMakeStraightFlush)
 *              {
 *                  if(unseenCards.Contains(c))
 *                  {
 *                      cards.Add(c);
 *                  }
 *              }
 *          }
 */

            // Check for drawing dead
            if (highCurrHandType == EHandType.HandFours && lowCurrHandType <= EHandType.HandTwoPair)
            {
                return(cards);
            }

            if (highCurrHandType == EHandType.HandFullHouse && lowCurrHandType <= EHandType.HandPair)
            {
                return(cards);
            }

            if (highCurrHandType >= EHandType.HandTwoPair && lowCurrHandType == EHandType.HandRunt)
            {
                return(cards);
            }

            // simple check - add any card of same rank as low hand pocket cards.
            cards.AddRange(unseenCards.Where(p => p.Rank == lowPocketCards.LowCard.Rank));
            if (!lowPocketCards.IsPair)
            {
                cards.AddRange(unseenCards.Where(p => p.Rank == lowPocketCards.HighCard.Rank));
            }

            // Also need to consider edge cases where a card pairs with board card and helps low hand but not high hand - eg high hand has flush, river card pairs with board
            // gives low hand (but not high hand) a full house.
            // Another edge case is where high hand has two pair (no pocket pair, but two cards paired with cards on board) and low hand has a pocket pair that is higher than highest of two pair
            // A drawn card that pairs with a board would give you a higher two pair.
            // Always checking all board cards is too slow!

/*
 *          foreach(Card c in lowHand.Board)
 *          {
 *              cards.AddRange(unseenCards.Where(p => p.Rank == c.Rank));
 *          }
 */

            return(cards.Distinct().ToList());
        }
Beispiel #4
0
        public void SeeBoardCard(EBoardCardType cardType, Card boardCard)
        {
            // update unseen card list
            UnseenCards.Remove(boardCard);
            Board.Add(boardCard);

            foreach (PlayerProfile p  in ActiveOpponents())
            {
                p.PointsForPossibleHands.RemoveHandsContaining(boardCard);
            }

            if (cardType == EBoardCardType.BoardFlop3)
            {
                InitStage(Stage.StageFlop);
            }
            else if (cardType == EBoardCardType.BoardTurn)
            {
                InitStage(Stage.StageTurn);
            }
            else if (cardType == EBoardCardType.BoardRiver)
            {
                InitStage(Stage.StageRiver);
            }

            // !!! eliminate possibilities for opponent hands

            // if you are not alive then you don't have a hand
            if (Players[MyPlayerId].IsAlive &&
                (cardType == EBoardCardType.BoardFlop3 ||
                 cardType == EBoardCardType.BoardTurn ||
                 cardType == EBoardCardType.BoardRiver)
                )
            {
                //// !!! this probably should be in the PocketCards class
                //List<Card> myCards = new List<Card>();
                //myCards.Add(MyCards.HighCard);
                //myCards.Add(MyCards.LowCard);

                // determine your best hand
//                MyBestHand = Hand.FindPlayersBestHand(MyCards.CardList, Board);

                // !!! move this bit to SeeBoardCard?
                MyHandAndBoard           = new HandAndBoard();
                MyHandAndBoard.HoleCards = MyCards;
                MyHandAndBoard.Board     = Board;
                MyHandAndBoard.Evaluate();


                // !!! determine nuts. Don't bet if your hand is far from nuts (unless bluff)?
                // !!! determine possible best hands for opponents (also include straight draws and flush draws)
                // for each possible hand ranks (that beats mine) - highest to lowest
                //      work out which pocket cards could make these (exclude cards already used on higher ranked hands)

                // for each opponent
                //      what is prob opponent hold them?

                // How to factor in draws to calc prob of winning showdown?
                // How to factor in hands of equal rank to mine?
                // Need to work through examples

                // !!! work out cards I am concerned opponent holds.
                // !!! work out good and bad cards for turn /river (cards that help me or cards that hurt me)
                // !!! calc your prob of winning showdown
            }
        }