public void TestMCTS() { var empty = new[] { Played.Empty, Played.Empty, Played.Empty, Played.Empty, Played.Empty, Played.Empty, Played.Empty, Played.Empty, Played.Empty, }; var board = new[] { empty, empty, empty, empty, empty, empty, empty, empty, empty, }; var gameState = new GameState(null, Player.Self, board, null !, empty); MCTS.BestMove(gameState, 1000); Console.WriteLine("Finished"); Console.WriteLine($"Heuristic Time {Monitoring.HeuristicTime}"); Console.WriteLine($"Generation time {Monitoring.ChildrenGenerationTime}"); Console.WriteLine($"Allocation time {Monitoring.AllocationTime}"); Console.WriteLine($"Children {Monitoring.Children}"); Console.WriteLine($"ComputeBoardResultTime {Monitoring.ComputeBoardResultTime}"); Console.WriteLine($"RollOutTime {Monitoring.RollOutTime}"); Console.WriteLine($"SetResult Time {Monitoring.SetResultTime}"); }
public static Lazy <string> DumpDebugInfo(this MCTS <GameNode> root, int depth = 2, int indent = 0, StringBuilder result = null) { if (depth < 0) { return(new Lazy <string>(() => "")); } if (result == null) { result = new StringBuilder(); } string currentIndentStr; StringBuilder currentIndentBuilder = new StringBuilder(); for (int i = 0; i < indent; ++i) { currentIndentBuilder.Append(indentStr); } currentIndentStr = currentIndentBuilder.ToString(); result.AppendFormat("{0}move: {1}; id: {2}\n", currentIndentStr, root.Node.ParentsMove, root.ToString()); result.AppendFormat("{0}{1}score: {2}\n", currentIndentStr, indentStr, root.Node.Value); result.AppendFormat("{0}{1}expected_score: {2}\n", currentIndentStr, indentStr, root.WinRate); foreach (var child in root.Children) { child.DumpDebugInfo(depth - 1, indent + 1, result); } return(new Lazy <string>(result.ToString)); }
/// <summary> /// 电脑落子 /// </summary> void computerPlacePiece() { MCTS mcts = new MCTS(gameState, N_SIMULATION_TIMES); GobangMove nextMove; MCTSGameMove MCTSMove = mcts.decideMove(); if (MCTSMove is GobangMove) { nextMove = (GobangMove) MCTSMove; GobangPoint point = nextMove.point; if (gameState.boardState[point.coord[0], point.coord[1]].pieceType != PieceType.Unplaced) Debug.LogWarning("Selected a point already had a piece."); point.pieceType = PieceType.Computer; gameState.placePiece(new GobangMove(point)); paintCube(point.coord, computerColor); GameResult result = gameState.judgeLastMove(); if (result != GameResult.NoOutcome) { gameRunning = false; reminder.GetComponent<CanvasGroup>().alpha = 1; if (result == GameResult.ComputerWon) showReminder("胜败乃兵家常事\n大侠请重新来过"); else if (result == GameResult.Draw) showReminder("平局"); } if (gameRunning) hideReminder(); playersTurn = true; } else { Debug.LogError("Cannot convert variable nextMove to type GobangMove."); } }
static void SearchBias(int visits, int _2048Visits, int k = 10) { double c = Math.Pow(2, k); var _lock = new Object(); MCTS <RangeNode> root = null; root = new MCTS <RangeNode>( new RangeNode( -0.75, 0.25, (x) => { var biasExponent = Math.Pow(2, x * c); var _2048Root = new MCTS <GameNode>( new GameNode( new _2048Model() ), biasExponent ); while (_2048Root.TryMove(_2048Visits, out _2048Root)) { ; } lock (_lock) { Console.WriteLine(string.Format("biasExponent: {0}", biasExponent)); Console.WriteLine(string.Format("score: {0}", _2048Root.Node.Game.Score)); Console.Write(((_2048Model)_2048Root.Node.Game).Matrix.ToDebugString(5)); Console.WriteLine(string.Format("best biasExponent: {0} score: {1}", Math.Pow(2, c * root.GetBestLeaf().Node.Middle), root.GetBestLeaf().WinRate)); } return(_2048Root.Node.Game.Score); } ) ); root.Execute(visits); var bestBiasExponent = Math.Pow(2, c * root.GetBestLeaf().Node.Middle); var statistics = new Statistics.Statistics(); Parallel.For(0, visits / 4, () => new Statistics.Statistics(), (i, loop, _statistics) => { var _2048Root2 = new MCTS <GameNode>( new GameNode( new _2048Model() ), bestBiasExponent ); while (_2048Root2.TryMove(_2048Visits, out _2048Root2)) { ; } _statistics.Add(_2048Root2.Node.Game.Score); Console.WriteLine(string.Format("best biasExponent: {0} score: {1} (s: {2}, c: {3})", bestBiasExponent, _statistics.Mean, _statistics.SampleStandardDeviation, _statistics.Count)); return(_statistics); }, (_statistics) => statistics.Add(_statistics) ); Console.WriteLine(string.Format("best biasExponent: {0} score: {1} (s: {2}, c: {3})", bestBiasExponent, statistics.Mean, statistics.SampleStandardDeviation, statistics.Count)); }
public void Reset(BoardState board) { _Board = board; if (null == _MCTS) { _MCTS = new MCTS(); } _MCTS.ClearState(); }
public static MCTS <GameNode> GetChildByMove(this MCTS <GameNode> root, int move) { foreach (var child in root.Children) { if (child.Node.ParentsMove == move) { return(child); } } throw new ArgumentOutOfRangeException("move"); }
public void Start() { if (KeepType.Instance.Difficulty == "hard") { agent = new MCTS(pokemonRenderer); } else { agent = new Randomer(pokemonRenderer); } }
public override ISearchStrategy <object, TicTacToeState, TicTacToeMove, object, TicTacToeMove> SetupMCTS() { var builder = MCTS <object, TicTacToeState, TicTacToeMove, object, TicTacToeMove> .Builder(); builder.Iterations = 10000; builder.PlayoutStrategy = new AgentPlayout <object, TicTacToeState, TicTacToeMove, object, TicTacToeMove>(Agent); builder.EvaluationStrategy = EvaluationStrategy; builder.SolutionStrategy = new ActionSolution <object, TicTacToeState, TicTacToeMove, object, TicTacToeMove, TreeSearchNode <TicTacToeState, TicTacToeMove> >(); return(builder.Build()); }
static void _2048MCTS(int iterations, int log_modulus) { /* biasExponent by iterations * 20: 0.00237352999996185 * 20: 0.0043530732132652 * 20: 0.00479875209416746 * 20: best biasExponent: 0,013431258317143700 score: 14271,36 (s: 6940,72141844670, c: 100) * 20: best biasExponent: 0,002995863277033120 score: 14088,64 (s: 6820,91629781646, c: 100) * 20: best biasExponent: 0,003611261854512600 score: 13818,04 (s: 6830,36352304690, c: 100) * 20: best biasExponent: 0,002896164722634640 score: 13349,96 (s: 6127,00251646494, c: 100) * 20: best biasExponent: 0,001130312571907960 score: 13334,64 (s: 6070,33165938645, c: 100) * 20: best biasExponent: 0,002050672042579470 score: 13282,40 (s: 6245,27094138542, c: 100) * 20: best biasExponent: 0,002939616663326970 score: 13002,68 (s: 6500,03447524657, c: 100) * 20: best biasExponent: 0,005991726554066230 score: 12908,00 (s: 6655,55313670889, c: 100) * 20: best biasExponent: 0,000736896693160851 score: 12572,24 (s: 6198,14900541551, c: 100) * 20: best biasExponent: 0,020762964440718000 score: 12466,36 (s: 5385,50701873917, c: 100) * 20: best biasExponent: 0,001100118768172110 score: 12359,12 (s: 5827,95236019713, c: 100) * 20: best biasExponent: 0,000577531597160323 score: 12226,44 (s: 5456,60602383881, c: 100) * 20: best biasExponent: 0,004236790477395740 score: 12215,36 (s: 7427,48165312273, c: 100) * 20: best biasExponent: 0,008081440143545950 score: 11983,68 (s: 6323,34747507244, c: 100) * 20: best biasExponent: 0,000582241886026929 score: 11665,56 (s: 6392,44493198689, c: 100) */ var root = new MCTS <GameNode>(new GameNode(new _2048Model()), 200); MCTS <GameNode> oldRoot = root; int counter = -1; var stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); while (!root.Complete) { if (++counter % log_modulus == 0) { Console.WriteLine(stopWatch.Elapsed); stopWatch.Restart(); Console.WriteLine(string.Format("move: {0}", counter)); Console.WriteLine(string.Format("score: {0}", root.Node.Game.Score)); Console.WriteLine(string.Format("missing visits: {0}", iterations - root.Visits)); Console.Write(((_2048Model)root.Node.Game).Matrix.ToDebugString(5)); //Console.Write(oldRoot.DumpDebugInfo(1).Value); } oldRoot = root; if (!root.TryMove(iterations, out root) && !root.Complete) { throw new InvalidOperationException("not moved."); } //Console.ReadLine(); } var a = "ahoj"; Console.WriteLine(string.Format("move: {0}", counter)); Console.WriteLine(string.Format("score: {0}", root.Node.Game.Score)); Console.Write(((_2048Model)root.Node.Game).Matrix.ToDebugString(5)); }
public static MCTS <T> GetBestLeaf <T>(this MCTS <T> root) where T : INode <double, T> { while (1 < root.Visits && 0 < root.Children.Count) { root = root.Children.Max( (x, y) => { return(x.Node.Value.CompareTo(y.Node.Value)); } ); } return(root); }
public static bool TryAutoMove(this MCTS <GameNode> root, out MCTS <GameNode> newRoot) { if (root.Node.Game.IsAutoMovePossible) { int move = root.Node.Game.GetAutoMoveIndex(); newRoot = root.GetChildByMove(move); return(true); } else { newRoot = root; return(false); } }
public static int GetBestMove(this MCTS <GameNode> root) { int maxVisits = int.MinValue; int bestMove = -1; foreach (var child in root.Children) { if (maxVisits < child.Visits) { maxVisits = child.Visits; bestMove = child.Node.ParentsMove; } } return(bestMove); }
IEnumerator MCTSAIInput() { thinking = true; MCTS search = new MCTS(board.boardState, targetTurnState); for (int i = 0; i < budget; i++) { for (int q = 0; q < 10; q++) { for (int j = 0; j < 10; j++) { search.Iterate(); } yield return(null); } } MCTS.Move bestMove = search.GetBestMove(); while (board.selectedTurn != bestMove.MoveIndex) { if (team == Team.Blue) { board.MoveLeft(); } else { board.MoveRight(); } yield return(new WaitForSeconds(0.1f)); } if (bestMove.Up) { board.MoveUp(); } else { board.MoveDown(); } thinking = false; }
static GameState RunSimulation(GameState state = null, bool isDeterministic = false) { var root = state ?? GetStartState(isDeterministic); var mcts = new MCTS(); for (int iteration = 0; iteration < 100000; iteration++) { var leaf = mcts.Select(root); if (leaf.IsSampled) { mcts.Expand(leaf); } mcts.Simulate(leaf); mcts.Propagate(leaf); } return(root); }
IEnumerator StartGame(GameController gc) { if (testDelay == 0) { yield return(1); } else { yield return(new WaitForSeconds(testDelay)); } mcts = new MCTS(); mcts.budget = budget; mcts.totalSimulation = totalSimulation; isMoveComputed = false; mcts.C = C; MCTS.TreeSize = 0; MCTS.TreeSize = 0; thread = new Thread(() => mcts.UCTSearch(mode, this.MyTurnID, gc.grid.grid, gc.availableTiles, gc.player_tiles[gc.currentTurn], gc.player_tiles[1 - gc.currentTurn], callback)); thread.Start(); }
public static bool TryMove(this MCTS <GameNode> root, int iterations, out MCTS <GameNode> newRoot, bool preferAutoMove = true) { if (preferAutoMove && root.TryAutoMove(out newRoot)) { return(true); } else { root.Execute(iterations); if (root.GetBestMove() < 0) { newRoot = root; return(false); } else { newRoot = root.GetChildByMove(root.GetBestMove()); return(true); } } }
public void MCTSBisect() { var expectedValue = 1.0; var floor = 0.0; var ceil = 10.0; var biasExponent = 0; var biasCoeff = 0; for (var iterations = 1; iterations < 200; iterations++) { var bisect = new RangeNode(floor, ceil, (x) => ceil - floor - Math.Abs(x - expectedValue)); MCTS <RangeNode> .SetRandomSeed(0); var root = MCTS.Create(bisect, biasCoeff, 1, biasExponent); root.Execute(iterations, parallel: false); Assert.AreEqual(iterations, root.Visits); var actualValue = root.GetBestLeaf().Node.Middle; var epsilon = Math.Max(Math.Pow(2, -iterations / 2.0 + 2), EDouble.RELATIVE_EPSILON); var actualEpsilon = GetEpsilon(actualValue, expectedValue); var epsilonDiff = epsilon / actualEpsilon; Assert.IsTrue(actualValue.NearlyEquals(expectedValue, epsilon)); } }
/// <summary> /// Constructs a new instance of MCTSBot with default strategies. /// </summary> /// <param name="allowPerfectInformation">[Optional] Whether or not this bot is allowed perfect information about the game state (i.e. no obfuscation and therefore no determinisation). Default value is false.</param> /// <param name="ensembleSize">[Optional] The size of the ensemble to use. Default value is 1.</param> /// <param name="playoutBotType">[Optional] The type of playout bot to be used during playouts. Default value is <see cref="PlayoutBotType.MAST"/>.</param> /// <param name="mastSelectionType">[Optional] The type of selection strategy used by the MAST playout. Default value is <see cref="MASTPlayoutBot.SelectionType.EGreedy"/>.</param> /// <param name="retainTaskStatistics">[Optional] Whether or not to retain the PlayerTask statistics between searches. Default value is false.</param> /// <param name="budgetType">[Optional] The type of budget that this bot will use. Default value is <see cref="BudgetType.Iterations"/>.</param> /// <param name="iterations">[Optional] The budget for the amount of iterations MCTS can use. Default value is <see cref="Constants.DEFAULT_COMPUTATION_ITERATION_BUDGET"/>.</param> /// <param name="time">[Optional] The budget for the amount of milliseconds MCTS can spend on searching. Default value is <see cref="Constants.DEFAULT_COMPUTATION_TIME_BUDGET"/>.</param> /// <param name="minimumVisitThresholdForExpansion">[Optional] The minimum amount of times a node has to be visited before it can be expanded. Default value is <see cref="Constants.DEFAULT_MCTS_MINIMUM_VISIT_THRESHOLD_FOR_EXPANSION"/>.</param> /// <param name="minimumVisitThresholdForSelection">[Optional] The minimum number of visits before using the NodeEvaluation to select the best node. Default value is <see cref="Constants.DEFAULT_MCTS_MINIMUM_VISIT_THRESHOLD_FOR_SELECTION"/>.</param> /// <param name="playoutTurnCutoff">[Optional] The amount of turns after which to stop a simulation. Default value is <see cref="Constants.DEFAULT_PLAYOUT_TURN_CUTOFF"/>.</param> /// <param name="ucbConstantC">[Optional] Value for the c-constant in the UCB1 formula. Default value is <see cref="Constants.DEFAULT_UCB1_C"/>.</param> /// <param name="dimensionalOrdering">[Optional] The ordering for dimensions when using Hierarchical Expansion. Default value is <see cref="DimensionalOrderingType.None"/>.</param> /// <param name="useHeuristicEvaluation">[Optional] Whether or not to use the HeuristicBot's evaluation function. Default value is false.</param> /// <param name="debugInfoToConsole">[Optional] Whether or not to write debug information to the console. Default value is false.</param> public HMCTSBot(bool allowPerfectInformation = false, int ensembleSize = 1, PlayoutBotType playoutBotType = PlayoutBotType.MAST, MASTPlayoutBot.SelectionType mastSelectionType = MASTPlayoutBot.SelectionType.EGreedy, bool retainTaskStatistics = false, BudgetType budgetType = BudgetType.Iterations, int iterations = Constants.DEFAULT_COMPUTATION_ITERATION_BUDGET, long time = Constants.DEFAULT_COMPUTATION_TIME_BUDGET, int minimumVisitThresholdForExpansion = Constants.DEFAULT_MCTS_MINIMUM_VISIT_THRESHOLD_FOR_EXPANSION, int minimumVisitThresholdForSelection = Constants.DEFAULT_MCTS_MINIMUM_VISIT_THRESHOLD_FOR_SELECTION, int playoutTurnCutoff = Constants.DEFAULT_PLAYOUT_TURN_CUTOFF, double ucbConstantC = Constants.DEFAULT_UCB1_C, DimensionalOrderingType dimensionalOrdering = DimensionalOrderingType.None, bool useHeuristicEvaluation = false, bool debugInfoToConsole = false) { PerfectInformation = allowPerfectInformation; EnsembleSize = ensembleSize; PlayoutBotType = playoutBotType; MASTSelectionType = mastSelectionType; RetainTaskStatistics = retainTaskStatistics; BudgetType = budgetType; Iterations = iterations; Time = time; MinimumVisitThresholdForExpansion = minimumVisitThresholdForExpansion; MinimumVisitThresholdForSelection = minimumVisitThresholdForSelection; PlayoutTurnCutoff = playoutTurnCutoff; UCBConstantC = ucbConstantC; DimensionalOrdering = dimensionalOrdering; _debug = debugInfoToConsole; // Create the ensemble search Ensemble = new EnsembleStrategySabberStone(enableStateObfuscation: true, enablePerfectInformation: PerfectInformation); // Simulation will be handled by the Playout. var sabberStoneStateEvaluation = new EvaluationStrategyHearthStone(useHeuristicEvaluation); Playout = new PlayoutStrategySabberStone(); // Set the playout bots switch (PlayoutBotType) { case PlayoutBotType.Random: MyPlayoutBot = new RandomBot(filterDuplicatePositionTasks: true); OpponentPlayoutBot = new RandomBot(filterDuplicatePositionTasks: true); break; case PlayoutBotType.Heuristic: MyPlayoutBot = new HeuristicBot(); OpponentPlayoutBot = new HeuristicBot(); break; case PlayoutBotType.MAST: MyPlayoutBot = new MASTPlayoutBot(MASTSelectionType, sabberStoneStateEvaluation); OpponentPlayoutBot = new MASTPlayoutBot(MASTSelectionType, sabberStoneStateEvaluation); break; default: throw new InvalidEnumArgumentException($"PlayoutBotType `{PlayoutBotType}' is not supported."); } // We'll be cutting off the simulations after X turns, using a GoalStrategy. Goal = new GoalStrategyTurnCutoff(PlayoutTurnCutoff); // Expansion, Application and Goal will be handled by the GameLogic. GameLogic = new SabberStoneGameLogic(Goal, true, DimensionalOrdering); // Create the INodeEvaluation strategy used in the selection phase. var nodeEvaluation = new ScoreUCB <SabberStoneState, SabberStoneAction>(UCBConstantC); // Build MCTS Builder = MCTS <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction> .Builder(); Builder.ExpansionStrategy = new MinimumTExpansion <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction>(MinimumVisitThresholdForExpansion); Builder.SelectionStrategy = new BestNodeSelection <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction>(MinimumVisitThresholdForSelection, nodeEvaluation); Builder.EvaluationStrategy = sabberStoneStateEvaluation; switch (BudgetType) { case BudgetType.Iterations: Builder.Iterations = EnsembleSize > 0 ? Iterations / EnsembleSize : Iterations; // Note: Integer division by design. break; case BudgetType.Time: Builder.Time = EnsembleSize > 0 ? Time / EnsembleSize : Time; // Note: Integer division by design. break; default: throw new InvalidEnumArgumentException($"BudgetType `{BudgetType}' is not supported."); } Builder.BackPropagationStrategy = new EvaluateOnceAndColourBackPropagation <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction>(); Builder.FinalNodeSelectionStrategy = new BestRatioFinalNodeSelection <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction>(); Builder.SolutionStrategy = new SolutionStrategySabberStone(true, nodeEvaluation); Builder.PlayoutStrategy = Playout; }
void Start() { gameBoard = GameObject.Find("Scripts").GetComponent <Board> (); gameUI = GameObject.Find("Scripts").GetComponent <GUI> (); gameMTCS = GameObject.Find("Scripts").GetComponent <MCTS> (); }
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)); }
public void MCTSSearchTest() { MCTS.Search(10, tree); BinarySerializer.SerializeObject <GameTree>(Parser.GetTopDirectory() + @"GameTrees\Data\Unit-Tests\gametree", tree); Assert.AreEqual(tree.Root.Unplayed.Count, 0); }
void Update() { if (Time.time > this.nextUpdateTime || this.GameManager.WorldChanged) { this.MCTS = new MCTSBiasedPlayout(new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals)); //this.MCTS = new MCTS(new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals)); this.GameManager.WorldChanged = false; this.nextUpdateTime = Time.time + DECISION_MAKING_INTERVAL; //first step, perceptions //update the agent's goals based on the state of the world this.SurviveGoal.InsistenceValue = this.GameManager.characterData.MaxHP - this.GameManager.characterData.HP; this.BeQuickGoal.InsistenceValue += DECISION_MAKING_INTERVAL * 0.1f; if (this.BeQuickGoal.InsistenceValue > 10.0f) { this.BeQuickGoal.InsistenceValue = 10.0f; } this.GainXPGoal.InsistenceValue += 0.1f; //increase in goal over time if (this.GameManager.characterData.XP > this.previousXP) { this.GainXPGoal.InsistenceValue -= this.GameManager.characterData.XP - this.previousXP; this.previousXP = this.GameManager.characterData.XP; } this.GetRichGoal.InsistenceValue += 0.1f; //increase in goal over time if (this.GetRichGoal.InsistenceValue > 10) { this.GetRichGoal.InsistenceValue = 10.0f; } if (this.GameManager.characterData.Money > this.previousGold) { this.GetRichGoal.InsistenceValue -= this.GameManager.characterData.Money - this.previousGold; this.previousGold = this.GameManager.characterData.Money; } this.SurviveGoalText.text = "Survive: " + this.SurviveGoal.InsistenceValue; this.GainXPGoalText.text = "Gain XP: " + this.GainXPGoal.InsistenceValue.ToString("F1"); this.BeQuickGoalText.text = "Be Quick: " + this.BeQuickGoal.InsistenceValue.ToString("F1"); this.GetRichGoalText.text = "GetRich: " + this.GetRichGoal.InsistenceValue.ToString("F1"); //initialize Decision Making Proccess this.CurrentAction = null; this.GOAPDecisionMaking.InitializeDecisionMakingProcess(); this.MCTS.InitializeMCTSearch(); } if (MCTSActive) { if (this.CurrentAction == null) { this.UpdateMCTS(); } } else { this.UpdateDLGOAP(); } if (this.CurrentAction != null) { if (this.CurrentAction.CanExecute()) { this.CurrentAction.Execute(); } } //call the pathfinding method if the user specified a new goal if (this.AStarPathFinding.InProgress) { var finished = this.AStarPathFinding.Search(out this.currentSolution); if (finished && this.currentSolution != null) { //lets smooth out the Path this.startPosition = this.Character.KinematicData.position; this.currentSmoothedSolution = StraightLinePathSmoothing.SmoothPath(this.Character.KinematicData.position, this.currentSolution); this.currentSmoothedSolution.CalculateLocalPathsFromPathPositions(this.Character.KinematicData.position); this.Character.Movement = new DynamicFollowPath(this.Character.KinematicData, this.currentSmoothedSolution) { MaxAcceleration = 200.0f, MaxSpeed = 50.0f }; } } this.Character.Update(); //manage the character's animation if (this.Character.KinematicData.velocity.sqrMagnitude > 0.1) { this.characterAnimator.SetBool("Walking", true); } else { this.characterAnimator.SetBool("Walking", false); } }
public void Start() { this.draw = true; this.navMesh = NavigationManager.Instance.NavMeshGraphs[0]; this.Character = new DynamicCharacter(this.gameObject); //initialize your pathfinding algorithm here! this.Initialize(NavigationManager.Instance.NavMeshGraphs[0], new NodeArrayAStarPathFinding(NavigationManager.Instance.NavMeshGraphs[0], new EuclideanDistanceHeuristic())); //initialization of the GOB decision making //let's start by creating 4 main goals this.SurviveGoal = new Goal(SURVIVE_GOAL, 2.0f); this.GainLevelGoal = new Goal(GAIN_LEVEL_GOAL, 2.0f) { ChangeRate = 0.2f }; this.GetRichGoal = new Goal(GET_RICH_GOAL, 1.0f) { InsistenceValue = 4.0f, ChangeRate = 0.2f }; this.BeQuickGoal = new Goal(BE_QUICK_GOAL, 1.0f) { ChangeRate = 0.1f }; this.Goals = new List <Goal>(); this.Goals.Add(this.SurviveGoal); this.Goals.Add(this.BeQuickGoal); this.Goals.Add(this.GetRichGoal); this.Goals.Add(this.GainLevelGoal); //initialize the available actions //Uncomment commented actions after you implement them this.Actions = new List <Action>(); this.Actions.Add(new ShieldOfFaith(this)); foreach (var chest in GameObject.FindGameObjectsWithTag("Chest")) { this.Actions.Add(new PickUpChest(this, chest)); } foreach (var potion in GameObject.FindGameObjectsWithTag("ManaPotion")) { this.Actions.Add(new GetManaPotion(this, potion)); } foreach (var potion in GameObject.FindGameObjectsWithTag("HealthPotion")) { this.Actions.Add(new GetHealthPotion(this, potion)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Skeleton")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new DivineSmite(this, enemy)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Orc")) { this.Actions.Add(new SwordAttack(this, enemy)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Dragon")) { this.Actions.Add(new SwordAttack(this, enemy)); } var worldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); this.GOAPDecisionMaking = new DepthLimitedGOAPDecisionMaking(worldModel, this.Actions, this.Goals); this.MCTS = new MCTS(worldModel); this.DiaryText.text = "My Diary \n I awoke. What a wonderful day to kill Monsters!\n"; }
public override PlayerTask GetMove(POGame poGame) { if (poGame.Turn != lastTurnCounter) { //Console.WriteLine("New turn " + poGame.Turn + "\n"); actionsToDo.Clear(); lastTurnCounter = poGame.Turn; mcts = new MCTS(poGame); actionsToDo = mcts.run(); } var player = poGame.CurrentPlayer; /* * Console.WriteLine("------------------------------------" + "\nCards on hand:\n" + String.Join(";\n", player.HandZone)); * Console.WriteLine("\nCurrent Turn and Mana:\n" + poGame.Turn + ";\n" + player.RemainingMana); * Console.WriteLine("\nCurrent Health and Enemy Health:\n" + player.Hero.Health + ";\n" + player.Opponent.Hero.Health); * * Console.WriteLine("\nCards on enemy field:\n" + String.Join(";\n", player.Opponent.BoardZone)); * if (player.Opponent.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health) > 0) * Console.WriteLine("Total taunt on enemy side:\n" + player.Opponent.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health)); * * Console.WriteLine("\nCards on own field:\n" + String.Join(";\n", player.BoardZone)); * if (player.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health) > 0) * Console.WriteLine("Total taunt on own side:\n" + player.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health)); */ if (actionsToDo.Any()) { PlayerTask task = actionsToDo[0]; actionsToDo.RemoveAt(0); return(task); } else { return(poGame.CurrentPlayer.Options().First(x => x.PlayerTaskType == PlayerTaskType.END_TURN)); } /* * * Root = new Node(); * * var player = poGame.CurrentPlayer; * * // simple Mulligan Rule * if (player.MulliganState == Mulligan.INPUT) * { * List<int> mulligan = new MidRangeScore().MulliganRule().Invoke(player.Choice.Choices.Select(p => poGame.getGame().IdEntityDic[p]).ToList()); * return ChooseTask.Mulligan(player, mulligan); * } * * // Get all valid options for this turn * var validOpts = poGame.Simulate(player.Options()).Where(x => x.Value != null); * validOpts.OrderBy(x => new MidRangeScore { Controller = player }.Rate()); * * // Build initial tree * foreach (KeyValuePair<PlayerTask, POGame> actionState in validOpts) * { * var appnode = new Node(); * appnode.state = actionState.Value; * appnode.nodeAction = actionState.Key; * appnode.Q = new MidRangeScore { Controller = player }.Rate(); //might be wrong * Root.childNodes.Append<Node>(appnode); * } * * // Stats output * List<PlayerTask> options = new List<PlayerTask>(); * if (validOpts.Any()) * { * Console.WriteLine("------------------------------------" + "\nCards on hand:\n" + String.Join(";\n", player.HandZone)); * Console.WriteLine("\nCurrent Turn and Mana:\n" + poGame.Turn + ";\n" + player.RemainingMana); * Console.WriteLine("\nCurrent Health and Enemy Health:\n" + player.Hero.Health + ";\n" + player.Opponent.Hero.Health); * * Console.WriteLine("\nCards on enemy field:\n" + String.Join(";\n", player.Opponent.BoardZone)); * if (player.Opponent.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health) > 0) * Console.WriteLine("Total taunt on enemy side:\n" + player.Opponent.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health)); * * Console.WriteLine("\nCards on own field:\n" + String.Join(";\n", player.BoardZone)); * if (player.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health) > 0) * Console.WriteLine("Total taunt on own side:\n" + player.BoardZone.Where(p => p.HasTaunt).Sum(p => p.Health)); * * options = poGame.CurrentPlayer.Options(); * * } * return options[Rnd.Next(options.Count)]; */ }
public MCTSPlayer(double utcC, int responseTimeInMilliseconds) { _mcts = new MCTS(utcC); ResponseTimeInMilliseconds = responseTimeInMilliseconds; }
public void Start() { this.draw = true; this.navMesh = NavigationManager.Instance.NavMeshGraphs[0]; this.Character = new DynamicCharacter(this.gameObject); var clusterGraph = Resources.Load <ClusterGraph>("ClusterGraph"); this.Initialize(NavigationManager.Instance.NavMeshGraphs[0], new NodeArrayAStarPathFinding(NavigationManager.Instance.NavMeshGraphs[0], new GatewayHeuristic(clusterGraph))); //initialization of the GOB decision making //let's start by creating 4 main goals this.SurviveGoal = new Goal(SURVIVE_GOAL, 2.0f); this.GainXPGoal = new Goal(GAIN_XP_GOAL, 1.0f) { ChangeRate = 0.1f }; this.GetRichGoal = new Goal(GET_RICH_GOAL, 1.0f) { InsistenceValue = 5.0f, ChangeRate = 0.2f }; this.BeQuickGoal = new Goal(BE_QUICK_GOAL, 1.0f) { ChangeRate = 0.1f }; this.Goals = new List <Goal>(); this.Goals.Add(this.SurviveGoal); this.Goals.Add(this.BeQuickGoal); this.Goals.Add(this.GetRichGoal); this.Goals.Add(this.GainXPGoal); //initialize the available actions this.Actions = new List <Action>(); this.Actions.Add(new LevelUp(this)); foreach (var chest in GameObject.FindGameObjectsWithTag("Chest")) { this.Actions.Add(new PickUpChest(this, chest)); } foreach (var potion in GameObject.FindGameObjectsWithTag("ManaPotion")) { this.Actions.Add(new GetManaPotion(this, potion)); } foreach (var potion in GameObject.FindGameObjectsWithTag("HealthPotion")) { this.Actions.Add(new GetHealthPotion(this, potion)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Skeleton")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new Fireball(this, enemy)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Orc")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new Fireball(this, enemy)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Dragon")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new Fireball(this, enemy)); } if (MCTSBias) { //temporary model used to sort var WorldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); if (MCTSBiasActions) { this.Actions.Sort((item1, item2) => item1.getHValue(WorldModel as WorldModel) < item2.getHValue(WorldModel) ? 1 : 0); //model with sorted values WorldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); } this.MCTSDecisionMaking = new MCTSBiasedPlayout(WorldModel); } else if (MCTSearch) { var WorldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); if (MCTSBiasActions) { this.Actions.Sort((item1, item2) => item1.getHValue(WorldModel as WorldModel) < item2.getHValue(WorldModel) ? 1 : 0); //model with sorted values WorldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); } this.GOAPDecisionMaking = new DepthLimitedGOAPDecisionMaking(WorldModel, this.Actions, this.Goals); this.MCTSDecisionMaking = new MCTS(WorldModel); } else if (MCTSRave) { var WorldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); if (MCTSBiasActions) { this.Actions.Sort((item1, item2) => item1.getHValue(WorldModel as WorldModel) < item2.getHValue(WorldModel) ? 1 : 0); //model with sorted values WorldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); } this.GOAPDecisionMaking = new DepthLimitedGOAPDecisionMaking(WorldModel, this.Actions, this.Goals); this.MCTSDecisionMaking = new MCTSRAVE(WorldModel); } else if (MCTSBiasRave) { var WorldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); if (MCTSBiasActions) { this.Actions.Sort((item1, item2) => item1.getHValue(WorldModel as WorldModel) < item2.getHValue(WorldModel) ? 1 : 0); //model with sorted values WorldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); } this.GOAPDecisionMaking = new DepthLimitedGOAPDecisionMaking(WorldModel, this.Actions, this.Goals); this.MCTSDecisionMaking = new MCTSBiasedRAVE(WorldModel); } this.MCTSDecisionMaking.MaxIterations = 5000; this.MCTSDecisionMaking.MaxIterationsProcessedPerFrame = 25; }
public void Start() { this.draw = true; this.navMesh = NavigationManager.Instance.NavMeshGraphs[0]; this.Character = new DynamicCharacter(this.gameObject); //initialize your pathfinding algorithm here! //use goalBoundingPathfinding for a more efficient algorithm this.Initialize(NavigationManager.Instance.NavMeshGraphs[0], new NodeArrayAStarPathFinding(NavigationManager.Instance.NavMeshGraphs[0], new EuclidianDistanceHeuristic())); //this.goalBoundsTable = Resources.Load<GoalBoundingTable>("GoalBoundingTable"); //this.Initialize(NavigationManager.Instance.NavMeshGraphs[0], new GoalBoundingPathfinding(NavigationManager.Instance.NavMeshGraphs[0], new EuclidianDistanceHeuristic(), this.goalBoundsTable)); //initialization of the GOB decision making //let's start by creating 4 main goals this.SurviveGoal = new Goal(SURVIVE_GOAL, 2.0f); this.GainXPGoal = new Goal(GAIN_XP_GOAL, 1.0f) { ChangeRate = 0.1f }; this.GetRichGoal = new Goal(GET_RICH_GOAL, 1.0f) { InsistenceValue = 5.0f, ChangeRate = 0.2f }; this.BeQuickGoal = new Goal(BE_QUICK_GOAL, 1.0f) { ChangeRate = 0.1f }; this.Goals = new List <Goal>(); this.Goals.Add(this.SurviveGoal); this.Goals.Add(this.BeQuickGoal); this.Goals.Add(this.GetRichGoal); this.Goals.Add(this.GainXPGoal); //initialize the available actions this.Actions = new List <Action>(); foreach (var chest in GameObject.FindGameObjectsWithTag("Chest")) { this.Actions.Add(new PickUpChest(this, chest)); } foreach (var potion in GameObject.FindGameObjectsWithTag("ManaPotion")) { this.Actions.Add(new GetManaPotion(this, potion)); } foreach (var potion in GameObject.FindGameObjectsWithTag("HealthPotion")) { this.Actions.Add(new GetHealthPotion(this, potion)); } this.Actions.Add(new LevelUp(this)); foreach (var enemy in GameObject.FindGameObjectsWithTag("Skeleton")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new Fireball(this, enemy)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Orc")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new Fireball(this, enemy)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Dragon")) { this.Actions.Add(new SwordAttack(this, enemy)); //this.Actions.Add(new Fireball(this, enemy)); } var worldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); //escolher entre MCTS ou GOAP if (MCTSActive) { this.MCTSDecisionMaking = new MCTS(worldModel); } else { this.GOAPDecisionMaking = new DepthLimitedGOAPDecisionMaking(worldModel, this.Actions, this.Goals); } }
public void Start() { this.draw = true; this.navMesh = NavigationManager.Instance.NavMeshGraphs[0]; this.Character = new DynamicCharacter(this.gameObject); var clusterGraph = Resources.Load <ClusterGraph>("ClusterGraph"); this.Initialize(NavigationManager.Instance.NavMeshGraphs[0], new NodeArrayAStarPathFinding(NavigationManager.Instance.NavMeshGraphs[0], new GatewayHeuristic(clusterGraph))); //this.Initialize(NavigationManager.Instance.NavMeshGraphs[0], new NodeArrayAStarPathFinding(NavigationManager.Instance.NavMeshGraphs[0], new EuclideanHeuristic())); //initialization of the GOB decision making //let's start by creating 4 main goals this.SurviveGoal = new Goal(SURVIVE_GOAL, 2.0f); this.GainXPGoal = new Goal(GAIN_XP_GOAL, 1.0f) { ChangeRate = 0.1f }; this.GetRichGoal = new Goal(GET_RICH_GOAL, 1.0f) { InsistenceValue = 5.0f, ChangeRate = 0.2f }; this.BeQuickGoal = new Goal(BE_QUICK_GOAL, 1.0f) { ChangeRate = 0.1f }; this.Goals = new List <Goal>(); this.Goals.Add(this.SurviveGoal); this.Goals.Add(this.BeQuickGoal); this.Goals.Add(this.GetRichGoal); this.Goals.Add(this.GainXPGoal); //initialize the available actions this.Actions = new List <Action>(); foreach (var chest in GameObject.FindGameObjectsWithTag("Chest")) { this.Actions.Add(new PickUpChest(this, chest)); } foreach (var potion in GameObject.FindGameObjectsWithTag("ManaPotion")) { this.Actions.Add(new GetManaPotion(this, potion)); } foreach (var potion in GameObject.FindGameObjectsWithTag("HealthPotion")) { this.Actions.Add(new GetHealthPotion(this, potion)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Skeleton")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new Fireball(this, enemy)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Orc")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new Fireball(this, enemy)); } foreach (var enemy in GameObject.FindGameObjectsWithTag("Dragon")) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new Fireball(this, enemy)); } var worldModel = new CurrentStateWorldModel(this.GameManager, this.Actions, this.Goals); this.GOAPDecisionMaking = new DepthLimitedGOAPDecisionMaking(worldModel, this.Actions, this.Goals); this.MCTSDecisionMaking = new MCTS(worldModel); this.MCTSDecisionMaking.MaxIterations = 1000; this.MCTSDecisionMaking.MaxIterationsProcessedPerFrame = 25; }
public MCTSPlayer(IPolicyValueNet policyValueNet, float c_puct = 5, int n_playout = 300) { mcts = new MCTS(policyValueNet, c_puct, n_playout); }
public void Start() { this.draw = true; this.navMesh = NavigationManager.Instance.NavMeshGraphs[0]; this.Character = new DynamicCharacter(this.gameObject); //initialize your pathfinding algorithm here! //use goalBoundingPathfinding for a more efficient algorithm //this.Initialize(NavigationManager.Instance.NavMeshGraphs[0], new NodeArrayAStarPathFinding(NavigationManager.Instance.NavMeshGraphs[0], new EucledianDistanceHeuristic())); this.Initialize(NavigationManager.Instance.NavMeshGraphs[0], new GoalBoundingPathfinding(NavigationManager.Instance.NavMeshGraphs[0], new EucledianDistanceHeuristic(), AssetDatabase.LoadAssetAtPath <Assets.Scripts.IAJ.Unity.Pathfinding.DataStructures.GoalBounding.GoalBoundingTable>("Assets/Resources/GoalBoundingTable.asset"))); //initialization of the GOB decision making //let's start by creating 4 main goals this.SurviveGoal = new Goal(SURVIVE_GOAL, 0.2f, 0); this.GainXPGoal = new Goal(GAIN_XP_GOAL, 0.1f, 1) { ChangeRate = 0.1f }; this.GetRichGoal = new Goal(GET_RICH_GOAL, 0.1f, 2) { InsistenceValue = 5.0f, ChangeRate = 0.2f }; this.BeQuickGoal = new Goal(BE_QUICK_GOAL, 8.0f, 3) { ChangeRate = 0.1f }; this.Goals = new List <Goal>(); this.Goals.Add(this.SurviveGoal); this.Goals.Add(this.BeQuickGoal); this.Goals.Add(this.GetRichGoal); this.Goals.Add(this.GainXPGoal); //initialize the available actions this.Actions = new List <Action>(); this.Actions.Add(new ShieldOfFaith(this)); this.Actions.Add(new LayOnHands(this)); foreach (var chest in GameObject.FindGameObjectsWithTag("Chest")) { this.Actions.Add(new PickUpChest(this, chest)); } foreach (var potion in GameObject.FindGameObjectsWithTag("ManaPotion")) { this.Actions.Add(new GetManaPotion(this, potion)); } foreach (var potion in GameObject.FindGameObjectsWithTag("HealthPotion")) { this.Actions.Add(new GetHealthPotion(this, potion)); } GameObject[] skeletons = GameObject.FindGameObjectsWithTag("Skeleton"); foreach (var enemy in skeletons) { this.Actions.Add(new SwordAttack(this, enemy)); this.Actions.Add(new DivineSmite(this, enemy)); } GameObject[] orcs = GameObject.FindGameObjectsWithTag("Orc"); foreach (var enemy in orcs) { this.Actions.Add(new SwordAttack(this, enemy)); } GameObject[] dragons = GameObject.FindGameObjectsWithTag("Dragon"); foreach (var enemy in dragons) { this.Actions.Add(new SwordAttack(this, enemy)); } List <GameObject> allEnemies = new List <GameObject>(); allEnemies.AddRange(skeletons); allEnemies.AddRange(orcs); allEnemies.AddRange(dragons); GameManager.enemies = allEnemies; this.Actions.Add(new DivineWrath(this, allEnemies)); var worldModel = new PropertyArrayWorldModel(this.GameManager, this.Actions); if (MCTSActive) { //this.MCTS = new MCTS(worldModel); this.MCTS = new MCTSBiasedPlayout(worldModel); this.MCTS.autonomousCharacter = this; } else { this.GOAPDecisionMaking = new DepthLimitedGOAPDecisionMaking(worldModel, this.Actions, this.Goals); } }