Example #1
0
        public override MEquity[] Equity(string[] board, string[][] holeCards, string[] blockers, int draws)
        {
            if (draws != 0)
            {
                throw new ArgumentException("invalid draws: " + draws);
            }

            validateBoard(board);
            foreach (var hole in holeCards)
            {
                validateHoleCards(hole);
            }

            // cards not used by hands or board
            String[] deck = OmahaPoker.remdeck(holeCards, board, blockers);

            if (board.Length <= 1)
            {
                // monte carlo (random sample boards)
                return(equityImpl(new HEBoardSample(deck, board, 10000), holeCards));
            }
            else
            {
                // all possible boards
                return(equityImpl(new HEBoardEnum(deck, board), holeCards));
            }
        }
Example #2
0
        public int Compare(string c1, string c2)
        {
            int v = OmahaPoker.faceValueAH(c1) - OmahaPoker.faceValueAH(c2);

            if (v == 0)
            {
                v = OmahaPoker.suit(c1) - OmahaPoker.suit(c2);
            }
            return(polarity * v);
        }
Example #3
0
        /**
         * Return string representing current value of hand
         */
        internal static String currentString(MEquity me)
        {
            String s = OmahaPoker.valueString(me.eqs[0].current);

            if (me.HiLo)
            {
                // s += " Hi: " + Poker.valueString(me.eqs[1].current);
                s += " / " + OmahaPoker.valueString(me.eqs[2].current);
            }
            return(s);
        }
Example #4
0
        /// <summary>
        ///  Go through every possible 5 card hand and collect the unique hand values in order
        /// </summary>
        /// <returns></returns>
        internal static int[] highValues()
        {
            if (uniqueHighValues != null)
            {
                return(uniqueHighValues);
            }

            HashSet <int> uniqueValueSet = new HashSet <int>();

            String[] hand       = new String[5];
            int      valueCount = 0;

            for (int n0 = 0; n0 < deckArr.Length; n0++)
            {
                hand[0] = deckArr[n0];
                for (int n1 = n0 + 1; n1 < deckArr.Length; n1++)
                {
                    hand[1] = deckArr[n1];
                    for (int n2 = n1 + 1; n2 < deckArr.Length; n2++)
                    {
                        hand[2] = deckArr[n2];
                        for (int n3 = n2 + 1; n3 < deckArr.Length; n3++)
                        {
                            hand[3] = deckArr[n3];
                            for (int n4 = n3 + 1; n4 < deckArr.Length; n4++)
                            {
                                hand[4] = deckArr[n4];
                                uniqueValueSet.Add(OmahaPoker.Value(hand));
                                valueCount++;
                            }
                        }
                    }
                }
            }

            int[] a = new int[uniqueValueSet.Count];
            int   i = 0;

            foreach (int v in uniqueValueSet)
            {
                a[i++] = v;
            }

            Array.Sort(a);
            uniqueHighValues = a;
            return(a);
        }
Example #5
0
        /// <summary>
        ///  get normalised score of hand (i.e. hand value is 0-1), optionally
        ///  inverted.bias is 0.5 to 1, representing how many values are less than
        ///  0.5, e.g. 0.9 means 90% of values are less than 0.5
        /// </summary>
        /// <param name=""></param>
        /// <param name="value"></param>
        /// <param name=""></param>
        /// <param name="bias"></param>
        /// <returns></returns>
        protected static float score(int value, double bias)
        {
            if (bias < 0.5 || bias > 1.0)
            {
                throw new ArgumentException("invalid bias " + bias);
            }

            // get high value
            bool high;
            int  highValue;

            switch (value & OmahaPoker.TYPE)
            {
            case OmahaPoker.HI_TYPE:
                high      = true;
                highValue = value;
                break;

            case OmahaPoker.DS_LOW_TYPE:
                high      = false;
                highValue = OmahaPoker.HI_TYPE | (OmahaPoker.MAX_RANK - (value & OmahaPoker.HAND));
                break;

            default:
                // ace to five doesn't include str/fl
                // but then, no drawing games use ace to five values so doesn't matter
                throw new ArgumentException("can't get score of " + value.ToString("X4"));
            }

            int[] highValues = OmahaPoker.highValues();
            int   p          = Array.BinarySearch(highValues, highValue);

            if (p < 0)
            {
                throw new ArgumentException("not a high value: " + highValue.ToString("X4"));
            }

            if (!high)
            {
                // invert score for deuce to seven low
                p = highValues.Length - 1 - p;
            }

            // raise score to some power to bias toward high values
            // note: for k=x^y, y=log(k)/log(x)... i think
            return((float)Math.Pow((1f * p) / (highValues.Length - 1f), Math.Log(0.5) / Math.Log(bias)));
        }
