public void FinalizeStatsWithNoWars() { var objectUnderTest = new FinalizeStats(); var dummyGameParams = new GameParameters { FirstPlayerName = "Alice", SecondPlayerName = "Bob", TotalLengthOfSimulation = TimeSpan.FromMinutes(10) }; var dummyStats = new SimulationStats { TotalSimulationTime = TimeSpan.FromMilliseconds(500), ShortestGame = TimeSpan.FromSeconds(90), Player1Wins = 50, Player2Wins = 50, WarsByDepth = new List <int>(), }; var result = objectUnderTest.GetFinalStats(dummyGameParams, dummyStats); Assert.Equal(@" Finished simulation of 00:10:00 of game play between Alice and Bob... Simulation Time: 00:00:00.5000000 Shortest Game: 00:01:30 Total Games Played: 100 Ties: 0 (0.00000 %) Alice Wins: 50 (50.00000 %) Bob Wins: 50 (50.00000 %) No wars ", result); }
private SimulationStats RunSimulation() { List <BattlegroundBoard> boards = _originalBoard.Initialize(); SimulationStats stats = new SimulationStats(0, 0, 0); foreach (BattlegroundBoard board in boards) { stats.Merge(SimulationHelper(board)); } return(stats); }
/// <summary> /// Initializes simulation variables /// </summary> private void Init() { TimeBetweenSpawns = 0.05f; TrafficJam = false; stats = GetComponent <SimulationStats>(); stats.Init(Map, Map.EdgeList.ToArray()); if (Map != null) { Nodes = Map.NodeList; } API = GetComponent <APIController>(); GetPathCount = 0; JsonPaths = new List <string>(); }
public void FinalizeStatsManyWars() { var objectUnderTest = new FinalizeStats(); var dummyGameParams = new GameParameters { FirstPlayerName = "Alice", SecondPlayerName = "Bob", TotalLengthOfSimulation = TimeSpan.FromDays(365) }; var dummyStats = new SimulationStats { TotalSimulationTime = TimeSpan.FromHours(1), ShortestGame = TimeSpan.FromSeconds(10), Ties = 1000, Player1Wins = 522425, Player2Wins = 521542, WarsByDepth = new List <int> { 0, 100, 200, 300, 400, 500, 600, 700 }, }; var result = objectUnderTest.GetFinalStats(dummyGameParams, dummyStats); Assert.Equal(@" Finished simulation of 365.00:00:00 of game play between Alice and Bob... Simulation Time: 01:00:00 Shortest Game: 00:00:10 Total Games Played: 1,044,967 Ties: 1,000 (0.09570 %) Alice Wins: 522,425 (49.99440 %) Bob Wins: 521,542 (49.90990 %) 100 single war(s) 200 double war(s) 300 triple war(s) 400 quadruple war(s) 500 quintuple war(s) 600 sextuple war(s) 700 septuple war(s) ", result); }
private IEnumerator SimulateCoroutine() { UIManager.Instance.Prompt("Simulation started"); uiTabGroup.SelectTab(simulationTabId); simulationStats = new SimulationStats(); // Describes the currently simulated in-game time (in hours, from 0.00f to 24.00f) float inGameTime = 0.0f; while (inGameTime <= 24.0f) { SiteManager.Instance.trafficManager.SimulateAtTime(inGameTime); inGameTime += Time.deltaTime * simulationTimescale / 3600.0f; simulationStats.TotalSimulationTime += Time.deltaTime; if (inGameTime >= 3.0f && inGameTime <= 9.0f) { clockDayBackground.color = new Color( clockDayBackground.color.r, clockDayBackground.color.g, clockDayBackground.color.b, (inGameTime - 3.0f) / 6.0f ); clockNightBackground.color = new Color( clockNightBackground.color.r, clockNightBackground.color.g, clockNightBackground.color.b, (9.0f - inGameTime) / 6.0f ); } else if (inGameTime >= 15.0f && inGameTime <= 21.0f) { clockDayBackground.color = new Color( clockDayBackground.color.r, clockDayBackground.color.g, clockDayBackground.color.b, (21.0f - inGameTime) / 6.0f ); clockNightBackground.color = new Color( clockNightBackground.color.r, clockNightBackground.color.g, clockNightBackground.color.b, (inGameTime - 15.0f) / 6.0f ); } clockHand.rotation = Quaternion.Euler(0.0f, 0.0f, inGameTime * -30.0f); trafficQualitySlider.value = simulationStats.TrafficQuality; yield return(null); } while (simulationStats.NumVehiclesReachedExit != simulationStats.NumVehiclesSpawned) { simulationStats.TotalSimulationTime += Time.deltaTime; trafficQualitySlider.value = simulationStats.TrafficQuality; yield return(null); } uiTabGroup.SelectTab(defaultTabId); UIManager.Instance.Prompt("Simulation ended"); OpenSimulationStats(); Dictionary <string, string> postParams = new Dictionary <string, string>(); postParams.Add(USERNAME_PARAM, SessionManager.Instance.Username); postParams.Add(SESSION_ID_PARAM, SessionManager.Instance.SessionId); postParams.Add(LEVEL_ID_PARAM, SessionManager.Instance.LevelId.ToString()); postParams.Add(SCORE_PARAM, simulationStats.Score.ToString()); StartCoroutine(Auth.AsyncPost( SessionManager.Instance.host, ATTEMPT_RANK_DIR, postParams, FetchRankCallback)); }
private SimulationStats SimulationHelper(BattlegroundBoard originalBoard) { // Base-case. Draw, win, or loss. if (originalBoard.IsDraw()) { return(new SimulationStats(0, 0, 1)); } if (originalBoard.IsWin()) { return(new SimulationStats(1, 0, 0)); } if (originalBoard.IsLoss()) { return(new SimulationStats(0, 1, 0)); } // Go through every possible iteration. List <BattlegroundCard> opponentCards = originalBoard.playerTurn ? originalBoard.opponentCards : originalBoard.playerCards; int playerIndex = originalBoard.playerTurn ? originalBoard.playerIndex : originalBoard.opponentIndex; SimulationStats simulationStats = new SimulationStats(0, 0, 0); // Look for attackable opponent cards. List <int> opponentCardIndices = new List <int>(); List <int> tauntedIndices = new List <int>(); for (int i = 0; i < opponentCards.Count; i++) { if (opponentCards[i].hasTaunt) { tauntedIndices.Add(i); } opponentCardIndices.Add(i); } if (tauntedIndices.Count > 0) { opponentCardIndices = tauntedIndices; } foreach (int index in opponentCardIndices) { BattlegroundBoard boardClone = new BattlegroundBoard(originalBoard); // Update playerCards and opponentCards with our new cloned board. List <BattlegroundCard> playerCards = boardClone.playerTurn ? boardClone.playerCards : boardClone.opponentCards; opponentCards = boardClone.playerTurn ? boardClone.opponentCards : boardClone.playerCards; BattlegroundCard playerCard = playerCards[playerIndex]; List <int> attackableOpponentIndices = new List <int>(); List <BattlegroundCard> attackableOpponentCards = new List <BattlegroundCard>(); if (playerCard.hasCleave) { if (index > 0) { attackableOpponentIndices.Add(index - 1); attackableOpponentCards.Add(opponentCards[index - 1]); } attackableOpponentIndices.Add(index); attackableOpponentCards.Add(opponentCards[index]); if (index < opponentCardIndices.Count - 1) { attackableOpponentIndices.Add(index + 1); attackableOpponentCards.Add(opponentCards[index + 1]); } } else { attackableOpponentIndices.Add(index); attackableOpponentCards.Add(opponentCards[index]); } List <Deathrattle> deathrattles = new List <Deathrattle>(); if (playerCard.hasDivineShield) { playerCard.hasDivineShield = false; } else { if (opponentCards[index].hasPoison) { playerCard.health = 0; } else { playerCard.health -= opponentCards[index].attack; } if (playerCard.health <= 0 && playerCard is DeathrattleBattlegroundCard) { // Note that the "playerCard" is actually the opponent when isPlayerTurn is false. // TODO: Rename playerCard and opponentCard in this instance. deathrattles.Add(new Deathrattle((DeathrattleBattlegroundCard)playerCard, boardClone, boardClone.playerTurn, playerIndex)); } } foreach (int opponentIndex in attackableOpponentIndices) { BattlegroundCard opponentCard = opponentCards[opponentIndex]; if (opponentCard.hasDivineShield) { opponentCard.hasDivineShield = false; } else { if (playerCard.hasPoison) { opponentCard.health = 0; } else { opponentCard.health -= playerCard.attack; } if (opponentCard.health <= 0 && opponentCard is DeathrattleBattlegroundCard) { deathrattles.Add(new Deathrattle((DeathrattleBattlegroundCard)opponentCard, boardClone, !boardClone.playerTurn, opponentIndex)); } } } if (playerCard.health <= 0) { if (boardClone.playerTurn) { boardClone.RemovePlayerCard(playerCard); } else { boardClone.RemoveOpponentCard(playerCard); } } foreach (BattlegroundCard opponentCard in attackableOpponentCards) { if (opponentCard.health <= 0) { if (boardClone.playerTurn) { boardClone.RemoveOpponentCard(opponentCard); } else { boardClone.RemovePlayerCard(opponentCard); } } } List <BattlegroundBoard> boards = new List <BattlegroundBoard>(); while (deathrattles.Count > 0) { foreach (Deathrattle deathrattle in deathrattles) { List <BattlegroundBoard> deathrattleBoards = deathrattle.ApplyDeathrattle(); if (deathrattleBoards != null) { foreach (BattlegroundBoard deathrattleBoard in deathrattleBoards) { boards.Add(deathrattleBoard); } } } deathrattles.Clear(); // Deathrattles could trigger other deathrattles (e.g. Kaboom Bot killing another card). We must now look for dead cards and reapply deathrattles. // TODO: Modulate this logic with the logic from above. List <BattlegroundBoard> boardsToRemove = new List <BattlegroundBoard>(); foreach (BattlegroundBoard board in boards) { bool triggeredDeathrattles = false; List <BattlegroundCard> playerCardsToRemove = new List <BattlegroundCard>(); List <BattlegroundCard> opponentCardsToRemove = new List <BattlegroundCard>(); DeathrattleChain deathrattleChain = new DeathrattleChain(board); for (int j = 0; j < board.playerCards.Count; j++) { if (board.playerCards[j].health <= 0) { playerCardsToRemove.Add(board.playerCards[j]); if (board.playerCards[j] is DeathrattleBattlegroundCard) { triggeredDeathrattles = true; deathrattleChain.AddDeathrattle(new Deathrattle((DeathrattleBattlegroundCard)board.playerCards[j], board, true, j)); } } } for (int j = 0; j < board.opponentCards.Count; j++) { if (board.opponentCards[j].health <= 0) { opponentCardsToRemove.Add(board.opponentCards[j]); if (board.opponentCards[j] is DeathrattleBattlegroundCard) { triggeredDeathrattles = true; deathrattleChain.AddDeathrattle(new Deathrattle((DeathrattleBattlegroundCard)board.opponentCards[j], board, false, j)); } } } foreach (BattlegroundCard card in playerCardsToRemove) { board.RemovePlayerCard(card); } foreach (BattlegroundCard card in opponentCardsToRemove) { board.RemoveOpponentCard(card); } if (triggeredDeathrattles) { deathrattles.Add(deathrattleChain); boardsToRemove.Add(board); } } // Remove any boards that are going to be handled by the newly triggered deathrattles. foreach (BattlegroundBoard board in boardsToRemove) { boards.Remove(board); } } // Continue on with the deathrattle boards, or the original boardClone if there were no deathrattles. if (boards.Count == 0) { boards.Add(boardClone); } foreach (BattlegroundBoard board in boards) { if (board.playerTurn && playerCard.health > 0) { board.playerIndex = board.playerCards.Count > 0 ? ++board.playerIndex : 0; } if (!board.playerTurn && playerCard.health > 0) { board.opponentIndex = board.opponentCards.Count > 0 ? ++board.opponentIndex : 0; } if (board.playerCards.Count > 0) { board.playerIndex %= board.playerCards.Count; } if (board.opponentCards.Count > 0) { board.opponentIndex %= board.opponentCards.Count; } board.playerTurn = !board.playerTurn; simulationStats.Merge(SimulationHelper(board)); } } return(simulationStats); }
public BattlegroundSimulation(List <Entity> playerBoard, List <Entity> opponentBoard, Dictionary <int, Entity> gameEntities) { _originalBoard = new BattlegroundBoard(CreateCards(playerBoard), CreateCards(opponentBoard)); _gameEntities = gameEntities; simulationStats = RunSimulation(); }
// Testing constructor. public BattlegroundSimulation(BattlegroundBoard board) { _originalBoard = board; simulationStats = RunSimulation(); }
public void Merge(SimulationStats sim) { totalWon += sim.totalWon; totalLost += sim.totalLost; totalDrawn += sim.totalDrawn; }
public ISimulationStats Play(GameParameters gameParams) { var overallStats = new SimulationStats(); int player1Wins = 0; int player2Wins = 0; int ties = 0; bool doneWithAllGames = false; var totalElapsedTime = new TimeSpan(); var startofSimulation = _dateTime.Now; while (!doneWithAllGames) { var game = _individualGameStateTracker.InitializeGameState(); _logger.LogDebug($"Game will last a max of {game.MaxDuration.TotalMinutes} minutes..."); if (_logger.IsEnabled(LogLevel.Trace)) { foreach (var card in game.FirstPlayerState.PlayPile.Cards) { _logger.LogTrace($"{gameParams.FirstPlayerName} has {card}"); } foreach (var card in game.SecondPlayerState.PlayPile.Cards) { _logger.LogTrace($"{gameParams.SecondPlayerName} has {card}"); } } bool doneWithIndividualGame = false; bool timeout = false; bool player1HasLost = false; bool player2HasLost = false; while (!doneWithIndividualGame) { _gamePlay.War(game); player1HasLost = _gamePlay.PlayerHasLost(game.FirstPlayerState); player2HasLost = _gamePlay.PlayerHasLost(game.SecondPlayerState); doneWithIndividualGame = player1HasLost || player2HasLost; if (player1HasLost || player2HasLost) { game.Stats.Player1WinsNinetySixToZero = player2HasLost; game.Stats.Player2WinsNinetySixToZero = player1HasLost; } else { _gamePlay.Transition(game); if (game.TimedOut) { doneWithIndividualGame = true; timeout = true; } } } totalElapsedTime += game.TimeElapsed; game.Stats.SimulationTime = game.TimeElapsed; int winner; if (player1HasLost) { winner = 2; } else if (player2HasLost) { winner = 1; } else if (timeout) { _logger.LogDebug($"Game has timed out after {game.TimeElapsed.TotalSeconds} seconds."); var player1Cards = game.FirstPlayerState.PlayPile.Cards.Concat(game.FirstPlayerState.GatherPile.Cards) .Concat(game.FirstPlayerState.PlayedCards.Cards); var player2Cards = game.SecondPlayerState.PlayPile.Cards.Concat(game.SecondPlayerState.GatherPile.Cards) .Concat(game.SecondPlayerState.PlayedCards.Cards); if (player1Cards.Count() + player2Cards.Count() != 52) { throw new Exception("Unexpected total cards after game. " + $"{gameParams.FirstPlayerName} {player1Cards.Count()}, {gameParams.SecondPlayerName} {player2Cards.Count()}."); } var player1Points = _pointsCalculator.GetPoints(player1Cards.ToList()); var player2Points = _pointsCalculator.GetPoints(player2Cards.ToList()); if (player1Points + player2Points != 96) { throw new Exception("Unexpected total points after game. " + $"{gameParams.FirstPlayerName} {player1Points}, {gameParams.SecondPlayerName} {player2Points}."); } if (player1Points > player2Points) { winner = 1; } else if (player2Points > player1Points) { winner = 2; } else { winner = 0; // tie!!! } } else { throw new Exception("Unexpected game ending...no winner and no time out!"); } game.Stats.Winner = winner; _logger.LogDebug(winner > 0 ? $"Player {winner} has won this game!" : "This game is a tie."); switch (winner) { case 2: player2Wins++; break; case 1: player1Wins++; break; default: ties++; break; } _logger.LogDebug($"{gameParams.FirstPlayerName} has {player1Wins} wins, " + $"{gameParams.SecondPlayerName} has {player2Wins} wins, {ties} ties"); _statsCompiler.UpdateStats(overallStats, game.Stats); doneWithAllGames = totalElapsedTime >= gameParams.TotalLengthOfSimulation; } var simulationTime = _dateTime.Now - startofSimulation; _logger.LogInformation($"Simulation took {simulationTime.TotalSeconds} seconds..."); overallStats.TotalSimulationTime = simulationTime; return(overallStats); }
public void UpdateStatsTest() { var objectUnderTest = new CompileStats(); var statsSoFar = new SimulationStats(); var longPlayer1WinStats = new SingleGameStats { SimulationTime = TimeSpan.FromHours(1), Winner = 1, Player1WinsNinetySixToZero = true, Player2WinsNinetySixToZero = false, Player1WarWinsByDepth = new List <int>() { 0, 10, 9, 8, 7, 6, 5, 4 }, Player2WarWinsByDepth = new List <int>() { 0, 10, 10, 10, 10, 10, 10, 10 }, }; var quickPlayer2WinsStats = new SingleGameStats { SimulationTime = TimeSpan.FromMinutes(1), Winner = 2, Player1WinsNinetySixToZero = false, Player2WinsNinetySixToZero = false, Player1WarWinsByDepth = new List <int>() { 0, 0, 0, 0, 0, 0, 0, 0 }, Player2WarWinsByDepth = new List <int>() { 0, 0, 0, 0, 0, 0, 0, 0 }, }; var tie = new SingleGameStats { SimulationTime = TimeSpan.FromMinutes(5), Winner = 0, Player1WinsNinetySixToZero = false, Player2WinsNinetySixToZero = false, Player1WarWinsByDepth = new List <int>() { 0, 3, 2, 1, 0, 0, 0, 0 }, Player2WarWinsByDepth = new List <int>() { 0, 3, 2, 1, 0, 0, 0, 0 }, }; objectUnderTest.UpdateStats(statsSoFar, longPlayer1WinStats); objectUnderTest.UpdateStats(statsSoFar, quickPlayer2WinsStats); objectUnderTest.UpdateStats(statsSoFar, tie); Assert.True(statsSoFar.Player1Wins == 1); Assert.True(statsSoFar.Player2Wins == 1); Assert.True(statsSoFar.Ties == 1); Assert.True(statsSoFar.Player1WinsNinetySixToZero == 1); Assert.True(statsSoFar.Player2WinsNinetySixToZero == 0); Assert.True(statsSoFar.ShortestGame == TimeSpan.FromMinutes(1)); Assert.True(statsSoFar.TotalWinsNinetySixToZero == 1); Assert.Equal(statsSoFar.WarsByDepth, new List <int>() { 0, 26, 23, 20, 17, 16, 15, 14 }); Assert.Equal(statsSoFar.Player1WarWinsByDepth, new List <int>() { 0, 13, 11, 9, 7, 6, 5, 4 }); Assert.Equal(statsSoFar.Player2WarWinsByDepth, new List <int>() { 0, 13, 12, 11, 10, 10, 10, 10 }); }