Example #1
0
    // Simple function for setting the tree of the agent.
    // All trees are defined by their rootnode: N_Root.
    public void SetTree(N_Root treeRoot, N_AgentNode.AgentType agent)
    {
        btRoot = treeRoot;
        // Find all agentnodes and set their agent to be this one.
        List <Node> agentNodes = TreeOperations.RetrieveNodesOfType(treeRoot, typeof(N_AgentNode));

        foreach (N_AgentNode n in agentNodes)
        {
            n.SetAgent(agent);
        }
    }
Example #2
0
    // Load both trees and assign them to the match simulator.
    private IEnumerator StartBattle()
    {
        singleBT = FileSaver.GetInstance().LoadTree(singleFilename);
        multiBT  = FileSaver.GetInstance().LoadTree(multiFilename);

        // Reset scores
        m_singleWon    = m_multiWon = 0;
        m_singleDamage = m_multiDamage = 0;
        m_singleHealth = m_multiHealth = 0;

        if (singleBT == null || multiBT == null)
        {
            Debug.LogError("Couldn't find requested behaviourtrees.");
            m_feedbackText.SetText("There doesn't exist a file for each algorithm. Please evolve using one of each before battling.");
            yield return(null);
        }

        originalMatchLength   = m_simulator.matchTime;
        m_simulator.matchTime = matchLength;
        // Disable button canvas before starting simulation
        m_buttonCanvas.SetActive(false);
        for (int i = 0; i < simulationMatches; i++)
        {
            m_feedbackText.SetText("Battle " + i);

            // Start match and set timescale
            battleOn = true;
            m_simulator.liveSimulationScale = battleTimeScale;

            // Start match and wait until over.
            m_simulator.SetAgentBTs(singleBT, multiBT);
            m_simulator.StartMatch();
            yield return(new WaitUntil(() => !battleOn));
        }

        ScreenCapture.CaptureScreenshot("Resultat.png");

        m_feedbackText.SetText("Single won: " + m_singleWon + ", Multi won: " + m_multiWon
                               + "\n" + "Single damage: " + m_singleDamage + ", Multi damage: " + m_multiDamage
                               + "\n" + "Single health: " + m_singleHealth + ", Multi health: " + m_multiHealth);
        m_buttonCanvas.SetActive(true);
        // Reset simulation scale and matchtime before yielding
        m_simulator.liveSimulationScale = m_simulator.simulationTimeScale;
        m_simulator.matchTime           = originalMatchLength;

        yield return(null);
    }
Example #3
0
    public void SaveTree(N_Root tree, string fileName)
    {
        string filePath = directoryPath + "/" + fileName + ".tree";

        if (!File.Exists(filePath))
        {
            Directory.CreateDirectory(directoryPath);
            FileStream newFile = File.Create(filePath);
            newFile.Close();
        }

        BinaryFormatter bf   = new BinaryFormatter();
        FileStream      file = File.Open(filePath, FileMode.Create);

        bf.Serialize(file, tree);
        file.Close();
        Debug.Log("Successfully saved " + filePath);
    }
Example #4
0
    // Randomize a new BT using given defined subtrees and definitions.
    protected Genome RandomGenome()
    {
        N_Root root         = new N_Root();
        Genome randomGenome = new Genome();

        // First, randomize starting composition.
        N_CompositionNode firstComp = RandomComp();

        N_CompositionNode currentComp = firstComp;
        bool nestled = false;

        // Generate random subtrees
        for (int i = 0; i < genomeSubtrees; i++)
        {
            // Calculate random chance for adding a new composition as well
            // as ending it.
            float randomChance = UnityEngine.Random.Range(0.0f, 1.0f);
            if (randomChance < additionalCompChance && !nestled)
            {
                nestled = true;
                N_CompositionNode subComp = RandomComp();

                // Attach new composition and add a subtree to it.
                currentComp.AddLast(subComp);
                currentComp = subComp;
            }
            else if (randomChance < (additionalCompChance + 0.2f) && nestled)
            {
                nestled     = false;
                currentComp = firstComp;
            }

            // Lastly, add a random subtree to the current composition as
            // well as to the list of subtree roots.
            Node subTree = RandomSubtree();
            randomGenome.SubRoots.Add(subTree);
            currentComp.AddLast(subTree);
        }

        root.Child            = firstComp;
        randomGenome.RootNode = root;

        return(randomGenome);
    }
