private N_CompositionNode RandomComp() { N_CompositionNode randomComp; int randomComposition = UnityEngine.Random.Range(0, 3); switch (randomComposition) { case 0: randomComp = new N_Selection(); break; case 1: randomComp = new N_Sequence(); break; case 2: randomComp = new N_ProbabilitySelector(); break; default: randomComp = null; Debug.LogError("No comp was chosen for generation of BT."); break; } return(randomComp); }
// Sequence for moving by patroling or kiting. // If an enemy is spotted, there's a probability of the agent either patroling. // or kiting. If no enemy, always patrol. // Returns success if path found and started. // Returns running if in process of walking towards destination. public static Node Tree_PatrolOrKite(N_AgentNode.AgentType agent) { N_ProbabilitySelector kiteOrPatrol = new N_ProbabilitySelector(); kiteOrPatrol.AddLast(new N_Kite(agent)); kiteOrPatrol.AddLast(new N_Patrol(agent)); //N_DecSuccess kiteOrPatrolSuccess = new N_DecSuccess(kiteOrPatrol); N_Sequence enemyThenKiteOrPatrol = new N_Sequence(); enemyThenKiteOrPatrol.AddLast(new N_IsEnemyVisible(agent)); enemyThenKiteOrPatrol.AddLast(kiteOrPatrol); //N_DecSuccess patrolSuccess = new N_DecSuccess(new N_Patrol(agent)); N_Selection enemyOrPatrol = new N_Selection(); enemyOrPatrol.AddLast(enemyThenKiteOrPatrol); enemyOrPatrol.AddLast(new N_Patrol(agent)); enemyOrPatrol.IsSubtree = true; return(enemyOrPatrol); }
// 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; } } } } }