예제 #1
0
        private bool isFullHouse(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
        {
            FullRank fRankTrio;

            HandCard[] hcsRankTrio;
            HandCard[] hcsFillTrio;
            if (!isKindN(hi, out fRankTrio, out hcsRankTrio, out hcsFillTrio, 3, 0))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return(false);
            }
            TValue trioValue = fRankTrio.Values[0];

            FullRank fRankPair;

            HandCard[] hcsRankPair;
            HandInfo   hi2 = new HandInfo(new Hand(hi.CardsAll.Except(hcsRankTrio)), hi.WildCards());

            if (!isKindN(hi2, out fRankPair, out hcsRankPair, out hcsFill, 2, NumCardsInFinalHand - 3 - 2))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return(false);
            }
            TValue pairValue = fRankPair.Values[0];

            fRank = new FullRank(SimpleRank.FullHouse,
                                 Util.PairEnumerable(trioValue, pairValue).Concat(hcsFill.Select(hc => TValue.Ace)));
            hcsRank = hcsRankTrio.Concat(hcsRankPair).ToArray();
            return(true);
        }
예제 #2
0
        public void GetFullRank(
            Hand h,
            IEnumerable <Card> wildCards,
            out FullRank fRank,
            out HandCard[] hcsRank,
            out HandCard[] hcsFill)
        {
            Contract.Requires(h.Cards.Count() >= NumCardsInFinalHand, "Error: Not enough cards in hand for ranking");
            foreach (HandCard hc in h.Cards)
            {
                hc.TamedValue = TValue.NoValue;
                hc.TamedSuit  = TSuit.NoSuit;
            }
            HandInfo hi = new HandInfo(h, wildCards);

            foreach (Ranker.RankPredicate rankPredicate in rankPredicates)
            {
                if (rankPredicate(hi, out fRank, out hcsRank, out hcsFill))
                {
                    return;
                }
            }
            // If HighCard is one of the RankPredicates, we should never arrive here.
            fRank   = new FullRank();
            hcsRank = null;
            hcsFill = null;
        }
예제 #3
0
 public static void WriteRankProfile(Hand hand, IEnumerable<Card> wildCards, Ranker ranker)
 {
     HandInfo hi = new HandInfo(hand, wildCards);
     foreach (SimpleRank sRank in Ranker.StandardRanks)
     {
         FullRank fRank;
         HandCard[] hcsRank;
         HandCard[] hcsFill;
         if (ranker.RankPredicateMap[sRank](hi, out fRank, out hcsRank, out hcsFill))
         {
             Console.WriteLine("Examining hand as a hand of rank {0:s}", fRank.SRank.ToString());
             Console.Write("  ");
             Hand.WriteHandData(hand, wildCards, fRank, hcsRank, hcsFill);
         }
     }
 }
예제 #4
0
        public static void WriteRankProfile(Hand hand, IEnumerable <Card> wildCards, Ranker ranker)
        {
            HandInfo hi = new HandInfo(hand, wildCards);

            foreach (SimpleRank sRank in Ranker.StandardRanks)
            {
                FullRank   fRank;
                HandCard[] hcsRank;
                HandCard[] hcsFill;
                if (ranker.RankPredicateMap[sRank](hi, out fRank, out hcsRank, out hcsFill))
                {
                    Console.WriteLine("Examining hand as a hand of rank {0:s}", fRank.SRank.ToString());
                    Console.Write("  ");
                    Hand.WriteHandData(hand, wildCards, fRank, hcsRank, hcsFill);
                }
            }
        }
