예제 #1
0
        /// <summary>
        /// Expands a selected node, if possible.
        /// </summary>
        /// <param name="id">The selected node.</param>
        /// <param name="tree">The game tree object.</param>
        /// <returns></returns>
        private static int Expand(int id, GameTree tree)
        {
            // Get the node object that corresponds with the input ID.
            GameTreeNode node = tree.GetNode(id);

            // If the node has at least one unplayed child, is not a dead end, and is not a goal state.
            if (node.Unplayed.Count > 0 && !node.DeadEnd && !node.IsGoal)
            {
                // Choose an unplayed child at random.
                GameTreeEdge outgoing = node.Unplayed.PickRandom <GameTreeEdge>();

                // Remove the child from the list of unplayed edges.
                node.Unplayed.Remove(outgoing);

                // Create the node object and store the child's ID.
                int child = tree.CreateNode(node.Domain, node.Problem, outgoing).ID;

                // Save the parent node to disk.
                tree.SetNode(node);

                // Return the child ID.
                return(child);
            }

            // Return the leaf node.
            return(node.ID);
        }
예제 #2
0
        /// <summary>
        /// Given a number of plays and a game tree object, performs MCTS.
        /// </summary>
        /// <param name="plays">The number of MCTS plays to perform.</param>
        /// <param name="tree">The game tree object on which to perform the search.</param>
        public static void Search(int plays, GameTree tree)
        {
            // Loop for the number of input play throughs.
            for (int i = 0; i < plays; i++)
            {
                // Select a leaf node.
                int select = Select(0, tree);

                // Expand the leaf node.
                int expand = Expand(select, tree);

                // Simulate a roll out from the leaf node.
                bool result = Simulate(expand, tree);

                // Propagate the result of the roll out back up the tree.
                Propagate(result, expand, tree);
            }
        }
예제 #3
0
        /// <summary>
        /// Selects a leaf node to expand.
        /// </summary>
        /// <param name="id">The ID of the current node.</param>
        /// <param name="tree">The game tree object.</param>
        /// <returns></returns>
        private static int Select(int id, GameTree tree)
        {
            // Get the node object that corresponds to the current ID.
            GameTreeNode node = tree.GetNode(id);

            // If the node has not been played before, has at least one outgoing edge, is not a dead end, and is not a goal state...
            if (node.Unplayed.Count == 0 && node.Outgoing.Count > 0 && !node.DeadEnd && !node.IsGoal)
            {
                // Create a variable to store the child with the highest interval.
                int highestChild = -1;

                // If it's not the player's turn...
                if (!tree.TurnOrder[node.Depth % tree.TurnOrder.Count].Equals(tree.Player))
                {
                    // Set the highest child to be the first child.
                    highestChild = node.Outgoing[0].Child;

                    // Loop through every remaining child.
                    for (int i = 1; i < node.Outgoing.Count; i++)
                    {
                        // If the current child has a higher interval than the stored child.
                        if (tree.GetInterval(node.Outgoing[i].Child) > tree.GetInterval(highestChild))
                        {
                            // Store the current child.
                            highestChild = node.Outgoing[i].Child;
                        }
                    }
                }
                // If it's the player's turn, chose an outgoing edge at random.
                else
                {
                    highestChild = node.Outgoing.PickRandom <GameTreeEdge>().Child;
                }

                // Recursively call this method with the selected child.
                return(Select(highestChild, tree));
            }

            // Return the leaf node.
            return(node.ID);
        }
예제 #4
0
        /// <summary>
        /// Propagates a roll out's result back through the tree.
        /// </summary>
        /// <param name="result">Whether the roll out resulted in a win or loss.</param>
        /// <param name="node">The current node.</param>
        /// <param name="tree">The game tree object.</param>
        private static void Propagate(bool result, int node, GameTree tree)
        {
            // Get the current node's parent ID.
            int parent = tree.GetParent(node);

            // Loop until we hit the root node's null parent link.
            while (parent != -1)
            {
                // Get the parent's node object from the game tree.
                GameTreeNode parentNode = tree.GetNode(parent);

                // Add the win/loss to the parent's node object.
                parentNode.AddResult(result);

                // Save the parent's node object to disk.
                tree.SetNode(parentNode);

                // Set the parent ID to the grandparent ID.
                parent = tree.GetParent(parent);
            }
        }
예제 #5
0
 /// <summary>
 /// Given a node, simulate a roll out.
 /// </summary>
 /// <param name="id">The ID of the selected node.</param>
 /// <param name="tree">The game tree object.</param>
 /// <returns></returns>
 private static bool Simulate(int id, GameTree tree)
 {
     // Ask the tree to simulate a roll out and return the result.
     return(tree.Simulate(id));
 }