示例#1
0
        /// <summary>
        /// Checks the achievement of any of the goal conditions (in state).
        /// </summary>
        /// <param name="currentWorldState"></param>
        public bool ControlToAchieveGoalState(ref StoryNode currentNode)
        {
            foreach (var goal in allGoalStates)
            {
                // todo: convert to switch
                // todo: supplement the types of goals - group and specific

                if (goal.goalTypeIsStatus)
                {
                    int  killCounter = 0;
                    bool killerDied  = false;

                    foreach (var agent in currentNode.GetWorldState().GetAgents())
                    {
                        switch (agent.Key.GetRole())
                        {
                        case AgentRole.USUAL: if (!agent.Value.GetStatus())
                            {
                                killCounter++;
                            }
                            break;

                        case AgentRole.PLAYER: if (!agent.Value.GetStatus())
                            {
                                killCounter++;
                            }
                            break;

                        case AgentRole.KILLER: if (!agent.Value.GetStatus())
                            {
                                killerDied = true;
                            }
                            break;
                        }
                    }

                    if (killCounter == currentNode.GetWorldState().GetAgents().Count - 1)
                    {
                        currentNode.goalState = true;
                        return(true);
                    }
                    if (killerDied)
                    {
                        currentNode.goalState = true;
                        return(true);
                    }
                }
            }

            return(false);
        }
示例#2
0
        /// <summary>
        /// Create a new node for the story graph and inserts it.
        /// </summary>
        public void CreateNewNode(PlanAction action,
                                  KeyValuePair <AgentStateStatic, AgentStateDynamic> agent,
                                  WorldDynamic currentState,
                                  StoryNode currentNode,
                                  ref int globalNodeNumber,
                                  bool succsessControl,
                                  bool counteract)
        {
            WorldDynamic newState = (WorldDynamic)currentState.Clone();

            if (!succsessControl)
            {
                action.Fail(ref newState);
            }
            else
            {
                action.ApplyEffects(ref newState);
            }
            newState.UpdateHashCode();

            // Create an empty new node.
            StoryNode newNode = new StoryNode();

            if (counteract)
            {
                newNode.counteract = true;
            }

            // We assign the state of the world (transferred) to the new node.
            newNode.SetWorldState((WorldDynamic)newState.Clone());

            newNode.SetActiveAgent(newNode.GetWorldState().GetAgentByName(agent.Key.GetName()));
            if (agent.Key.GetRole() == AgentRole.PLAYER)
            {
                newNode.SetActivePlayer(true);
            }
            else
            {
                newNode.SetActivePlayer(false);
            }

            ConnectionTwoNodes(action, currentNode, newNode, false);

            globalNodeNumber++;
            newNode.SetNumberInSequence(globalNodeNumber);

            if (nodes.Contains(newNode))
            {
                bool test = true;
            }

            // Add a new node to the graph.
            AddNode(newNode);
        }
        /// <summary>
        /// A method that returns the index of the agent that should perform the action.
        /// </summary>
        /// <param name="prevNumber">Index of the agent who performed the action in the previous state.</param>
        public int GetActualAgentNumber(int prevNumber, ref StoryNode currentNode)
        {
            // Flag for checking if the agent being checked is alive.
            bool aliveControl = false;

            // Determine how many agents exist in the current state.
            int maxNumber = currentNode.GetWorldState().GetNumberOfAgents();

            // Default result.
            int result = 0;

            // Until the flag signaling the status of the agent being checked is omitted.
            while (!aliveControl)
            {
                // If the index of the previous agent is equal to the maximum possible index.
                if (prevNumber == maxNumber - 1)
                {
                    // Then we go back to the beginning of the index list and set 0 as the result (the circle is passed).
                    result     = 0;
                    prevNumber = 0;
                }
                else
                {
                    // Otherwise, we increase the value of the index of the previous agent by one and write it down as a result.
                    prevNumber++;
                    result = prevNumber;
                }

                // We check if the agent with the received index is alive. If not, we continue the cycle.
                if (!currentNode.GetWorldState().GetAgentByIndex(result).Value.GetStatus())
                {
                    continue;
                }

                // Otherwise, we raise the flag that the control has been passed.
                aliveControl = true;
            }

            // We return the result - the index of the guaranteed living agent acting after the specified in the parameters.
            return(result);
        }
示例#4
0
        public StoryNode CreateTestNode(WorldDynamic currentState,
                                        PlanAction action,
                                        KeyValuePair <AgentStateStatic, AgentStateDynamic> agent,
                                        StoryNode currentNode,
                                        bool connection,
                                        int globalNodeNumber,
                                        bool succsessControl)
        {
            WorldDynamic worldForTest = (WorldDynamic)currentState.Clone();

            if (!succsessControl)
            {
                action.Fail(ref worldForTest);
            }
            else
            {
                action.ApplyEffects(ref worldForTest);
            }
            worldForTest.UpdateHashCode();

            StoryNode testNode = new StoryNode();

            //if (counteract) { testNode.counteract = true; }
            //testNode.SetWorldState(worldForTest);
            testNode.SetWorldState((WorldDynamic)worldForTest.Clone());

            // Create a clone of the agent.
            //KeyValuePair<AgentStateStatic, AgentStateDynamic> newAgent =
            //    new KeyValuePair<AgentStateStatic, AgentStateDynamic>((AgentStateStatic)agent.Key.Clone(), (AgentStateDynamic)agent.Value.Clone());
            testNode.SetActiveAgent(testNode.GetWorldState().GetAgentByName(agent.Key.GetName()));

            // We take the last node from the list of all nodes and assign whether the player is active and which of the agents was active on this turn.
            if (agent.Key.GetRole() == AgentRole.PLAYER)
            {
                testNode.SetActivePlayer(true);
            }
            else
            {
                testNode.SetActivePlayer(false);
            }

            //testNode.SetActiveAgent(newAgent);

            /*if (connection)
             * {
             *  ConnectionTwoNodes(action, currentNode, testNode, false);
             * }*/

            testNode.SetNumberInSequence(globalNodeNumber + 1);

            return(testNode);
        }
        /// <summary>
        /// Convergence in turn asks agents for actions, checks them, applies them, counteracts them, or does not.
        /// </summary>
        public void Step(StoryNode currentNode, int agentIndex, bool root, ref int globalNodeNumber, ref Queue <StoryNode> queue)
        {
            // Convergence assigns who is on the turn to the node and then applies the changes to the state of the world.
            currentStoryState = currentNode.GetWorldState();
            currentStoryState.GetStaticWorldPart().IncreaseTurnNumber();

            while (!currentStoryState.GetAgentByIndex(agentIndex).Value.GetStatus())
            {
                agentIndex = GetActualAgentNumber(agentIndex, ref currentNode);
            }

            // We check if the agent from whom we are going to request an action is alive (i.e. capable of doing it).
            if (currentStoryState.GetAgentByIndex(agentIndex).Value.GetStatus())
            {
                // We create a request for action of the specified agent from the specified state.
                storyworldConvergence.ActionRequest(currentStoryState.GetAgentByIndex(agentIndex), ref newStoryGraph, ref currentStoryState,
                                                    currentNode, root, ref globalNodeNumber, ref queue);
            }
        }
        /// <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;
            }
        }