예제 #5
0
        private bool isHighCard(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
        {
            // Note: Any hand with 2+ cards and at least one wild card contains a pair.
            hcsRank = new HandCard[0];
            List <HandCard> fillTamed;
            List <HandCard> fillPlain;

            Util.TakeFill(NumCardsInFinalHand, hi.CardsUnbound, out fillTamed,
                          hi.CardsPlain.OrderByDescending(hc => hc.Value), out fillPlain);
            foreach (HandCard hc in fillTamed)
            {
                hc.TamedValue = TValue.Ace;
            }
            hcsFill = fillPlain.Reverse <HandCard>().Concat(fillTamed).ToArray();
            TValue[] vals = fillTamed
                            .Select(hc => hc.TamedValue)
                            .Concat(fillPlain.Select(hc => hc.Value))
                            .ToArray();
            fRank = new FullRank(SimpleRank.HighCard, vals);
            return(true);
        }
예제 #6
0
        public static void WriteRandomHandProfiles(
            Ranker ranker,
            int numCardsDealt           = 7,
            int numCardsInFinalHand     = 5,
            IEnumerable <Card> wilds    = null,
            int numSamplesPerSimpleRank = 10)
        {
            Console.WriteLine();
            Console.WriteLine("Press enter to write out full evaluation of random hands.");
            Console.Out.Flush();
            Console.ReadLine();

            TestHandGenerator handGen = new TestHandGenerator(0);

            foreach (SimpleRank sRank in Ranker.StandardRanks)
            {
                Console.WriteLine();
                Console.Write("Press enter to see full evaluation of hands of type {0:s}", sRank.ToString());
                Console.Out.Flush();
                Console.ReadLine();
                for (int i = 0; i < numSamplesPerSimpleRank; i++)
                {
                    Hand     h  = handGen.Generators[sRank](numCardsDealt, numCardsInFinalHand);
                    HandInfo hi = new HandInfo(h, wilds);
                    foreach (SimpleRank sRank2 in Ranker.StandardRanks)
                    {
                        FullRank   fRank;
                        HandCard[] hcsRank;
                        HandCard[] hcsFill;
                        if (ranker.RankPredicateMap[sRank2](hi, out fRank, out hcsRank, out hcsFill))
                        {
                            Console.WriteLine("Examining hand as a hand of rank {0:s}", fRank.SRank.ToString());
                            Console.Write("  ");
                            Hand.WriteHandData(h, wilds, fRank, hcsRank, hcsFill);
                        }
                    }
                }
            }
        }
예제 #7
0
파일: Program.cs 프로젝트: jaycoskey/Poker
        public static void WriteRandomHandProfiles(
            Ranker ranker,
            int numCardsDealt = 7,
            int numCardsInFinalHand = 5,
            IEnumerable<Card> wilds = null,
            int numSamplesPerSimpleRank = 10)
        {
            Console.WriteLine();
            Console.WriteLine("Press enter to write out full evaluation of random hands.");
            Console.Out.Flush();
            Console.ReadLine();

            TestHandGenerator handGen = new TestHandGenerator(0);
            foreach (SimpleRank sRank in Ranker.StandardRanks)
            {
                Console.WriteLine();
                Console.Write("Press enter to see full evaluation of hands of type {0:s}", sRank.ToString());
                Console.Out.Flush();
                Console.ReadLine();
                for (int i = 0; i < numSamplesPerSimpleRank; i++)
                {
                    Hand h = handGen.Generators[sRank](numCardsDealt, numCardsInFinalHand);
                    HandInfo hi = new HandInfo(h, wilds);
                    foreach (SimpleRank sRank2 in Ranker.StandardRanks)
                    {
                        FullRank fRank;
                        HandCard[] hcsRank;
                        HandCard[] hcsFill;
                        if (ranker.RankPredicateMap[sRank2](hi, out fRank, out hcsRank, out hcsFill))
                        {
                            Console.WriteLine("Examining hand as a hand of rank {0:s}", fRank.SRank.ToString());
                            Console.Write("  ");
                            Hand.WriteHandData(h, wilds, fRank, hcsRank, hcsFill);
                        }
                    }
                }
            }
        }
예제 #8
0
        private bool isTwoPair(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
        {
            // Note: In the presence of wild cards, any hand with two pair
            //       would also have a higher rank (e.g., 3 of a kind).
            FullRank fRank1;

            HandCard[] hcsRank1;
            HandCard[] hcsFill1;
            if (!isKindN(hi, out fRank1, out hcsRank1, out hcsFill1, 2, 0))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return(false);
            }
            TValue value1 = fRank1.Values[0];

            FullRank fRank2;

            HandCard[] hcsRank2;
            HandInfo   hi2 = new HandInfo(new Hand(hi.CardsAll.Except(hcsRank1)), hi.WildCards());

            if (!isKindN(hi2, out fRank2, out hcsRank2, out hcsFill, 2, NumCardsInFinalHand - 4))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return(false);
            }
            TValue value2 = fRank2.Values[0];

            TValue[] fillValues = hcsFill
                                  .Select(hc => hc.TamedValue == TValue.NoValue ? hc.Value : hc.TamedValue)
                                  .ToArray();
            IEnumerable <TValue> vals = Util.PairEnumerable(value1, value2).Concat(fillValues);

            fRank   = new FullRank(SimpleRank.TwoPair, vals);
            hcsRank = hcsRank1.Concat(hcsRank2).ToArray();
            return(true);
        }
