public void BuildStatistic() { CardValue[] card_values = Enum.GetValues(typeof(CardValue)).OfType<CardValue>().ToArray(); Func<Card, Card, int, int, int, double> func = (Card card1, Card card2, int gameNumber, int parallelLevel, int enemyCount) => { var parameters = new CalculationParameters(); parameters.PlayerCard1 = card1; parameters.PlayerCard2 = card2; parameters.GameNumber = gameNumber; parameters.ParallelLevel = parallelLevel; parameters.EnemyPlayersCount = enemyCount; var psc = new PokerStatisticCalc(); Statistic stat = psc.RunExperiment(parameters); return Math.Round(stat.Win * 100d / stat.GameNumber, 2); }; for (int enemy = 1; enemy <= MaxEnemyCount; enemy++) { double min = int.MaxValue; double max = int.MinValue; var table = new List<KeyValuePair<CardValue, List<Tuple<CardValue, double, double>>>>(); for (int i = 0; i < card_values.Length; i++) { var line = new List<Tuple<CardValue, double, double>>(); for (int j = 0; j < card_values.Length; j++) { double d1 = func( new Card(CardSuit.Clubs, card_values[i]), new Card(CardSuit.Hearts, card_values[j]), GameCount, ParallellLevel, enemy); min = Math.Min(min, d1); max = Math.Max(max, d1); double d2 = -1; if (i != j) { d2 = func( new Card(CardSuit.Clubs, card_values[i]), new Card(CardSuit.Clubs, card_values[j]), GameCount, ParallellLevel, enemy); min = Math.Min(min, d2); max = Math.Max(max, d2); } line.Add(Tuple.Create(card_values[j], d1, d2)); } table.Add(new KeyValuePair<CardValue, List<Tuple<CardValue, double, double>>>(card_values[i], line)); } var make_rel = new Func<double, double, double, double>( (double mmin, double mmax, double val) => { double range = mmax - mmin; double d1 = (val - mmin) / range; // [0;1] return d1; //double rel = mmax / mmin; //return 1 + d1 * rel; }); var lines = new List<List<string>>(); var lines2 = new List<List<string>>(); foreach (var item in table) { var nodes = new List<string>(); var nodes2 = new List<string>(); foreach (var item2 in item.Value) { nodes.Add("{0}{1} - {2} ({3})".FormatStr( CardUtils.ConvertToString(item.Key), CardUtils.ConvertToString(item2.Item1), item2.Item2, (item2.Item3 == -1 ? "-" : item2.Item3.ToString()))); nodes2.Add("{0}{1} - {2:0.####} ({3})".FormatStr( CardUtils.ConvertToString(item.Key), CardUtils.ConvertToString(item2.Item1), make_rel(min, max, item2.Item2), (item2.Item3 == -1 ? "-" : make_rel(min, max, item2.Item3).ToString("0.####")))); } lines.Add(nodes); lines2.Add(nodes2); } int maxLength = lines.Select(x => x.Max(y => y.Length)).Max(); int maxLength2 = lines2.Select(x => x.Max(y => y.Length)).Max(); for (int i = 0; i < lines.Count; i++) { for (int j = 0; j < lines[i].Count; j++) { lines[i][j] = lines[i][j].PadRight(maxLength); lines2[i][j] = lines2[i][j].PadRight(maxLength2); } } string s = string.Join(Environment.NewLine, lines.Select(l => string.Join(" | ", l))); File.WriteAllText(FileNamePattern.FormatStr(enemy), s); string s2 = string.Join(Environment.NewLine, lines2.Select(l => string.Join(" | ", l))); File.WriteAllText(FileNamePattern2.FormatStr(enemy), s2); } }
private void SimulateGame(Card player_card1, Card player_card2, Card[] open_cards, Card[] free_cards, int enemyPlayersCount, StatisticInternal stat, CalculationParameters param) { var common_cards = new Card[5]; Array.Copy(open_cards, common_cards, open_cards.Length); var cards_shuffled = new Card[free_cards.Length]; Array.Copy(free_cards, cards_shuffled, free_cards.Length); Shuffle(cards_shuffled); int cards_shuffled_used_count = 0; if (open_cards.Length < 5) { int destinationIndex = open_cards.Length; int number_of_elements_to_copy = common_cards.Length - open_cards.Length; Array.Copy(cards_shuffled, 0, common_cards, destinationIndex, number_of_elements_to_copy); cards_shuffled_used_count = number_of_elements_to_copy; } OrderCards(common_cards); Card[] player_cards = AppendPreserveOrder(common_cards, player_card1, player_card2); bool[] player_cards_equality_by_value_helper = GetEqualityCardsByValueHelper(player_cards); IHand player_hand = GetStrongestHand(player_cards, player_cards_equality_by_value_helper, null); IHand enemy_stat_hand = null; PlayerHandResult player_stat_hand_result = PlayerHandResult.PlayerWin; PlayerHandResult player_hand_final_result = PlayerHandResult.PlayerWin; for (int enemyIndx = 0; enemyIndx < enemyPlayersCount; enemyIndx++) { Card enemy_card1 = cards_shuffled[cards_shuffled_used_count]; cards_shuffled_used_count++; Card enemy_card2 = cards_shuffled[cards_shuffled_used_count]; cards_shuffled_used_count++; Card[] enemy_cards = AppendPreserveOrder(common_cards, enemy_card1, enemy_card2); bool[] enemy_cards_equality_by_value_helper = GetEqualityCardsByValueHelper(enemy_cards); IHand enemy_hand = GetStrongestHand(enemy_cards, enemy_cards_equality_by_value_helper, (enemyIndx > 0 ? player_hand : null)); if (enemyIndx == 0) { enemy_stat_hand = enemy_hand; } PlayerHandResult player_hand_result = (enemy_hand != null) ? HandHelper.ComparePlayerHand(player_hand, enemy_hand) : PlayerHandResult.PlayerWin; switch (player_hand_result) { case PlayerHandResult.PlayerWin: // nop break; case PlayerHandResult.Draw: player_hand_final_result = PlayerHandResult.Draw; if (enemyIndx == 0) { player_stat_hand_result = PlayerHandResult.Draw; } break; case PlayerHandResult.PlayerLose: player_hand_final_result = PlayerHandResult.PlayerLose; if (enemyIndx == 0) { player_stat_hand_result = PlayerHandResult.PlayerLose; } break; default: throw Utility.GetUnknownEnumValueException(player_hand_result); } if (player_hand_final_result == PlayerHandResult.PlayerLose) { break; } } UpdateStatistic(stat, player_hand, player_hand_final_result, enemy_stat_hand, player_stat_hand_result); Interlocked.Increment(ref param.SimulatedGamesCount); }
private Card[] GetOpenCards(CalculationParameters ex_params) { var boardCards = new Card[] { ex_params.Flop1, ex_params.Flop2, ex_params.Flop3, ex_params.Turn, ex_params.River, }; return boardCards.Where(x => x != null).ToArray(); }
public Statistic RunExperiment(CalculationParameters param) { CheckParameters(param); var sw = Stopwatch.StartNew(); SimulatedGamesCount = 0; Card player_card1 = param.PlayerCard1; Card player_card2 = param.PlayerCard2; Card[] open_cards = GetOpenCards(param); ValidateInputCards(player_card1, player_card2, open_cards); Card[] cards = GetAllCards(); Card[] free_cards = GetFreeCards(cards, player_card1, player_card2, open_cards); var stat = new StatisticInternal(); stat.Init(); int parallelLevel = param.ParallelLevel; #if OneThreadForDBG parallelLevel = 1; #endif int enemyPlayersCount = param.EnemyPlayersCount; int gameNumber = param.GameNumber; var semaphore = new SemaphoreSlim(parallelLevel); var countdown = new CountdownEvent(gameNumber); for (int i = 0; i < gameNumber; i++) { param.CancelToken.ThrowIfCancellationRequested(); if (param.TimeLimit.HasValue && sw.Elapsed > param.TimeLimit.Value) { countdown.Signal(gameNumber - i); break; } semaphore.Wait(); SimulatedGamesCount++; Action action = () => { try { SimulateGame(player_card1, player_card2, open_cards, free_cards, enemyPlayersCount, stat, param); } finally { semaphore.Release(); countdown.Signal(); } }; if (parallelLevel == 1) { action(); } else { Task.Factory.StartNew(action); } } countdown.Wait(); countdown.Dispose(); semaphore.Dispose(); Statistic public_stat = PreparePublicStatistic(stat); return public_stat; }
private static void CheckParameters(CalculationParameters param) { Code.RequireNotNull(param); Code.RequireNotNull(param.PlayerCard1); Code.RequireNotNull(param.PlayerCard2); Code.Require(param.GameNumber > 0); Code.Require(param.ParallelLevel > 0); Code.Require(param.EnemyPlayersCount > 0 && param.EnemyPlayersCount <= 22); Code.Require(param.TimeLimit == null || param.TimeLimit.Value > TimeSpan.Zero); }