Exemple #1
0
        public ApproximationResults Approximate(CardCollection deadCards, params Range[] ranges)
        {
            var allApprox = ranges.Select(r => r.SelectedHoleCardBinaries
                                          .Where(b => !_cards.ContainsSome(b) && (deadCards == null || !deadCards.ContainsSome(b))))
                            .CartesianProduct()
                            .Select(s => Approximate(s.ToArray(), deadCards, trials: 100))
                            .ToList();

            var   players   = new List <float>(new float[ranges.Length]);
            float splitProb = 0f;

            foreach (var approx in allApprox)
            {
                splitProb += approx.SplitProbability;
                for (int p = 0; p < ranges.Length; p++)
                {
                    players[p] += approx[p].Equity;
                }
            }
            players.ForEach(p => p /= allApprox.Count);
            splitProb /= allApprox.Count;

            return(new ApproximationResults(players.Select((eq, i) => new ApproximationResults.PlayerResults(i, eq, 3UL)), splitProb)); // Todo: add ranges to result
        }
Exemple #2
0
        public void ApproximateLive(Action <IEnumerable <float>, float> updateLiveResults, CardCollection deadCards, CancellationToken?cancellationToken, params Range[] ranges)
        {
            var rnd          = new Random();
            var nativeRanges = ranges.Select(r => r.SelectedHoleCardBinaries.Where(b => !_cards.ContainsSome(b) && (!deadCards?.ContainsSome(b) ?? true)).ToList()).ToList();

            cancellationToken?.ThrowIfCancellationRequested();


            ulong[]? localHoleCards = new ulong[nativeRanges.Count];
            ulong allLocalHoleCards;

            float[]? totalEquity = new float[nativeRanges.Count];
            float splitEquity = 0f;

            int  firstSelectedPlayer = 0;
            int  skippedSituations   = 0;
            bool skipSituation       = false;

            for (int i = 0; i < Int32.MaxValue; i++)
            {
                // Stop if requested
                cancellationToken?.ThrowIfCancellationRequested();

                allLocalHoleCards = 0;
                // Select random hole cards from each player to test
                // Do not select from the same player first every time,
                // the equities can be affected by this (e.g. AA-KK vs AA-KK vs AA-KK)
                int j = firstSelectedPlayer;
                do
                {
                    var validHoleCards = nativeRanges[j].Where(hc => (hc & allLocalHoleCards) == 0).ToList();

                    if (!validHoleCards.Any())
                    {
                        if (skippedSituations > (i < 1000 ? 950 : i * 0.95f))
                        {
                            throw new NashException("Ranges are too narrow. Please adjust.");
                        }
                        skipSituation = true;
                        break;
                    }

                    localHoleCards[j]  = validHoleCards[rnd.Next(validHoleCards.Count)];
                    allLocalHoleCards |= localHoleCards[j];

                    // if the last player is reached wrap around to the first one
                    if (++j >= nativeRanges.Count)
                    {
                        j = 0;
                    }
                } while (j != firstSelectedPlayer);

                // skip this situation if not all hole cards were chosen
                // try with same first player to not influence the results
                if (skipSituation)
                {
                    skippedSituations++;
                    skipSituation = false;
                    continue;
                }

                // update first player for next run
                if (++firstSelectedPlayer >= nativeRanges.Count)
                {
                    firstSelectedPlayer = 0;
                }

                // Add to total equity
                var results = Approximate(localHoleCards, deadCards, trials: 1000);
                for (int k = 0; k < nativeRanges.Count; k++)
                {
                    totalEquity[k] += results[k].Equity;
                }
                splitEquity += results.SplitProbability;

                // Update live results
                if (i % 10 == 0)
                {
                    int simulationCount = (i - skippedSituations + 1);
                    updateLiveResults?.Invoke(totalEquity.Select(eq => Math.Min(eq / simulationCount, 1f)), Math.Min(splitEquity / simulationCount, 1f));
                }
            }
        }