예제 #9
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
 private bool isStraightN(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill, int n)
 {
     return isStraightOrStraightFlushN(hi, out fRank, out hcsRank, out hcsFill, false, n);
 }
예제 #10
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
 private bool isStraightFlush5(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
 {
     return isStraightOrStraightFlushN(hi, out fRank, out hcsRank, out hcsFill, true, 5);
 }
예제 #11
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
        private bool isKindN(
            HandInfo hi,
            out FullRank fRank,
            out HandCard[] hcsRank,
            out HandCard[] hcsFill,
            int n,
            int maxFillCount = int.MaxValue)
        {
            Contract.Requires(n >= 2 && n <= 5, String.Format("Error: Unrecognized n-of-a-kind: {0:d}", n));
            bool hasKindN = (!hi.HasPlainCards() && hi.UnboundCount() >= n)
                || (hi.ValueGram.Values.Max() >= n - hi.UnboundCount());
            if (!hasKindN)
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return false;
            }

            TValue kindVal;
            int numChosen;
            HandCard[] hcsChosen;
            var plainValues = hi.ValueGram.Keys;
            if (plainValues.Count() == 0)
            {
                kindVal = TValue.Ace;
                numChosen = 0;
                hcsChosen = new HandCard[0];
            }
            else
            {
                kindVal = plainValues.Where(val => hi.ValueGram[val] >= n - hi.UnboundCount()).Max();
                HandCard[] hcsAvail = hi.CardsPlain.Where(hc => hc.Value == kindVal).ToArray();
                numChosen = Math.Min(n, hcsAvail.Count());
                hcsChosen = hcsAvail.Take(numChosen).ToArray();
            }
            int numTamed = Math.Min(n - numChosen, hi.UnboundCount());
            HandCard[] hcsTamed = hi.CardsUnbound.Take(numTamed).ToArray();
            foreach (HandCard hc in hcsTamed) { hc.TamedValue = kindVal; }
            List<HandCard> fillTamed;
            List<HandCard> fillPlain;
            Util.TakeFill(Math.Min(NumCardsInFinalHand - n, maxFillCount),
                hi.CardsUnbound.Except(hcsTamed).OrderByDescending(hc => hc.Value),
                out fillTamed,
                hi.CardsPlain.Except(hcsChosen).OrderByDescending(hc => hc.Value),
                out fillPlain);
            foreach (HandCard hc in fillTamed) { hc.TamedValue = TValue.Ace; }
            SimpleRank sRank;
            switch (n)
            {
                case 5: sRank = SimpleRank.Kind5; break;
                case 4: sRank = SimpleRank.Kind4; break;
                case 3: sRank = SimpleRank.Kind3; break;
                case 2: sRank = SimpleRank.Kind2; break;
                default: throw new ArgumentException("n");
            }
            fRank = new FullRank(sRank,
                Util.SingletonEnumerable(kindVal)
                    .Concat(fillTamed.Select(hc => hc.TamedValue))
                    .Concat(fillPlain.Select(hc => hc.Value))
                );
            hcsRank = hcsChosen.Concat(hcsTamed).ToArray();
            hcsFill = fillTamed.Concat(fillPlain).ToArray();
            return true;
        }