Example #6
0
 /// <summary>
 ///  Summarise out probabilities for given number of picks from remaining cards
 /// </summary>
 /// <param name="remCards"></param>
 /// <param name="picks"></param>
 /// <param name="samples"></param>
 internal void summariseOuts(float remCards, float picks, float samples)
 {
     if (outcount != null)
     {
         // maximum number of times an out can appear (average if sampled)
         // prob of appearing once is picks/remCards, just multiply by samples
         // (n,k,s) = (k*s)/n
         // (52,1,52) = 1,  (52,2,1326) = 51,  (52,3,100000) = 5769
         float max = (picks * samples) / remCards;
         //System.out.println(String.format("sum outs(%f,%f,%f) max=%f", remCards, picks, samples, max));
         for (int n = 0; n < outcount.Count(); n++)
         {
             int count = outcount[n];
             if (count > 0)
             {
                 String card = OmahaPoker.indexToCard(n);
                 float  pc   = (count * 100f) / max;
                 outs.Add(new Out(card, pc));
             }
         }
         outs.Sort();
         outs.Reverse();
     }
 }
Example #7
0
 public override int value(string[] hand)
 {
     return(OmahaPoker.afLowValue(hand));
 }
Example #8
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);
        }
Example #9
0
        /**
         * Update equities win, tie and win rank with given hand values for the
         * given cards. Return index of single winner (scoop), if any, or -1
         */
        private static int updateMEquities2(MEquity[] meqs, OmahaEquity.EquityType eqtype, int[] vals, String[] cards)
        {
            // find highest hand and number of times it occurs
            int max = 0, maxcount = 0;

            for (int i = 0; i < vals.Length; i++)
            {
                int v = vals[i];
                if (v > max)
                {
                    max      = v;
                    maxcount = 1;
                }
                else if (v == max)
                {
                    maxcount++;
                }
            }

            int winner = -1;

            for (int i = 0; i < vals.Length; i++)
            {
                if (vals[i] == max)
                {
                    // update the win/tied/rank count
                    OmahaEquity e = meqs[i].getEquity(eqtype);
                    if (maxcount == 1)
                    {
                        winner = i;
                        e.woncount++;
                    }
                    else
                    {
                        e.tiedcount++;
                        e.tiedwithcount += maxcount;
                    }
                    e.wonrankcount[OmahaPoker.rank(max)]++;

                    // count the cards as outs if this turns losing hand into
                    // win/tie or tying hand into win
                    if (cards != null && e.current > 0 && (!(e.curwin || e.curtie) || (e.curtie && maxcount == 1)))
                    {
                        for (int c = 0; c < cards.Length; c++)
                        {
                            String card      = cards[c];
                            int    cardIndex = OmahaPoker.cardToIndex(card);
                            e.outcount[cardIndex]++;
                        }
                    }

                    // XXX experimental - String[][] mcards

                    /*
                     * if (mcards != null && e.current > 0 && (!e.curwin ||
                     * (e.curtie && maxcount == 1))) { for (int c = 0; c <
                     * mcards[i].length; c++) { String card = mcards[i][c]; int
                     * cardIndex = Poker.cardToIndex(card); e.outcount[cardIndex]++;
                     * } }
                     */
                }
            }

            return(winner);
        }
Example #10
0
 public int Compare(String c1, String c2)
 {
     // highest first
     return(polarity * (OmahaPoker.faceValueAH(c2) - OmahaPoker.faceValueAH(c1)));
 }