static void doTileZeroSimulation() { string adaptID = "Game difficulty - Player skill"; string gameID = "TileZeroSimul"; string playerID = "EvolvingAI"; // [SC] do not update xml files bool updateDatafiles = false; // [SC] to randomly decide which player moves first Random rnd = new Random(); // [SC] creating a game object Game tzGame = new Game(); // [SC] disable logging to speed-up simulation Cfg.enableLog(false); double numberOfSimulations = 10; double numberOfMatches = 400; // [SC] the number of games to be played with each AI evolution int playableTileCount = 54; double minRT = 60000; double distMean = 0.75; double distSD = 0.1; double lowerLimit = 0.5; double upperLimit = 1.0; // [SC] a player is represented by an AI evolving from Very Easy AI to Very Hard AI string[] aiOneEvolution = { TileZero.Cfg.VERY_EASY_AI , TileZero.Cfg.EASY_AI , TileZero.Cfg.MEDIUM_COLOR_AI , TileZero.Cfg.MEDIUM_SHAPE_AI , TileZero.Cfg.HARD_AI , TileZero.Cfg.VERY_HARD_AI }; // [SC] start simulations for (int simIndex = 0; simIndex < numberOfSimulations; simIndex++) { TwoA twoA = new TwoA(new MyBridge()); twoA.SetTargetDistribution(distMean, distSD, lowerLimit, upperLimit); double avgAccuracy = 0; // [SC] start AI player evolution from easiest to hardest foreach (string aiOneID in aiOneEvolution) { // [SC] play a number of games before eacg evolution for (int matchIndex = 0; matchIndex < numberOfMatches; matchIndex++) { // [SC] get a recommended opponent AI from TwoA string aiTwoID = null; aiTwoID = twoA.TargetScenarioID(adaptID, gameID, playerID); Cfg.clearLog(); // [SC] start one match simualtion int startPlayerIndex = rnd.Next(2); // [SC] decide whether the player or the opponent moves first tzGame.initNewGame(aiOneID, aiTwoID, playableTileCount, startPlayerIndex); tzGame.startNewGame(); // [SC] simulate player's response time SimpleRNG.SetSeedFromRandom(); double rt = SimpleRNG.GetNormal(120000, 10000); // [SC] max is 900000 if (rt < minRT) { rt = minRT; } // [SC] obtain player's accuracy double correctAnswer = 0; if (tzGame.getPlayerByIndex(0).WinFlag) { correctAnswer = 1; } avgAccuracy += correctAnswer; printMsg("Counter: " + (matchIndex + 1) + "; Start index: " + startPlayerIndex); //printMsg(TileZero.Cfg.getLog()); // [SC] update ratings twoA.UpdateRatings(adaptID, gameID, playerID, aiTwoID, rt, correctAnswer, updateDatafiles); } } printMsg(String.Format("Accurracy for simulation {0}: {1}", simIndex, avgAccuracy / (numberOfMatches * aiOneEvolution.Length))); // [SC] creating a file with final ratings using (StreamWriter ratingfile = new StreamWriter("S4/ratingfile" + simIndex + ".txt")) { string line = "" + "\"ScenarioID\"" + "\t" + "\"Rating\"" + "\t" + "\"PlayCount\"" + "\t" + "\"Uncertainty\""; ratingfile.WriteLine(line); foreach (string scenarioID in aiOneEvolution) { line = "" + "\"" + scenarioID + "\"" + "\t" + "\"" + twoA.ScenarioRating(adaptID, gameID, scenarioID) + "\"" + "\t" + "\"" + twoA.ScenarioPlayCount(adaptID, gameID, scenarioID) + "\"" + "\t" + "\"" + twoA.ScenarioUncertainty(adaptID, gameID, scenarioID) + "\""; ratingfile.WriteLine(line); } } // [SC] creating a file with history of gameplays including player and scenario ratings using (StreamWriter datafile = new StreamWriter("S4/datafile" + simIndex + ".txt")) { GameplaysData gameplays = twoA.GameplaysData; TwoAAdaptation adaptNode = gameplays.Adaptation.First(p => p.AdaptationID.Equals(adaptID)); TwoAGame gameNode = adaptNode.Game.First(p => p.GameID.Equals(gameID)); string line = "" + "\"ID\"" + "\t" + "\"PlayerID\"" + "\t" + "\"ScenarioID\"" + "\t" + "\"Timestamp\"" + "\t" + "\"RT\"" + "\t" + "\"Accuracy\"" + "\t" + "\"PlayerRating\"" + "\t" + "\"ScenarioRating\""; datafile.WriteLine(line); int id = 1; foreach (TwoAGameplay gp in gameNode.Gameplay) { line = "" + "\"" + id++ + "\"" + "\t" + "\"" + gp.PlayerID + "\"" + "\t" + "\"" + gp.ScenarioID + "\"" + "\t" + "\"" + gp.Timestamp + "\"" + "\t" + "\"" + gp.RT + "\"" + "\t" + "\"" + gp.Accuracy + "\"" + "\t" + "\"" + gp.PlayerRating + "\"" + "\t" + "\"" + gp.ScenarioRating + "\""; datafile.WriteLine(line); } } } }