예제 #12
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
 private bool isKind5(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
 {
     return isKindN(hi, out fRank, out hcsRank, out hcsFill, 5);
 }
예제 #13
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
 private bool isHighCard(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
 {
     // Note: Any hand with 2+ cards and at least one wild card contains a pair.
     hcsRank = new HandCard[0];
     List<HandCard> fillTamed;
     List<HandCard> fillPlain;
     Util.TakeFill(NumCardsInFinalHand, hi.CardsUnbound, out fillTamed,
         hi.CardsPlain.OrderByDescending(hc => hc.Value), out fillPlain);
     foreach (HandCard hc in fillTamed) { hc.TamedValue = TValue.Ace; }
     hcsFill = fillPlain.Reverse<HandCard>().Concat(fillTamed).ToArray();
     TValue[] vals = fillTamed
         .Select(hc => hc.TamedValue)
         .Concat(fillPlain.Select(hc => hc.Value))
         .ToArray();
     fRank = new FullRank(SimpleRank.HighCard, vals);
     return true;
 }
예제 #14
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
        private bool isFullHouse(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
        {
            FullRank fRankTrio;
            HandCard[] hcsRankTrio;
            HandCard[] hcsFillTrio;
            if (!isKindN(hi, out fRankTrio, out hcsRankTrio, out hcsFillTrio, 3, 0))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return false;
            }
            TValue trioValue = fRankTrio.Values[0];

            FullRank fRankPair;
            HandCard[] hcsRankPair;
            HandInfo hi2 = new HandInfo(new Hand(hi.CardsAll.Except(hcsRankTrio)), hi.WildCards());
            if (!isKindN(hi2, out fRankPair, out hcsRankPair, out hcsFill, 2, NumCardsInFinalHand - 3 - 2))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return false;
            }
            TValue pairValue = fRankPair.Values[0];
            fRank = new FullRank(SimpleRank.FullHouse,
                Util.PairEnumerable(trioValue, pairValue).Concat(hcsFill.Select(hc => TValue.Ace)));
            hcsRank = hcsRankTrio.Concat(hcsRankPair).ToArray();
            return true;
        }
예제 #15
0
        private bool isKindN(
            HandInfo hi,
            out FullRank fRank,
            out HandCard[] hcsRank,
            out HandCard[] hcsFill,
            int n,
            int maxFillCount = int.MaxValue)
        {
            Contract.Requires(n >= 2 && n <= 5, String.Format("Error: Unrecognized n-of-a-kind: {0:d}", n));
            bool hasKindN = (!hi.HasPlainCards() && hi.UnboundCount() >= n) ||
                            (hi.ValueGram.Values.Max() >= n - hi.UnboundCount());

            if (!hasKindN)
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return(false);
            }

            TValue kindVal;
            int    numChosen;

            HandCard[] hcsChosen;
            var        plainValues = hi.ValueGram.Keys;

            if (plainValues.Count() == 0)
            {
                kindVal   = TValue.Ace;
                numChosen = 0;
                hcsChosen = new HandCard[0];
            }
            else
            {
                kindVal = plainValues.Where(val => hi.ValueGram[val] >= n - hi.UnboundCount()).Max();
                HandCard[] hcsAvail = hi.CardsPlain.Where(hc => hc.Value == kindVal).ToArray();
                numChosen = Math.Min(n, hcsAvail.Count());
                hcsChosen = hcsAvail.Take(numChosen).ToArray();
            }
            int numTamed = Math.Min(n - numChosen, hi.UnboundCount());

            HandCard[] hcsTamed = hi.CardsUnbound.Take(numTamed).ToArray();
            foreach (HandCard hc in hcsTamed)
            {
                hc.TamedValue = kindVal;
            }
            List <HandCard> fillTamed;
            List <HandCard> fillPlain;

            Util.TakeFill(Math.Min(NumCardsInFinalHand - n, maxFillCount),
                          hi.CardsUnbound.Except(hcsTamed).OrderByDescending(hc => hc.Value),
                          out fillTamed,
                          hi.CardsPlain.Except(hcsChosen).OrderByDescending(hc => hc.Value),
                          out fillPlain);
            foreach (HandCard hc in fillTamed)
            {
                hc.TamedValue = TValue.Ace;
            }
            SimpleRank sRank;

            switch (n)
            {
            case 5: sRank = SimpleRank.Kind5; break;

            case 4: sRank = SimpleRank.Kind4; break;

            case 3: sRank = SimpleRank.Kind3; break;

            case 2: sRank = SimpleRank.Kind2; break;

            default: throw new ArgumentException("n");
            }
            fRank = new FullRank(sRank,
                                 Util.SingletonEnumerable(kindVal)
                                 .Concat(fillTamed.Select(hc => hc.TamedValue))
                                 .Concat(fillPlain.Select(hc => hc.Value))
                                 );
            hcsRank = hcsChosen.Concat(hcsTamed).ToArray();
            hcsFill = fillTamed.Concat(fillPlain).ToArray();
            return(true);
        }
