private void UpdateStatistic(StatisticInternal stat, IHand player_hand, PlayerHandResult player_hand_final_result, IHand enemy_stat_hand, PlayerHandResult player_stat_hand_result) { lock (UpdateStat_SyncRoot) { Statistic.HandStatistic hs; hs = stat.PlayerHandsStat[player_hand.Value]; switch (player_hand_final_result) { case PlayerHandResult.PlayerWin: hs.Win++; break; case PlayerHandResult.Draw: hs.Draw++; break; case PlayerHandResult.PlayerLose: hs.Lose++; break; default: throw Utility.GetUnknownEnumValueException(player_hand_final_result); } stat.PlayerHandsStat[player_hand.Value] = hs; hs = stat.EnemyHandsStat[enemy_stat_hand.Value]; switch (player_stat_hand_result) { case PlayerHandResult.PlayerWin: hs.Lose++; break; case PlayerHandResult.Draw: hs.Draw++; break; case PlayerHandResult.PlayerLose: hs.Win++; break; default: throw Utility.GetUnknownEnumValueException(player_stat_hand_result); } stat.EnemyHandsStat[enemy_stat_hand.Value] = hs; } }
private Statistic PreparePublicStatistic(StatisticInternal stat) { var public_stat = new Statistic(); public_stat.GameNumber = SimulatedGamesCount; var player_hands_stat = new List<Statistic.HandStatistic>(); for (int hand_value = 0; hand_value < stat.PlayerHandsStat.Length; hand_value++) { HandType player_hand_type; if (!HandTypeConverter.TryGetHandType(hand_value, out player_hand_type)) { continue; } player_hands_stat.Add(stat.PlayerHandsStat[hand_value]); } public_stat.PlayerHandsStat = player_hands_stat.ToArray(); public_stat.Win = public_stat.PlayerHandsStat.Sum(x => x.Win); public_stat.Draw = public_stat.PlayerHandsStat.Sum(x => x.Draw); public_stat.Lose = public_stat.PlayerHandsStat.Sum(x => x.Lose); var enemy_hands_stat = new List<Statistic.HandStatistic>(); for (int hand_value = 0; hand_value < stat.EnemyHandsStat.Length; hand_value++) { HandType enemy_hand_type; if (!HandTypeConverter.TryGetHandType(hand_value, out enemy_hand_type)) { continue; } enemy_hands_stat.Add(stat.EnemyHandsStat[hand_value]); } public_stat.EnemyHandsStat = enemy_hands_stat.ToArray(); return public_stat; }
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); }
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; }