Example #1
0
            private bool IsOpenEndedStraightDraw(CardList cardList)
            {
                if (cardList.Count < 4)
                {
                    return(false);
                }

                // Except if the ace is the last card, because there's no cards higher than the ace
                if (cardList.AreConsecutive(true, false, 4))
                {
                    // (list is sorted from lowest to highest)
                    cardList.Sort(SortUsing.AceHigh);

                    // Special case
                    if (cardList[cardList.Count - 1].Face == CardFace.Ace &&
                        cardList[cardList.Count - 2].Face == CardFace.King &&
                        cardList[cardList.Count - 3].Face == CardFace.Queen &&
                        cardList[cardList.Count - 4].Face == CardFace.Jack)
                    {
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }

                // Except if the ace is not the first card, there's no cards lower than the ace

                if (cardList.AreConsecutive(false, false, 4))
                {
                    cardList.Sort(SortUsing.AceLow);

                    // Special case
                    if (cardList[0].Face == CardFace.Ace &&
                        cardList[1].Face == CardFace.Two &&
                        cardList[2].Face == CardFace.Three &&
                        cardList[3].Face == CardFace.Four)
                    {
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }

                return(false);
            }
Example #2
0
            private PairType GetPairType(CardList communityCards, Card matching, Card firstCard, Card secondCard)
            {
                communityCards.Sort(SortUsing.AceHigh);

                // Pocket pair
                if (firstCard.Face == secondCard.Face)
                {
                    if (firstCard.GetFaceValue() >= communityCards.Last.GetFaceValue())
                    {
                        return(PairType.Top);
                    }
                    else if (firstCard.GetFaceValue() <= communityCards[0].GetFaceValue())
                    {
                        return(PairType.Bottom);
                    }
                    else
                    {
                        return(PairType.Middle);
                    }
                }
                else
                {
                    // Matched the board
                    if (matching.Face == communityCards.Last.Face)
                    {
                        return(PairType.Top);
                    }
                    else if (matching.Face == communityCards[0].Face)
                    {
                        return(PairType.Bottom);
                    }
                    else
                    {
                        return(PairType.Middle);
                    }
                }
            }
Example #3
0
            private bool IsInsideStraightDraw(CardList cardList, bool countAceAsHigh)
            {
                if (cardList.Count < 4)
                {
                    return(false);
                }

                cardList.Sort(countAceAsHigh);

                // Case 1 and 2 are special cases

                // Case 1: first card is an ace and we are not counting ace as low, followed by 2, 3, 4
                if (!countAceAsHigh &&
                    cardList[0].Face == CardFace.Ace &&
                    cardList[1].Face == CardFace.Two &&
                    cardList[2].Face == CardFace.Three &&
                    cardList[3].Face == CardFace.Four)
                {
                    return(true);
                }

                // Case 2: first card is a J and we are counting ace as high, followed by Q, K, A
                if (countAceAsHigh &&
                    cardList[0].Face == CardFace.Jack &&
                    cardList[1].Face == CardFace.Queen &&
                    cardList[2].Face == CardFace.King &&
                    cardList[3].Face == CardFace.Ace)
                {
                    return(true);
                }


                // Case 2: 1 card, missing, 3 straight
                for (int i = 0; i < (cardList.Count - 3); i++)
                {
                    int faceValue = cardList[i].GetFaceValue(countAceAsHigh);
                    if (cardList[i + 1].GetFaceValue(countAceAsHigh) == faceValue + 2 &&
                        cardList[i + 2].GetFaceValue(countAceAsHigh) == faceValue + 3 &&
                        cardList[i + 3].GetFaceValue(countAceAsHigh) == faceValue + 4)
                    {
                        return(true);
                    }
                }

                // Case 3: 2 straight, missing, 2 straight
                for (int i = 1; i < (cardList.Count - 2); i++)
                {
                    int faceValue = cardList[i].GetFaceValue(countAceAsHigh);
                    if (cardList[i - 1].GetFaceValue(countAceAsHigh) == faceValue - 1 &&
                        cardList[i + 1].GetFaceValue(countAceAsHigh) == faceValue + 2 &&
                        cardList[i + 2].GetFaceValue(countAceAsHigh) == faceValue + 3)
                    {
                        return(true);
                    }
                }

                // Case 4: 3 straight, missing, 1 card
                for (int i = 2; i < (cardList.Count - 1); i++)
                {
                    int faceValue = cardList[i].GetFaceValue(countAceAsHigh);
                    if (cardList[i - 2].GetFaceValue(countAceAsHigh) == faceValue - 2 &&
                        cardList[i - 1].GetFaceValue(countAceAsHigh) == faceValue - 1 &&
                        cardList[i + 1].GetFaceValue(countAceAsHigh) == faceValue + 2)
                    {
                        return(true);
                    }
                }

                return(false);
            }
Example #4
0
            public ClassificationPostflop(HoldemHand hand, HoldemGamePhase phase, HoldemBoard board)
            {
                CardList communityCards = board.GetBoardAt(phase);

                // Default
                this.hand         = HandType.Unknown;
                this.kicker       = KickerType.Unknown;
                this.pair         = PairType.Irrelevant;
                this.draw         = DrawType.Irrelevant;
                this.straightDraw = StraightDrawType.None;

                Trace.Assert(communityCards.Count > 0, "Cannot classificate an empty list of community cards.");

                // Create a new list including the board cards and the cards from the hand
                CardList cards = new CardList(communityCards.Count + 2);

                foreach (Card c in communityCards)
                {
                    cards.AddCard(c);
                }
                cards.AddCard(hand.GetFirstCard());
                cards.AddCard(hand.GetSecondCard());

                // --- Royal flush
                if (IsRoyalFlush(cards))
                {
                    this.hand   = HandType.RoyalFlush;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Four of a kind
                if (cards.HaveIdenticalFaces(4))
                {
                    this.hand   = HandType.FourOfAKind;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Full House
                // If we have three of a kind and two pair at the same time, we have a full house
                bool isThreeOfAKind = cards.HaveIdenticalFaces(3);
                bool isTwoPair      = IsTwoPair(cards);

                if (isThreeOfAKind && isTwoPair)
                {
                    this.hand   = HandType.FullHouse;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Flush
                for (int i = 0; i < cards.Count; i++)
                {
                    int numCardsSameSuit = 0;
                    for (int j = i + 1; j < cards.Count; j++)
                    {
                        if (cards[i].Suit == cards[j].Suit)
                        {
                            numCardsSameSuit++;
                        }
                    }

                    if (numCardsSameSuit >= 4)
                    {
                        this.hand   = HandType.Flush;
                        this.kicker = KickerType.Irrelevant;
                        return;
                    }
                }

                // -- Straight
                if (IsStraight(cards))
                {
                    this.hand   = HandType.Straight;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // Calculate draws (if we got until here, there might be some)
                // Also, no draws are possible at the river
                if (phase == HoldemGamePhase.River)
                {
                    draw         = DrawType.None;
                    straightDraw = StraightDrawType.None;
                }
                else
                {
                    draw = GetDrawType(cards);

                    if (IsInsideStraightDraw(cards))
                    {
                        straightDraw = StraightDrawType.InsideStraightDraw;
                    }

                    if (IsOpenEndedStraightDraw(cards))
                    {
                        straightDraw = StraightDrawType.OpenEndedStraightDraw;
                    }
                }

                // -- Trips
                if (isThreeOfAKind)
                {
                    this.hand   = HandType.ThreeOfAKind;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Two pair
                if (isTwoPair)
                {
                    this.hand   = HandType.TwoPair;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Pair
                Card matching;

                if (cards.HaveIdenticalFaces(2, out matching))
                {
                    // Sort list by face value (ace high first)
                    cards.Sort(SortUsing.AceHigh);

                    // Find kicker (check from end of the list where face values are higher)
                    Card kicker = cards[0];
                    for (int i = cards.Count - 1; i >= 0; i--)
                    {
                        if (cards[i].Face != matching.Face)
                        {
                            kicker = cards[i];
                            break;
                        }
                    }


                    this.hand   = HandType.Pair;
                    this.kicker = GetKickerTypeFromCard(kicker);
                    this.pair   = GetPairType(communityCards, matching, hand.GetFirstCard(), hand.GetSecondCard());
                    return;
                }

                // -- High card
                cards.Sort(SortUsing.AceHigh);
                Card highCard = cards.Last;

                this.hand   = HandType.HighCard;
                this.kicker = GetKickerTypeFromCard(highCard);
            }
Example #5
0
            private bool IsOpenEndedStraightDraw(CardList cardList)
            {
                if (cardList.Count < 4) return false;

                // Except if the ace is the last card, because there's no cards higher than the ace
                if (cardList.AreConsecutive(true, false, 4)){

                    // (list is sorted from lowest to highest)
                    cardList.Sort(SortUsing.AceHigh);

                    // Special case
                    if (cardList[cardList.Count - 1].Face == CardFace.Ace &&
                        cardList[cardList.Count - 2].Face == CardFace.King &&
                        cardList[cardList.Count - 3].Face == CardFace.Queen &&
                        cardList[cardList.Count - 4].Face == CardFace.Jack) return false;
                    else return true;
                }

                // Except if the ace is not the first card, there's no cards lower than the ace

                if (cardList.AreConsecutive(false, false, 4))
                {
                    cardList.Sort(SortUsing.AceLow);

                    // Special case
                    if (cardList[0].Face == CardFace.Ace &&
                        cardList[1].Face == CardFace.Two &&
                        cardList[2].Face == CardFace.Three &&
                        cardList[3].Face == CardFace.Four) return false;
                    else return true;
                }

                return false;
            }
Example #6
0
            private bool IsInsideStraightDraw(CardList cardList, bool countAceAsHigh)
            {
                if (cardList.Count < 4) return false;

                cardList.Sort(countAceAsHigh);

                // Case 1 and 2 are special cases

                // Case 1: first card is an ace and we are not counting ace as low, followed by 2, 3, 4
                if (!countAceAsHigh &&
                    cardList[0].Face == CardFace.Ace &&
                    cardList[1].Face == CardFace.Two &&
                    cardList[2].Face == CardFace.Three &&
                    cardList[3].Face == CardFace.Four) return true;

                // Case 2: first card is a J and we are counting ace as high, followed by Q, K, A
                if (countAceAsHigh &&
                    cardList[0].Face == CardFace.Jack &&
                    cardList[1].Face == CardFace.Queen &&
                    cardList[2].Face == CardFace.King &&
                    cardList[3].Face == CardFace.Ace) return true;

                // Case 2: 1 card, missing, 3 straight
                for (int i = 0; i < (cardList.Count - 3); i++)
                {
                    int faceValue = cardList[i].GetFaceValue(countAceAsHigh);
                    if (cardList[i + 1].GetFaceValue(countAceAsHigh) == faceValue + 2 &&
                        cardList[i + 2].GetFaceValue(countAceAsHigh) == faceValue + 3 &&
                        cardList[i + 3].GetFaceValue(countAceAsHigh) == faceValue + 4)
                    {
                        return true;
                    }
                }

                // Case 3: 2 straight, missing, 2 straight
                for (int i = 1; i < (cardList.Count - 2); i++)
                {
                    int faceValue = cardList[i].GetFaceValue(countAceAsHigh);
                    if (cardList[i - 1].GetFaceValue(countAceAsHigh) == faceValue - 1 &&
                        cardList[i + 1].GetFaceValue(countAceAsHigh) == faceValue + 2 &&
                        cardList[i + 2].GetFaceValue(countAceAsHigh) == faceValue + 3)
                    {
                        return true;
                    }
                }

                // Case 4: 3 straight, missing, 1 card
                for (int i = 2; i < (cardList.Count - 1); i++)
                {
                    int faceValue = cardList[i].GetFaceValue(countAceAsHigh);
                    if (cardList[i - 2].GetFaceValue(countAceAsHigh) == faceValue - 2 &&
                        cardList[i - 1].GetFaceValue(countAceAsHigh) == faceValue - 1 &&
                        cardList[i + 1].GetFaceValue(countAceAsHigh) == faceValue + 2)
                    {
                        return true;
                    }
                }

                return false;
            }
Example #7
0
            private PairType GetPairType(CardList communityCards, Card matching, Card firstCard, Card secondCard)
            {
                communityCards.Sort(SortUsing.AceHigh);

                // Pocket pair
                if (firstCard.Face == secondCard.Face)
                {
                    if (firstCard.GetFaceValue() >= communityCards.Last.GetFaceValue()) return PairType.Top;
                    else if (firstCard.GetFaceValue() <= communityCards[0].GetFaceValue()) return PairType.Bottom;
                    else return PairType.Middle;
                }
                else
                {
                    // Matched the board
                    if (matching.Face == communityCards.Last.Face) return PairType.Top;
                    else if (matching.Face == communityCards[0].Face) return PairType.Bottom;
                    else return PairType.Middle;
                }
            }
Example #8
0
            public ClassificationPostflop(HoldemHand hand, HoldemGamePhase phase, HoldemBoard board)
            {
                CardList communityCards = board.GetBoardAt(phase);

                // Default
                this.hand = HandType.Unknown;
                this.kicker = KickerType.Unknown;
                this.pair = PairType.Irrelevant;
                this.draw = DrawType.Irrelevant;
                this.straightDraw = StraightDrawType.None;

                Trace.Assert(communityCards.Count > 0, "Cannot classificate an empty list of community cards.");

                // Create a new list including the board cards and the cards from the hand
                CardList cards = new CardList(communityCards.Count + 2);
                foreach (Card c in communityCards) cards.AddCard(c);
                cards.AddCard(hand.GetFirstCard());
                cards.AddCard(hand.GetSecondCard());

                // --- Royal flush
                if (IsRoyalFlush(cards))
                {
                    this.hand = HandType.RoyalFlush;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Four of a kind
                if (cards.HaveIdenticalFaces(4))
                {
                    this.hand = HandType.FourOfAKind;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Full House
                // If we have three of a kind and two pair at the same time, we have a full house
                bool isThreeOfAKind = cards.HaveIdenticalFaces(3);
                bool isTwoPair = IsTwoPair(cards);
                if (isThreeOfAKind && isTwoPair)
                {
                    this.hand = HandType.FullHouse;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Flush
                for (int i = 0; i < cards.Count; i++)
                {
                    int numCardsSameSuit = 0;
                    for (int j = i + 1; j < cards.Count; j++)
                    {
                        if (cards[i].Suit == cards[j].Suit)
                        {
                            numCardsSameSuit++;
                        }
                    }

                    if (numCardsSameSuit >= 4)
                    {
                        this.hand = HandType.Flush;
                        this.kicker = KickerType.Irrelevant;
                        return;
                    }
                }

                // -- Straight
                if (IsStraight(cards))
                {
                    this.hand = HandType.Straight;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // Calculate draws (if we got until here, there might be some)
                // Also, no draws are possible at the river
                if (phase == HoldemGamePhase.River)
                {
                    draw = DrawType.None;
                    straightDraw = StraightDrawType.None;
                }
                else
                {
                    draw = GetDrawType(cards);

                    if (IsInsideStraightDraw(cards))
                    {
                        straightDraw = StraightDrawType.InsideStraightDraw;
                    }

                    if (IsOpenEndedStraightDraw(cards))
                    {
                        straightDraw = StraightDrawType.OpenEndedStraightDraw;
                    }
                }

                // -- Trips
                if (isThreeOfAKind)
                {
                    this.hand = HandType.ThreeOfAKind;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Two pair
                if (isTwoPair)
                {
                    this.hand = HandType.TwoPair;
                    this.kicker = KickerType.Irrelevant;
                    return;
                }

                // -- Pair
                Card matching;
                if (cards.HaveIdenticalFaces(2, out matching))
                {
                    // Sort list by face value (ace high first)
                    cards.Sort(SortUsing.AceHigh);

                    // Find kicker (check from end of the list where face values are higher)
                    Card kicker = cards[0];
                    for (int i = cards.Count - 1; i >= 0; i--)
                    {
                        if (cards[i].Face != matching.Face)
                        {
                            kicker = cards[i];
                            break;
                        }
                    }

                    this.hand = HandType.Pair;
                    this.kicker = GetKickerTypeFromCard(kicker);
                    this.pair = GetPairType(communityCards, matching, hand.GetFirstCard(), hand.GetSecondCard());
                    return;
                }

                // -- High card
                cards.Sort(SortUsing.AceHigh);
                Card highCard = cards.Last;

                this.hand = HandType.HighCard;
                this.kicker = GetKickerTypeFromCard(highCard);
            }