Example #1
0
 public override string[] draw(String[] cards, int drawn, String[] blockers, List <Draw> drawList)
 {
     return(DrawPrediction.getDrawingHand(drawList, cards, drawn, true, blockers));
 }
Example #2
0
        /// <summary>
        /// get the best drawing hand for the given hand, number drawn and hand valuation. optionally returns score of all possible drawing hands.
        /// </summary>
        /// <param name="list"></param>
        /// <param name="hand"></param>
        /// <param name="drawn"></param>
        /// <param name="high"></param>
        /// <param name="blockers"></param>
        /// <returns></returns>
        public static String[] getDrawingHand(List <Draw> list, String[] hand, int drawn, bool high, String[] blockers)
        {
            if (hand.Length > 5)
            {
                throw new ArgumentException("invalid hand: " + (string.Join(", ", hand)));
            }

            // XXX really should take into account multiple draws
            // but thats only really a problem if you draw a greater number on a
            // later street (which is a bad strategy and almost unheard of)
            // e.g. draw 1, 1, 5 - obviously can't use final hand to predict any of them
            // related problem is that a later hand might contain blockers from a
            // reshuffle and so can't possibly occur on an earlier street
            // and you might not even have enough cards that aren't blocked,
            // i.e. bincoff(length(hand - blockers), 5 - drawn) needs to be >= 1
            if (blockers != null && blockers.Length > 0)
            {
                String[] hand2 = ArrayUtil.sub(hand, blockers);
                if (hand2.Length != hand.Length)
                {
                    // some of the cards were blocked
                    // cheat and increase the draw amount (if necessary)
                    drawn = Math.Max(5 - hand2.Length, drawn);
                    hand  = hand2;
                }
            }

            BigInteger combs = MathsUtil.binomialCoefficient(hand.Length, 5 - drawn);

            if ((int)combs <= 0)
            {
                throw new ArgumentException("invalid combs: " + combs);
            }

            // XXX if only 1 comb, just return hand?

            // high draw works best with around 0.9, low draw with 0.99
            // generally, you can win in high with any top 10% hand, but low draw
            // pretty much needs 7-high (75432, 76432, 76542, etc) to win
            // XXX actually it probably depends if it's 2-7 single or triple draw
            double     bias = high ? 0.9 : 0.99;
            OmahaValue value;

            if (high)
            {
                value = new HiValue();
            }
            else
            {
                value = new DsLowValue();
            }

            if (drawn < 0 || drawn > 5)
            {
                throw new ArgumentException("invalid drawn: " + drawn);
            }
            else if (drawn == 5)
            {
                // special case, no draw and no meaningful score
                return(new String[0]);
            }
            else if (drawn == 0)
            {
                // special case, nothing to test other than given hand
                if (list != null)
                {
                    float s = score(value.value(hand), bias);
                    list.Add(new Draw(hand, s));
                }
                return(hand.ToArray());
            }

            // drawing 1-4

            // from players point of view, all other cards are possible (even the blockers)
            String[] deck      = OmahaPoker.remdeck(null, hand);
            String[] drawnHand = new String[5];
            int      imax      = MathsUtil.binomialCoefficientFast(hand.Length, 5 - drawn);
            int      jmax      = MathsUtil.binomialCoefficientFast(deck.Length, drawn);

            String[] maxDrawingHand = null;
            float    maxScore       = -1f;

            for (int i = 0; i < imax; i++)
            {
                ArrayUtil.Populate(drawnHand, null);
                // pick kept from hand
                MathsUtil.kCombination(5 - drawn, i, hand, drawnHand, 0);
                //System.out.println("drawnHand: " + Arrays.toString(drawnHand));
                float score = 0;

                for (int j = 0; j < jmax; j++)
                {
                    // pick drawn from deck
                    MathsUtil.kCombination(drawn, j, deck, drawnHand, 5 - drawn);
                    //System.out.println("  drawnHand: " + Arrays.toString(drawnHand));
                    int v = value.value(drawnHand);
                    score += DrawPrediction.score(v, bias);
                }

                float    averageScore = score / (1.0f * jmax);
                string[] drawingHand  = drawnHand.Take(5 - drawn).ToArray();

                if (list != null)
                {
                    Array.Sort(drawingHand, Cmp.revCardCmp);
                    list.Add(new Draw(drawingHand, averageScore));
                }

                if (score > maxScore)
                {
                    // copy new max hole cards
                    maxDrawingHand = drawingHand;
                    maxScore       = score;
                }
            }

            if (list != null)
            {
                list.Sort();
                list.Reverse();
            }
            return(maxDrawingHand);
        }