예제 #16
0
        private bool isFlushN(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill, int n)
        {
            Contract.Requires(n >= 4 && n <= 5, String.Format("Error: Unrecognized flush size: {0:d}", n));
            bool hasFlushN = (!hi.HasPlainCards() && hi.UnboundCount() >= n) ||
                             (hi.SuitGram.Values.Max() >= n - hi.UnboundCount());

            if (!hasFlushN)
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return(false);
            }

            TSuit flushSuit;
            int   numChosen = 0;
            IEnumerable <HandCard> hcsChosen;

            if (!hi.HasPlainCards())
            {
                flushSuit = Card.Suits.First();     // Any suit will do
                numChosen = 0;
                hcsChosen = new HandCard[0];
            }
            else
            {
                var sg = hi.SuitGram;
                // Note: suits can only have Length > 1 if the hand has >= 2 * numCardsInFullHand cards.
                TSuit[] candidateSuits = sg.Keys.Where(s => sg[s] >= n - hi.UnboundCount()).ToArray();
                if (candidateSuits.Length == 1)
                {
                    flushSuit = candidateSuits[0];
                }
                else
                {   // Determine which suit is best
                    var cardSeqEnum = candidateSuits
                                      .Select(s => hi.CardsPlain
                                              .Where(hc => hc.Suit == s)
                                              .OrderByDescending(hc => hc.Value));
                    var cardSeqOrd = cardSeqEnum
                                     .OrderByDescending(hcs => (IEnumerable <HandCard>)hcs,
                                                        new EnumerableComparer <HandCard>());
                    var cardSeq = cardSeqOrd.First();
                    flushSuit = cardSeq.First().Suit;
                }
                HandCard[] hcsAvail = hi.CardsPlain.Where(hc => hc.Suit == flushSuit).ToArray();
                numChosen = Math.Min(n, hcsAvail.Count());
                hcsChosen = hcsAvail.OrderByDescending(hc => hc.Value).Take(numChosen);
            }
            HandCard[] hcsTamed = hi.CardsUnbound.Take(n - numChosen).ToArray();
            foreach (HandCard hcs in hcsTamed)
            {
                hcs.TamedValue = TValue.Ace;
                hcs.TamedSuit  = flushSuit;
            }

            List <HandCard> fillTamed;
            List <HandCard> fillPlain;

            Util.TakeFill(NumCardsInFinalHand - n,
                          hi.CardsUnbound.Except(hcsTamed), out fillTamed,
                          hi.CardsPlain.Except(hcsChosen), out fillPlain);
            foreach (HandCard hcs in fillTamed)
            {
                hcs.TamedValue = TValue.Ace;
            }
            ; SimpleRank sRank;
            switch (n)
            {
            case 4: sRank = SimpleRank.Flush4; break;

            case 5: sRank = SimpleRank.Flush5; break;

            default: throw new ApplicationException(String.Format(
                                                        String.Format("Error: Unrecognized flush size: {0:d}", n)));
            }
            ;
            fRank = new FullRank(sRank,
                                 hcsTamed.Select(hc => hc.TamedValue)
                                 .Concat(hcsChosen.Select(hc => hc.Value).OrderByDescending(v => v))
                                 .Concat(fillTamed.Select(hc => hc.TamedValue))
                                 .Concat(fillPlain.Select(hc => hc.Value).OrderByDescending(v => v)));
            hcsRank = hcsChosen.Concat(hcsTamed).ToArray();
            hcsFill = fillTamed.Concat(fillPlain).ToArray();
            return(true);
        }
예제 #17
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
 public void GetFullRank(
     Hand h,
     IEnumerable<Card> wildCards,
     out FullRank fRank,
     out HandCard[] hcsRank,
     out HandCard[] hcsFill)
 {
     Contract.Requires(h.Cards.Count() >= NumCardsInFinalHand, "Error: Not enough cards in hand for ranking");
     foreach (HandCard hc in h.Cards)
     {
         hc.TamedValue = TValue.NoValue;
         hc.TamedSuit = TSuit.NoSuit;
     }
     HandInfo hi = new HandInfo(h, wildCards);
     foreach (Ranker.RankPredicate rankPredicate in rankPredicates)
     {
         if (rankPredicate(hi, out fRank, out hcsRank, out hcsFill))
         {
             return;
         }
     }
     // If HighCard is one of the RankPredicates, we should never arrive here.
     fRank = new FullRank();
     hcsRank = null;
     hcsFill = null;
 }
