private async Task MCTSRoutine() { System.Action <string> print = (s) => Logger.Log(s); MOARandom r = new MOARandom(); IActor playerOne = null; IGameState game = null; switch (_testingGame) { case TestingGame.OX: playerOne = new OXActor(_startPlayerOne ? _playerTwo.Name : _playerOne.Name); game = new OXGameState(_playerOne.Name, _playerTwo.Name, playerOne as OXActor); break; case TestingGame.C4: playerOne = new C4Actor(_startPlayerOne ? _playerTwo.Name : _playerOne.Name); game = new C4GameState(_playerOne.Name, _playerTwo.Name, playerOne as C4Actor); break; case TestingGame.Pentagoesque: playerOne = new PentActor(_startPlayerOne ? _playerTwo.Name : _playerOne.Name); game = new PentGameState(_playerOne.Name, _playerTwo.Name, playerOne as PentActor); break; default: break; } _playerOne.Config = new MCTSConfig { MaxIterations = (uint)_playerOne.Iterations, Verbose = verbose, PrintFn = print, UCTK = uctExploration }; switch (_playerOne.Behaviour) { case PlayerBehaviour.MCTS: _playerOne.TreeRoot = new MCTSNode(0, null, null, game.ActorJustActed, game); break; case PlayerBehaviour.UCT: _playerOne.TreeRoot = new UCTNode(0, null, null, game.ActorJustActed, game, _playerOne.Config.UCTK); break; } _playerTwo.Config = new MCTSConfig { MaxIterations = (uint)_playerTwo.Iterations, Verbose = verbose, PrintFn = print, UCTK = uctExploration }; switch (_playerTwo.Behaviour) { case PlayerBehaviour.MCTS: _playerTwo.TreeRoot = new MCTSNode(0, null, null, game.ActorJustActed, game); break; case PlayerBehaviour.UCT: _playerTwo.TreeRoot = new UCTNode(0, null, null, game.ActorJustActed, game, _playerTwo.Config.UCTK); break; } while (!game.IsTerminal() && Application.isPlaying) { IAction action = null; Player actingPlayer = null; Player otherPlayer = null; if (game.ActorJustActed.Name == _playerOne.Name) { actingPlayer = _playerTwo; otherPlayer = _playerOne; } else { actingPlayer = _playerOne; otherPlayer = _playerTwo; } Logger.Log(GetType().Name, $"Player Acting: {actingPlayer.Name}, Behaviour: {actingPlayer.Behaviour}"); MCTSNode node = null; switch (actingPlayer.Behaviour) { case PlayerBehaviour.Random: action = game.GetRandomMove(); break; case PlayerBehaviour.MCTS: node = await MCTS.ProcessTree( actingPlayer.RetainTree?actingPlayer.TreeRoot : new MCTSNode(0, null, null, game.ActorJustActed, game), game, actingPlayer.Config ); action = node.IncomingAction; actingPlayer.TreeRoot = node.ConstructAsRoot(); break; case PlayerBehaviour.UCT: node = await MCTS.ProcessTree( actingPlayer.RetainTree?actingPlayer.TreeRoot : new UCTNode(0, null, null, game.ActorJustActed, game, actingPlayer.Config.UCTK), game, actingPlayer.Config ); action = node.IncomingAction; actingPlayer.TreeRoot = node.ConstructAsRoot(); break; default: break; } if (action != null) { game = action.DoAction(); Logger.Log(action.ASCIIRepresentation); otherPlayer.TreeRoot = otherPlayer.TreeRoot?.GetChildWithState(game)?.ConstructAsRoot(); } else { Logger.Log("STALLING!!"); break; } Logger.Log(game.ASCIIRepresentation); if (waitTime != 0f) { await Task.Delay((int)(waitTime * 1000)); } } Logger.LogFormat("{0} {1}", game.ActorJustActed.Name, game.GetResult(game.ActorJustActed)); }