Example #5
0
    public N_Root LoadTree(string fileName)
    {
        string filePath = directoryPath + "/" + fileName + ".tree";

        if (File.Exists(filePath))
        {
            BinaryFormatter bf   = new BinaryFormatter();
            FileStream      file = File.Open(filePath, FileMode.Open);
            N_Root          data = (N_Root)bf.Deserialize(file);
            file.Close();

            Debug.Log("Successfully loaded " + filePath);
            return(data);
        }
        else
        {
            Debug.Log("No savefile found, when trying to load.");
            return(null);
        }
    }
Example #6
0
    public static List <Node> RetrieveNodesOfType(N_Root tree, Type nodeType)
    {
        Queue <Node> itQ   = new Queue <Node>();
        List <Node>  found = new List <Node>();

        itQ.Enqueue(tree.Child);

        // Do a breadth-first search to retrieve all nodes of the given type.
        while (itQ.Count > 0)
        {
            Node current = itQ.Dequeue();
            // If the current node ís the same as the search type
            // or a subclass of it, add it to found.
            if (current.GetType().IsSubclassOf(nodeType) ||
                current.GetType() == nodeType)
            {
                found.Add(current);
            }

            // If node is a composition or decorator, enqueue its child(ren).
            if (current.GetType().IsSubclassOf(typeof(N_CompositionNode)))
            {
                N_CompositionNode comp = current as N_CompositionNode;
                foreach (Node n in comp.GetChildren())
                {
                    itQ.Enqueue(n);
                }
            }
            else if (current.GetType().IsSubclassOf(typeof(N_Decorator)))
            {
                N_Decorator dec = current as N_Decorator;
                itQ.Enqueue(dec.Child);
            }
        }

        // Lastly, return the found children.
        return(found);
    }
Example #7
0
    // Return a list of all nodes that act as roots for a randomized subtree.
    public static List <Node> RetrieveSubtreeNodes(N_Root tree)
    {
        Queue <Node> itQ   = new Queue <Node>();
        List <Node>  found = new List <Node>();

        itQ.Enqueue(tree.Child);

        while (itQ.Count > 0)
        {
            Node current = itQ.Dequeue();

            // If current node is flagged as subtree, add it to found
            if (current.IsSubtree)
            {
                found.Add(current);
            }

            // If node is a composition or decorator, enqueue its child(ren).
            if (current.GetType().IsSubclassOf(typeof(N_CompositionNode)))
            {
                N_CompositionNode comp = current as N_CompositionNode;
                foreach (Node n in comp.GetChildren())
                {
                    itQ.Enqueue(n);
                }
            }
            else if (current.GetType().IsSubclassOf(typeof(N_Decorator)))
            {
                N_Decorator dec = current as N_Decorator;
                itQ.Enqueue(dec.Child);
            }
        }

        // Return all nodes found with the subtree flag
        return(found);
    }
