/// <summary> /// Calculate value of holdem/omaha hand (using at least min cards from hand). Board can be 3-5 cards. /// </summary> /// <param name="Value"></param> /// <param name=""></param> /// <param name="String"></param> /// <param name=""></param> /// <param name="String"></param> /// <param name=""></param> /// <param name="String"></param> /// <param name=""></param> /// <returns></returns> private int heValue(OmahaValue v, String[] board, String[] hole, String[] temp) { int hv = 0; for (int n = min; n <= 2; n++) { int nh = MathsUtil.binomialCoefficientFast(hole.Length, n); int nb = MathsUtil.binomialCoefficientFast(board.Length, 5 - n); for (int kh = 0; kh < nh; kh++) { MathsUtil.kCombination(n, kh, hole, temp, 0); for (int kb = 0; kb < nb; kb++) { MathsUtil.kCombination(5 - n, kb, board, temp, n); int val = v.value(temp); //System.out.println(Arrays.asList(h5) + " - " + Poker.desc(v)); if (val > hv) { hv = val; } } } } return(hv); }
/// <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); }
internal override void Next() { // get board combination MathsUtil.kCombination(k, p++, deck, board, current.Length); }