예제 #18
0
        private bool isStraightOrStraightFlushN(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill, bool isFlushRequired, int n)
        {
            bool   isStraight      = false;
            bool   isStraightFlush = false;
            TValue minVal          = TValue.NoValue; // Suppress compiler warning
            TValue maxVal;
            IEnumerable <IGrouping <TValue, HandCard> > valueGroups = null;
            TSuit flushSuit = TSuit.NoSuit;

            // Note: The loop could be started at Max(hcsPlain.Value) + hi.UnboundCount()
            for (maxVal = TValue.Ace;
                 maxVal >= (TValue)n; // TValue.Five
                 maxVal = maxVal.Prev())
            {
                minVal      = maxVal.Prev(n - 1);
                valueGroups = hi.CardsPlain
                              .Where(hc => (hc.Value >= minVal && hc.Value <= maxVal) || (minVal == TValue.LowAce && hc.Value == TValue.Ace))
                              .GroupBy(hc => hc.Value);
                isStraight = valueGroups.Count() >= n - hi.UnboundCount();
                if (isStraight && isFlushRequired)
                {
                    foreach (TSuit s in Card.Suits)
                    {
                        if (valueGroups.All(grp => grp.Any(hc => hc.Suit == s)))
                        {
                            flushSuit       = s;
                            isStraightFlush = true;
                            break;
                        }
                    }
                }
                if (isStraight && (isStraightFlush || !isFlushRequired))
                {
                    break;
                }
            }
            if (!isStraight || (isFlushRequired && !isStraightFlush))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return(false);
            }
            Func <HandCard, bool> pred = null;

            if (isFlushRequired)
            {
                pred = hc => hc.Suit == flushSuit;
            }
            IEnumerable <HandCard> hcsAvail = valueGroups.EnumerableChoice(pred);

            hcsRank = new HandCard[n];
            hcsFill = new HandCard[NumCardsInFinalHand - n];
            int             index      = 0;
            List <HandCard> hcsUnbound = new List <HandCard>(hi.CardsUnbound);    // Need random access

            for (TValue val = minVal; val <= maxVal; val = val.Next())
            {
                HandCard nextCard = hcsAvail.Where(hc => hc.Value == val).FirstOrDefault();
                if (nextCard != null)
                {
                    hcsRank[index] = nextCard;
                }
                else
                {
                    Debug.Assert(hcsUnbound.Count > 0, "Error: Not enough cards to form straight");
                    IEnumerable <HandCard> hcDesired = hcsUnbound.Where(hc => hc.Value == val).Take(1);
                    if (hcDesired.Count() > 0)
                    {
                        hcsRank[index] = hcDesired.ElementAt(0);
                        hcsUnbound.Remove(hcsRank[index]);
                    }
                    else
                    {
                        hcsRank[index] = hcsUnbound[0];
                        hcsUnbound.RemoveAt(0);
                    }
                    hcsRank[index].TamedValue = val;
                    if (isFlushRequired)
                    {
                        hcsRank[index].TamedSuit = flushSuit;
                    }
                }
                index++;
            }
            fRank = new FullRank(
                isFlushRequired
                    ? SimpleRank.StraightFlush5
                    : SimpleRank.Straight5,
                Enumerable.Range((int)minVal, ((int)maxVal - (int)minVal) + 1)
                .OrderByDescending(x => x)
                .Select(x => (TValue)x)
                .ToArray()
                );
            return(true);
        }
예제 #19
0
 private bool isStraightN(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill, int n)
 {
     return(isStraightOrStraightFlushN(hi, out fRank, out hcsRank, out hcsFill, false, n));
 }
