public bool CyclesControl(WorldDynamic currentState, PlanAction action, StoryGraph currentGraph, KeyValuePair <AgentStateStatic, AgentStateDynamic> agent, StoryNode currentNode, bool duplicated, int globalNodeNumber, bool succsessControl) { bool result = false; // We create a test node similar to the one we are going to add to the graph as a result of the current action. StoryNode testNode = currentGraph.CreateTestNode(currentState, action, agent, currentNode, !duplicated, globalNodeNumber, succsessControl); StoryNode duplicatedNode = null; Edge testEdge = new Edge(); if (!duplicated) { duplicatedNode = currentGraph.GetNode(testNode); if (currentNode.Equals(duplicatedNode)) { return(false); } testEdge.SetUpperNode(ref currentNode); testEdge.SetLowerNode(ref duplicatedNode); currentNode.AddEdge(testEdge); duplicatedNode.AddEdge(testEdge); currentNode.AddLinkToNode(ref duplicatedNode); duplicatedNode.AddLinkToNode(ref currentNode); } string[] colors = new string[currentGraph.GetNodes().Count + 2]; for (int i = 0; i < currentGraph.GetNodes().Count + 2; i++) { colors[i] = "white"; } result = TarjanAlgStep(currentGraph.GetRoot(), ref colors, !duplicated, duplicatedNode); if (!duplicated) { currentNode.RemoveEdge(testEdge); currentNode.DeleteLink(duplicatedNode); duplicatedNode.RemoveEdge(testEdge); duplicatedNode.DeleteLink(currentNode); testEdge.ClearUpperNode(); testEdge.ClearLowerNode(); testEdge = null; } // We delete the test node and mark the loop test as passed. currentGraph.DeleteTestNode(ref testNode); return(result); }
/// <summary> /// A method in which we sequentially create a story graph, node by node, starting at the root, using the concept of Breadth First Search. /// </summary> public void BFSTraversing(StoryNode rootNode, bool root = true) { // We create a queue and a list of visited nodes. Queue <StoryNode> queue = new Queue <StoryNode>(); HashSet <StoryNode> visitedNodes = new HashSet <StoryNode>(); // Добавляем узел в очередь и список посещённых узлов. queue.Enqueue(rootNode); visitedNodes.Add(rootNode); // We initialize numeric variables storing the number of the current agent and the number of the last node in the sequence. int actualAgentNumber = 0; int globalNodeNumber = -1; // We will perform the action in a loop until the queue becomes empty. while (queue.Count > 0 && newStoryGraph.GetNodes().Count <= maxNodes) { // We take the node in question from the queue. StoryNode currentNode = queue.Dequeue(); // If we come across a node with a target state, then we do not expand it. if (storyworldConvergence.ControlToAchieveGoalState(ref currentNode)) { //currentNode.goalState = true; continue; } else { // If the node in question is a root. if (currentNode.Equals(rootNode) && root) { // We call the method for creating a new node. Step(newStoryGraph.GetRoot(), actualAgentNumber, root, ref globalNodeNumber, ref queue); // Add the considered node back to the queue (in the case of the root, we only changed it and will consider it again), // and also to the list of visited nodes. We remove the flag indicating that we are considering the root node. queue.Enqueue(currentNode); visitedNodes.Add(currentNode); root = false; } // If the node in question IS NOT a root. else { // We determine the index of the agent, which will have to act when creating a new node. actualAgentNumber = GetActualAgentNumber(currentNode.GetWorldState().GetIndexOfAgent(currentNode.GetActiveAgent()), ref currentNode); // We call the method to create a new node. Step(newStoryGraph.GetNode(currentNode), actualAgentNumber, root, ref globalNodeNumber, ref queue); } } // We go through the nodes associated with the considered one. foreach (StoryNode nextNode in currentNode.GetLinks()) { // If one of them has already been visited earlier, then we continue, moving on to the next. if (visitedNodes.Contains(nextNode)) { continue; } // Otherwise, we add them to the queue and the list of visited nodes. queue.Enqueue(nextNode); visitedNodes.Add(nextNode); } // We clear the link pointing to the node in question. currentNode = null; } }