public OverallStatistics Run() { Parallel.For(0, _opponents.Count, new ParallelOptions { MaxDegreeOfParallelism = 8 }, i => { queueGame(i); }); /* * for (int i=0; i<_opponents.Count; i++) * queueGame(i); */ // Calculate turn averages from the totals double avgHealthDifference = _totalHealthDifference * 1.0 / _opponents.Count; double avgDamage = _totalDamage * 1.0 / _totalTurns; double avgCardsDrawn = _totalCardsDrawn * 1.0 / _totalTurns; double avgHandSize = _totalHandSize * 1.0 / _totalTurns; double avgManaSpent = _totalManaSpent * 1.0 / _totalTurns; double avgManaWasted = _totalManaWasted * 1.0 / _totalTurns; double avgStrategyAlignment = _totalStrategyAlignment * 1.0 / _totalTurns; double turnsPerGame = _totalTurns * 1.0 / _opponents.Count; // Pack up the results and give them back. var results = new OverallStatistics(); string[] cardNames = _player.Deck.GetCardNames(); results.UsageCounts = new int[cardNames.Length]; for (int i = 0; i < cardNames.Length; i++) { results.UsageCounts[i] = _usageCount[cardNames[i]]; } results.WinCount = _winCount; results.AverageHealthDifference = avgHealthDifference; results.DamageDone = avgDamage; results.NumTurns = turnsPerGame; results.CardsDrawn = avgCardsDrawn; results.HandSize = avgHandSize; results.ManaSpent = avgManaSpent; results.ManaWasted = avgManaWasted; results.StrategyAlignment = avgStrategyAlignment; return(results); }
public OverallStatistics Run() { //Parallel.For(0, _opponents.Count, i => {queueGame(i);}); for (int i = 0; i < _opponents.Count; i++) { queueGame(i); // Rest every game. Thread.Sleep(1000); } // Calculate turn averages from the totals long avgDamage = _totalDamage * 1000000L / _totalTurns; long avgCardsDrawn = _totalCardsDrawn * 1000000L / _totalTurns; long avgHandSize = _totalHandSize * 1000000L / _totalTurns; long avgManaSpent = _totalManaSpent * 1000000L / _totalTurns; long avgManaWasted = _totalManaWasted * 1000000L / _totalTurns; long avgStrategyAlignment = _totalStrategyAlignment * 100L / _totalTurns; long turnsPerGame = _totalTurns * 1000000L / _opponents.Count; // Pack up the results and give them back. var results = new OverallStatistics(); string[] cardNames = _player.Deck.GetCardNames(); results.UsageCounts = new int[cardNames.Length]; for (int i = 0; i < cardNames.Length; i++) { results.UsageCounts[i] = _usageCount[cardNames[i]]; } results.WinCount = _winCount; results.TotalHealthDifference = _totalHealthDifference; results.DamageDone = (int)avgDamage; results.NumTurns = (int)turnsPerGame; results.CardsDrawn = (int)avgCardsDrawn; results.HandSize = (int)avgHandSize; results.ManaSpent = (int)avgManaSpent; results.ManaWasted = (int)avgManaWasted; results.StrategyAlignment = (int)avgStrategyAlignment; return(results); }
static void Main(string[] args) { string nodeName = args[0]; int nodeId = Int32.Parse(args[0]); Console.WriteLine("Node Id: " + nodeId); // These files are for asyncronous communication between this // worker and it's scheduler. // // Decks to evaluate come in the inbox and are dished out of the // outbox. string boxesDirectory = "boxes/"; string inboxPath = boxesDirectory + string.Format("deck-{0,4:D4}-inbox.tml", nodeId); string outboxPath = boxesDirectory + string.Format("deck-{0,4:D4}-outbox.tml", nodeId); // Hailing string activeDirectory = "active/"; string activeWorkerPath = activeDirectory + string.Format("worker-{0,4:D4}.txt", nodeId); string activeSearchPath = activeDirectory + "search.txt"; if (!File.Exists(activeSearchPath)) { Console.WriteLine("No search has been found."); return; } // The opponent deck doesn't change so we can load it here. string[] textLines = File.ReadAllLines(activeSearchPath); Console.WriteLine("Config File: " + textLines[1]); var config = Toml.ReadFile <Configuration>(textLines[1]); // Apply nerfs if nerfs are available ApplyNerfs(config.Nerfs); // Setup the pools of card decks for possible opponents. var deckPoolManager = new DeckPoolManager(); deckPoolManager.AddDeckPools(config.Evaluation.DeckPools); // Setup test suites: (strategy, deck) combos to play against. var suiteConfig = Toml.ReadFile <DeckSuite>( config.Evaluation.OpponentDeckSuite); var gameSuite = new GameSuite(suiteConfig.Opponents, deckPoolManager); // Let the scheduler know we are here. using (FileStream ow = File.Open(activeWorkerPath, FileMode.Create, FileAccess.Write, FileShare.None)) { WriteText(ow, "Hail!"); ow.Close(); } // Loop while the guiding search is running. while (File.Exists(activeSearchPath)) { // Wait until we have some work. while (!File.Exists(inboxPath) && File.Exists(activeSearchPath)) { Console.WriteLine("Waiting... (" + nodeId + ")"); Thread.Sleep(5000); } if (!File.Exists(activeSearchPath)) { break; } // Wait for the file to be finish being written Thread.Sleep(5000); // Run games, evaluate the deck, and then save the results. var playMessage = Toml.ReadFile <PlayMatchesMessage>(inboxPath); Deck playerDeck = playMessage.Deck.ContructDeck(); int numStrats = config.Evaluation.PlayerStrategies.Length; var stratStats = new StrategyStatistics[numStrats]; var overallStats = new OverallStatistics(); overallStats.UsageCounts = new int[playerDeck.CardList.Count]; RecordDeckProperties(playerDeck, overallStats); for (int i = 0; i < numStrats; i++) { // Setup the player with the current strategy PlayerStrategyParams curStrat = config.Evaluation.PlayerStrategies[i]; var player = new PlayerSetup(playerDeck, PlayerSetup.GetStrategy(curStrat.Strategy, config.Network, playMessage.Strategy)); List <PlayerSetup> opponents = gameSuite.GetOpponents(curStrat.NumGames); var launcher = new GameDispatcher( player, opponents ); // Run the game and collect statistics OverallStatistics stats = launcher.Run(); stratStats[i] = new StrategyStatistics(); stratStats[i].WinCount += stats.WinCount; stratStats[i].Alignment += stats.StrategyAlignment; overallStats.Accumulate(stats); } // Write the results overallStats.ScaleByNumStrategies(numStrats); var results = new ResultsMessage(); results.PlayerDeck = playMessage.Deck; results.OverallStats = overallStats; results.StrategyStats = stratStats; Toml.WriteFile <ResultsMessage>(results, outboxPath); // Wait for the TOML file to write (buffers are out of sync) // Then tell the search that we are done writing the file. Thread.Sleep(3000); File.Delete(inboxPath); // Cleanup. GC.Collect(); // Look at all the files in the current directory. // Eliminate anythings that matches our log file. /* * string[] oFiles = Directory.GetFiles(".", "DeckEvaluator.o*"); * foreach (string curFile in oFiles) * { * if (curFile.EndsWith(nodeName)) * { * File.Delete(curFile); * } * }*/ } }
private static void RecordDeckProperties(Deck deck, OverallStatistics stats) { // Calculate the dust cost of the deck int dust = 0; foreach (Card c in deck.CardList) { if (c.Rarity == Rarity.COMMON) { dust += 40; } else if (c.Rarity == Rarity.RARE) { dust += 100; } else if (c.Rarity == Rarity.EPIC) { dust += 400; } else if (c.Rarity == Rarity.LEGENDARY) { dust += 1600; } } // Calculate the sum of mana costs int deckManaSum = 0; foreach (Card c in deck.CardList) { deckManaSum += c.Cost; } // Calculate the variance of mana costs double avgDeckMana = deckManaSum * 1.0 / deck.CardList.Count; double runningVariance = 0; foreach (Card c in deck.CardList) { double diff = c.Cost - avgDeckMana; runningVariance += diff * diff; } double deckManaVariance = runningVariance / deck.CardList.Count; // Calculate the number of minion and spell cards int numMinionCards = 0; int numSpellCards = 0; foreach (Card c in deck.CardList) { if (c.Type == CardType.MINION) { numMinionCards++; } else if (c.Type == CardType.SPELL) { numSpellCards++; } } // Record the properties stats.Dust = dust; stats.DeckManaSum = deckManaSum; stats.DeckManaVariance = deckManaVariance; stats.NumMinionCards = numMinionCards; stats.NumSpellCards = numSpellCards; }