Example #8
0
    // Assign random mutations to the given tree.
    protected void Mutate(N_Root child)
    {
        // First, check if there'll be any mutation at all.
        float random = UnityEngine.Random.Range(0.0f, 1.0f);

        if (random < mutationRate)
        {
            List <Node> thresholds = TreeOperations.RetrieveNodesOfType(child, typeof(N_Threshold));
            List <Node> probNodes  = TreeOperations.RetrieveNodesOfType(child, typeof(N_ProbabilitySelector));

            // Randomise between whether to change thresholds or probabilities
            random = UnityEngine.Random.Range(0.0f, 1.0f);
            // If no probnode exists, change condition if there are any instead
            if ((random <= 0.25f && thresholds.Count > 0))
            {
                //Debug.Log("Changing threshold!");
                // Get random index within range of list
                int         index  = UnityEngine.Random.Range(0, thresholds.Count);
                N_Threshold thresh = thresholds[index] as N_Threshold;

                // Mutate threshold by random offset
                int offset = UnityEngine.Random.Range(minThresholdOffset, maxTresholdOffset);
                thresh.SetThreshold(thresh.Threshold + offset);
            }
            else if (random > 0.25f && random <= 0.5f && probNodes.Count > 0) // Adjust relative probabilities on a probability selector.
            {
                //Debug.Log("Changing prob!");
                // Get random index within range of list
                int index = UnityEngine.Random.Range(0, probNodes.Count);
                N_ProbabilitySelector probSelect = probNodes[index] as N_ProbabilitySelector;

                // Check so that the probablitySelector has any children.
                if (probSelect.GetChildren().Count <= 0)
                {
                    return;
                }

                // Calculate total probability and retrieve a relative offset based on it.
                float totalProb = 0.0f;
                foreach (Node n in probSelect.GetChildren())
                {
                    totalProb += probSelect.GetProbabilityWeight(n);
                }
                float offset = totalProb * (relativeProbabilityMutation / 100.0f);
                // Also, get a random sign to decide whether to substract or add offset
                // and a random index for which child to be changed.
                float randomSign       = Mathf.Sign(UnityEngine.Random.Range(-1.0f, 1.0f));
                int   randomChildIndex = UnityEngine.Random.Range(0, probSelect.GetChildren().Count);

                // Finally, offset the given childs probability by the random amount.
                probSelect.OffsetProbabilityWeight(probSelect.GetChildren()[randomChildIndex]
                                                   , offset * randomSign);
            }
            else if (random > 0.5f && random <= 0.75f) // Change subtree
            {
                //Debug.Log("Changing subtree!");
                List <Node>       subtrees    = TreeOperations.RetrieveSubtreeNodes(child);
                int               randomIndex = UnityEngine.Random.Range(0, subtrees.Count);
                Node              subtree     = subtrees[randomIndex];
                N_CompositionNode parentComp  = subtree.Parent as N_CompositionNode;

                // Get a random subtree index and replace its position in the tree with
                // a new randomized subtree instead.
                parentComp.ReplaceChild(subtree, RandomSubtree());
            }
            else if (random > 0.75f) // Change composition
            {
                //Debug.Log("Changing composition!");
                List <Node>       comps       = TreeOperations.RetrieveNodesOfType(child, typeof(N_CompositionNode));
                int               randomIndex = UnityEngine.Random.Range(0, comps.Count);
                N_CompositionNode replaceComp = comps[randomIndex] as N_CompositionNode;

                // If parent is null, this comp is the initial comp.
                if (replaceComp.Parent != null)
                {
                    Node        compParent = replaceComp.Parent;
                    List <Node> children   = replaceComp.GetChildren();

                    // Attach old comps children to the new one.
                    N_CompositionNode newComp = RandomComp();
                    // Make sure to keep structure of subtrees
                    if (replaceComp.IsSubtree)
                    {
                        newComp.IsSubtree = true;
                    }

                    foreach (Node c in children)
                    {
                        c.Parent = newComp;
                        newComp.AddLast(c);
                    }

                    // Reattach parent to the new comp
                    if (compParent.GetType().IsSubclassOf(typeof(N_CompositionNode)))
                    {
                        N_CompositionNode compParent_comp = compParent as N_CompositionNode;
                        compParent_comp.ReplaceChild(replaceComp, newComp);
                    }
                    else if (compParent.GetType().IsSubclassOf(typeof(N_Decorator)))
                    {
                        N_Decorator compParent_dec = compParent as N_Decorator;
                        compParent_dec.Child = newComp;
                    }
                }
            }
        }
    }
Example #9
0
 public Genome(N_Root root)
 {
     subRoots = new List <Node>();
     rootNode = root;
 }
Example #10
0
 // Initialize variables.
 public Genome()
 {
     subRoots = new List <Node>();
     rootNode = null;
 }
Example #11
0
 // Set the behaviour trees of the agents.
 public void SetAgentBTs(N_Root bt0, N_Root bt1)
 {
     bt_agent0.SetTree(bt0, N_AgentNode.AgentType.agent0);
     bt_agent1.SetTree(bt1, N_AgentNode.AgentType.agent1);
 }