예제 #20
0
 private bool isStraightFlush5(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
 {
     return(isStraightOrStraightFlushN(hi, out fRank, out hcsRank, out hcsFill, true, 5));
 }
예제 #21
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
 private bool isStraightOrStraightFlushN(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill, bool isFlushRequired, int n)
 {
     bool isStraight = false;
     bool isStraightFlush = false;
     TValue minVal = TValue.NoValue;     // Suppress compiler warning
     TValue maxVal;
     IEnumerable<IGrouping<TValue, HandCard>> valueGroups = null;
     TSuit flushSuit = TSuit.NoSuit;
     // Note: The loop could be started at Max(hcsPlain.Value) + hi.UnboundCount()
     for (maxVal = TValue.Ace;
         maxVal >= (TValue)n; // TValue.Five
         maxVal = maxVal.Prev())
     {
         minVal = maxVal.Prev(n - 1);
         valueGroups = hi.CardsPlain
             .Where(hc => (hc.Value >= minVal && hc.Value <= maxVal) || (minVal == TValue.LowAce && hc.Value == TValue.Ace))
             .GroupBy(hc => hc.Value);
         isStraight = valueGroups.Count() >= n - hi.UnboundCount();
         if (isStraight && isFlushRequired)
         {
             foreach (TSuit s in Card.Suits)
             {
                 if (valueGroups.All(grp => grp.Any(hc => hc.Suit == s)))
                 {
                     flushSuit = s;
                     isStraightFlush = true;
                     break;
                 }
             }
         }
         if (isStraight && (isStraightFlush || !isFlushRequired)) { break; }
     }
     if (!isStraight || (isFlushRequired && !isStraightFlush))
     {
         setToNull(out fRank, out hcsRank, out hcsFill);
         return false;
     }
     Func<HandCard, bool> pred = null;
     if (isFlushRequired)
     {
         pred = hc => hc.Suit == flushSuit;
     }
     IEnumerable<HandCard> hcsAvail = valueGroups.EnumerableChoice(pred);
     hcsRank = new HandCard[n];
     hcsFill = new HandCard[NumCardsInFinalHand - n];
     int index = 0;
     List<HandCard> hcsUnbound = new List<HandCard>(hi.CardsUnbound);    // Need random access
     for (TValue val = minVal; val <= maxVal; val = val.Next())
     {
         HandCard nextCard = hcsAvail.Where(hc => hc.Value == val).FirstOrDefault();
         if (nextCard != null)
         {
             hcsRank[index] = nextCard;
         }
         else
         {
             Debug.Assert(hcsUnbound.Count > 0, "Error: Not enough cards to form straight");
             IEnumerable<HandCard> hcDesired = hcsUnbound.Where(hc => hc.Value == val).Take(1);
             if (hcDesired.Count() > 0)
             {
                 hcsRank[index] = hcDesired.ElementAt(0);
                 hcsUnbound.Remove(hcsRank[index]);
             }
             else
             {
                 hcsRank[index] = hcsUnbound[0];
                 hcsUnbound.RemoveAt(0);
             }
             hcsRank[index].TamedValue = val;
             if (isFlushRequired) { hcsRank[index].TamedSuit = flushSuit; }
         }
         index++;
     }
     fRank = new FullRank(
             isFlushRequired
             ? SimpleRank.StraightFlush5
             : SimpleRank.Straight5,
         Enumerable.Range((int)minVal, ((int)maxVal - (int)minVal) + 1)
             .OrderByDescending(x => x)
             .Select(x => (TValue) x)
             .ToArray()
         );
     return true;
 }
예제 #22
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
        private bool isFlushN(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill, int n)
        {
            Contract.Requires(n >= 4 && n <= 5, String.Format("Error: Unrecognized flush size: {0:d}", n));
            bool hasFlushN = (!hi.HasPlainCards() && hi.UnboundCount() >= n)
                || (hi.SuitGram.Values.Max() >= n - hi.UnboundCount());
            if (!hasFlushN)
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return false;
            }

            TSuit flushSuit;
            int numChosen = 0;
            IEnumerable<HandCard> hcsChosen;
            if (!hi.HasPlainCards())
            {
                flushSuit = Card.Suits.First();     // Any suit will do
                numChosen = 0;
                hcsChosen = new HandCard[0];
            }
            else
            {
                var sg = hi.SuitGram;
                // Note: suits can only have Length > 1 if the hand has >= 2 * numCardsInFullHand cards.
                TSuit[] candidateSuits = sg.Keys.Where(s => sg[s] >= n - hi.UnboundCount()).ToArray();
                if (candidateSuits.Length == 1)
                {
                    flushSuit = candidateSuits[0];
                }
                else
                {   // Determine which suit is best
                    var cardSeqEnum = candidateSuits
                        .Select(s => hi.CardsPlain
                            .Where(hc => hc.Suit == s)
                            .OrderByDescending(hc => hc.Value));
                    var cardSeqOrd = cardSeqEnum
                        .OrderByDescending(hcs => (IEnumerable<HandCard>) hcs,
                            new EnumerableComparer<HandCard>());
                    var cardSeq = cardSeqOrd.First();
                    flushSuit = cardSeq.First().Suit;
                }
                HandCard[] hcsAvail = hi.CardsPlain.Where(hc => hc.Suit == flushSuit).ToArray();
                numChosen = Math.Min(n, hcsAvail.Count());
                hcsChosen = hcsAvail.OrderByDescending(hc => hc.Value).Take(numChosen);
            }
            HandCard[] hcsTamed = hi.CardsUnbound.Take(n - numChosen).ToArray();
            foreach (HandCard hcs in hcsTamed)
            {
                hcs.TamedValue = TValue.Ace;
                hcs.TamedSuit = flushSuit;
            }

            List<HandCard> fillTamed;
            List<HandCard> fillPlain;
            Util.TakeFill(NumCardsInFinalHand - n,
                hi.CardsUnbound.Except(hcsTamed), out fillTamed,
                hi.CardsPlain.Except(hcsChosen), out fillPlain);
            foreach (HandCard hcs in fillTamed) { hcs.TamedValue = TValue.Ace; }
            ; SimpleRank sRank;
            switch (n)
            {
                case 4: sRank = SimpleRank.Flush4; break;
                case 5: sRank = SimpleRank.Flush5; break;
                default: throw new ApplicationException(String.Format(
                    String.Format("Error: Unrecognized flush size: {0:d}", n)));
            };
            fRank = new FullRank(sRank,
                hcsTamed.Select(hc => hc.TamedValue)
                    .Concat(hcsChosen.Select(hc => hc.Value).OrderByDescending(v => v))
                    .Concat(fillTamed.Select(hc => hc.TamedValue))
                    .Concat(fillPlain.Select(hc => hc.Value).OrderByDescending(v => v)));
            hcsRank = hcsChosen.Concat(hcsTamed).ToArray();
            hcsFill = fillTamed.Concat(fillPlain).ToArray();
            return true;
        }
