Example #1
0
    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>();
    }
Example #4
0
    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);
    }
Example #5
0
    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
        });
    }