/// <summary> /// Changes the current node to be the parent of the current node, if it has a parent /// </summary> public void SelectParentNode() { if (CurrentNode.Parent != null) { CurrentNode = (NodeObject)CurrentNode.Parent; LineDraw.SelectNode(CurrentNode); TreeUIController.DisplayNodeInfo(CurrentNode); } }
/// <summary> /// Changes the currently selected node to be a child of the currently selected node /// </summary> /// <param name="childIndex">The child index of the new selected node</param> public void SelectChildNode(int childIndex) { if (CurrentNode.Children.Count > childIndex) { CurrentNode = (NodeObject)CurrentNode.Children[childIndex]; LineDraw.SelectNode(CurrentNode); TreeUIController.DisplayNodeInfo(CurrentNode); } }
/// <summary> /// Runs MCTS until completion asyncronously and then disables the stop button /// </summary> /// <param name="mcts">The MCTS instance to run</param> private static async void RunMCTS(TreeSearch <NodeObject> mcts) { await Task.Factory.StartNew(() => { while (!mcts.Finished) { mcts.Step(); } }, TaskCreationOptions.LongRunning); TreeUIController.StopButtonPressed(); }
/// <summary> /// If the user has started running MCTS, then display information about it to the UI whilst it generates <para/> /// When the MCTS has finished generating, set the position of each <see cref="NodeObject"/> so that they can be rendered on-screen <para/> /// When each nodes position has been set, switch to the tree navigation UI /// </summary> void Update() { //Don't do anything until the user has started running the MCTS if (mcts == null) { return; } //While the MCTS is still running, display progress information about the time remaining and the amounts of nodes created to the user if (!mcts.Finished) { timeLeft -= Time.deltaTime; if (timeLeft <= 0) { mcts.Finish(); } TreeUIController.UpdateProgressBar((1 - (timeLeft / timeToRunFor)) / 2, "Running MCTS " + mcts.UniqueNodes + " nodes " + timeLeft.ToString("0.0") + "s/" + timeToRunFor.ToString("0.0") + "s"); } //Return if the MCTS has not finished being created if (!mcts.Finished) { return; } //If the MCTS has finished being computed, start to create gameobjects for each node in the tree if (!startedVisualisation) { rootNodeObject = (NodeObject)mcts.Root; rootNodeObject.SetPosition(visualisationType); StartCoroutine(SetNodePosition(rootNodeObject)); startedVisualisation = true; } //Display information on the progress bar about how many node objects have been created, until every node in the tree has its own gameobject if (!allNodesGenerated) { if (nodesGenerated < mcts.UniqueNodes) { TreeUIController.UpdateProgressBar(0.5f + ((float)nodesGenerated / mcts.UniqueNodes / 2), "Creating node objects: " + nodesGenerated + "/" + mcts.UniqueNodes); } else if (nodesGenerated == mcts.UniqueNodes) { //If every node has had a gameobject created for it, then switch to the navigation UI and start to render the game tree TreeUIController.SwitchToNavigationUI(); Camera.main.GetComponent <LineDraw>().linesVisible = true; Camera.main.GetComponent <TreeCameraControl>().CurrentNode = rootNodeObject; TreeUIController.DisplayNodeInfo(mcts.Root); allNodesGenerated = true; LineDraw.SelectNode(rootNodeObject); } } }
/// <summary> /// Ran when the program starts <para/> /// There should only ever be one object with a TreeUIController, so this should only be run once /// </summary> public void Start() { //If the singleton reference is not null, then there are more than one UIcontrollers, which is not allowed if (uiController != null) { throw new Exception("UIController is a Singleton, there cannot be more than one instance"); } //Set the singleton static reference to be this instance uiController = this; //Setup the list of child buttons to use for displaying child node information ChildButtons = new List <Button>(); //Add each child button to the list of child buttons for (int i = 0; i < ChildButtonHolder.childCount; i++) { ChildButtons.Add(ChildButtonHolder.GetChild(i).GetComponent <Button>()); ChildButtonHolder.GetChild(i).GetComponent <Button>().gameObject.SetActive(false); } }
/// <summary> /// Called when the start/stop button is pressed <para/> /// If MCTS is not running, then it will be started <para/> /// If MCTS is running, this will make it finish early /// </summary> public void StartStopButtonPressed() { //Starts or ends MCTS depending on when the button is pressed if (mcts == null) { //Create an empty board instance, which will have whatever game the user chooses assigned to it Board board; //Assign whatever game board the user has chosen to the board instance switch (TreeUIController.GetGameChoice) { case 0: displayBoardModel = false; board = new TTTBoard(); break; case 1: displayBoardModel = true; board = new C4Board(); //Create a C4 Board GameObject and obtain a reference to its BoardModelController Component GameObject boardModel = Instantiate(Resources.Load("C4 Board", typeof(GameObject))) as GameObject; boardModelController = boardModel.GetComponent <BoardModelController>(); boardModelController.Initialise(); break; case 2: displayBoardModel = false; board = new OthelloBoard(); break; default: throw new System.Exception("Unknown game type index has been input"); } //Assign whatever visualisation type the user has chosen switch (TreeUIController.GetVisualisationChoice) { case 0: visualisationType = VisualisationType.Standard3D; break; case 1: visualisationType = VisualisationType.Disk2D; break; case 2: visualisationType = VisualisationType.Cone; break; default: throw new System.Exception("Unknown visualisation type: encountered"); } //Initialise MCTS on the given game board mcts = new TreeSearch <NodeObject>(board); //Obtain the time to run mcts for from the input user amount timeToRunFor = TreeUIController.GetTimeToRunInput; timeLeft = timeToRunFor; //Run mcts asyncronously RunMCTS(mcts); TreeUIController.StartButtonPressed(); } else { //Stop the MCTS early mcts.Finish(); } }