예제 #23
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
        private bool isTwoPair(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
        {
            // Note: In the presence of wild cards, any hand with two pair
            //       would also have a higher rank (e.g., 3 of a kind).
            FullRank fRank1;
            HandCard[] hcsRank1;
            HandCard[] hcsFill1;
            if (!isKindN(hi, out fRank1, out hcsRank1, out hcsFill1, 2, 0))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return false;
            }
            TValue value1 = fRank1.Values[0];

            FullRank fRank2;
            HandCard[] hcsRank2;
            HandInfo hi2 = new HandInfo(new Hand(hi.CardsAll.Except(hcsRank1)), hi.WildCards());
            if (!isKindN(hi2, out fRank2, out hcsRank2, out hcsFill, 2, NumCardsInFinalHand - 4))
            {
                setToNull(out fRank, out hcsRank, out hcsFill);
                return false;
            }
            TValue value2 = fRank2.Values[0];
            TValue[] fillValues = hcsFill
                .Select(hc => hc.TamedValue == TValue.NoValue ? hc.Value : hc.TamedValue)
                .ToArray();
            IEnumerable<TValue> vals = Util.PairEnumerable(value1, value2).Concat(fillValues);
            fRank = new FullRank(SimpleRank.TwoPair, vals);
            hcsRank = hcsRank1.Concat(hcsRank2).ToArray();
            return true;
        }
예제 #24
0
 private bool isKind5(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
 {
     return(isKindN(hi, out fRank, out hcsRank, out hcsFill, 5));
 }
예제 #25
0
파일: Ranker.cs 프로젝트: jaycoskey/Poker
 private bool isFlush4(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
 {
     return isFlushN(hi, out fRank, out hcsRank, out hcsFill, 4);
 }
예제 #26
0
 private bool isFlush4(HandInfo hi, out FullRank fRank, out HandCard[] hcsRank, out HandCard[] hcsFill)
 {
     return(isFlushN(hi, out fRank, out hcsRank, out hcsFill, 4));
 }