Пример #1
0
        // Realtime level generation I
        public static CreVoxNode GenerateMissionGraph(string xmlPath, int Seed)
        {
            DungeonLevel.OperateXML.Unserialize.UnserializeFromXml(xmlPath);
            GraphGrammar graph = new GraphGrammar();

            // Rewrite system initialization.
            RewriteSystem.Initial(Seed);
            graph = RewriteSystem.TransformFromGraph();
            var stopWatch = System.Diagnostics.Stopwatch.StartNew();

            // Iterate until finish.
            while (
                (
                    // Still exist non-terminal nodes.
                    graph.Nodes.Exists(n => n.Terminal == NodeTerminalType.NonTerminal)
                    // Have to exhauste all rules that set minimum.
                    || RewriteSystem.Rules.Sum(r => r.QuantityLimitMin) > 0
                )
                // Time limit is 3,000 ms.
                && stopWatch.ElapsedMilliseconds <= 3000
                )
            {
                // Rewrite system iteration.
                RewriteSystem.Iterate();
                // Update the current graph.
                graph = RewriteSystem.TransformFromGraph();
            }
            stopWatch.Stop();
            // Setting root node for CreVoxAttach.
            SetCreVoxNodeRoot(graph.Nodes[0]);
            Debug.Log(_rootNode);
            return(_rootNode);
        }
Пример #2
0
            // Unserialize MissionGraph
            private static Mission.GraphGrammar UnserializeMissionGraph(XElement element)
            {
                Mission.GraphGrammar graph = new Mission.GraphGrammar();
                XElement             elementMissionGraph = element.Element("MissionGraph");

                graph.Nodes       = UnserializeNodes(elementMissionGraph);
                graph.Connections = UnserializeConnections(elementMissionGraph);
                // Unserialize sticky
                int connectionIndex = 0;

                foreach (var elementConnection in elementMissionGraph.Element("Connections").Elements("Connection"))
                {
                    if (!elementConnection.Element("StartpointStickyOn").IsEmpty)
                    {
                        Guid guid      = new Guid(elementConnection.Element("StartpointStickyOn").Value);
                        int  nodeIndex = graph.Nodes.FindIndex(x => x.ID == guid);
                        graph.Connections[connectionIndex].StartpointStickyOn = graph.Nodes[nodeIndex];
                        graph.Nodes[nodeIndex].AddStickiedConnection(graph.Connections[connectionIndex], "start");
                    }
                    if (!elementConnection.Element("EndpointStickyOn").IsEmpty)
                    {
                        Guid guid      = new Guid(elementConnection.Element("EndpointStickyOn").Value);
                        int  nodeIndex = graph.Nodes.FindIndex(x => x.ID == guid);
                        graph.Connections[connectionIndex].EndpointStickyOn = graph.Nodes[nodeIndex];
                        graph.Nodes[nodeIndex].AddStickiedConnection(graph.Connections[connectionIndex], "end");
                    }
                    connectionIndex++;
                }
                return(graph);
            }
Пример #3
0
        // Transform a graph into tree struct. Then return the table.
        private static List <Node> TransformGraph(GraphGrammar graph, out int nodeCount)
        {
            int edgeIndex = graph.Nodes.Count + 1;
            // Initialize nodes
            var nodes = new List <Node>();

            for (int i = 0; i < graph.Nodes.Count; i++)
            {
                nodes.Add(new Node(graph.Nodes[i], graph.Nodes[i].Ordering));
            }
            // Set parents and children
            for (int i = 0; i < graph.Nodes.Count; i++)
            {
                foreach (var childNode in graph.Nodes[i].Children)
                {
                    Node edgeNode = new Node(graph.GetConnectionByNode(graph.Nodes[i], childNode), edgeIndex++);
                    nodes.Add(edgeNode);
                    nodes[i].Children.Add(edgeNode);
                    edgeNode.Parents.Add(nodes[i]);
                    int index = graph.Nodes.FindIndex(n => n.ID == childNode.ID);
                    edgeNode.Children.Add(nodes[index]);
                    nodes[index].Parents.Add(edgeNode);
                }
            }
            // Update the node count.
            nodeCount = graph.Nodes.Count + graph.Connections.Count;
            // Return the table.
            return(nodes.OrderBy(n => n.Index).ToList());
        }
Пример #4
0
 // No 9. OverflowedAnyNode.
 private static bool ValidateOverflowedAnyNode(MissionRule rule, GraphGrammar graphGrammar)
 {
     // Sort nodes in ordering.
     GraphGrammarNode[] sourceNodes = rule.SourceRule.Nodes.OrderBy(n => n.Ordering).ToArray();
     // if replaceRule have any node that dont match the source ordering.
     return(!rule.ReplacementRule.Nodes.Exists(n => (Alphabet.IsAnyNode(n.AlphabetID) &&
                                                     (n.Ordering > sourceNodes.Length ? true : !Alphabet.IsAnyNode(sourceNodes[n.Ordering - 1].AlphabetID)))));
 }
Пример #5
0
            // Serialize MissionGraph
            private static XElement SerializeMissionGraph(Mission.GraphGrammar graph)
            {
                XElement elementMissionGraph = new XElement("MissionGraph");

                elementMissionGraph.Add(SerializeNodes(graph.Nodes),
                                        SerializeConnections(graph.Connections));

                return(elementMissionGraph);
            }
Пример #6
0
 public static void Initialize()
 {
     _scrollView      = new Vector2(0, 60);
     _errorType       = ErrorType.None;
     _graphState      = GraphState.Mission;
     _currentGraph    = new Mission.GraphGrammar();
     _isInitTabButton = true;
     _isRuleChanged   = true;
     Seed             = 0;
 }
Пример #7
0
 // No 6. MultipleRelations.
 private static bool ValidateMultipleRelations(MissionRule rule, GraphGrammar graphGrammar)
 {
     if (graphGrammar.Connections.Count > 1)
     {
         foreach (GraphGrammarConnection connection in graphGrammar.Connections)
         {
             if ((graphGrammar.Connections.Where(e => (e != connection &&
                                                       (e.StartpointStickyOn == connection.StartpointStickyOn && e.EndpointStickyOn == connection.EndpointStickyOn) ||
                                                       (e.StartpointStickyOn == connection.EndpointStickyOn && e.EndpointStickyOn == connection.StartpointStickyOn)))).Any())
             {
                 return(false);
             }
         }
     }
     return(true);
 }
Пример #8
0
        // Add node and connection to graph grammar by dfs.
        // "layer" is used to calculate x position
        private static void RecursionGraphGrammar(Node node, ref GraphGrammar graphGrammar, int layer)
        {
            if (CountInLayer.Count <= layer)
            {
                CountInLayer.Add(0);
            }
            // Mark this node.
            node.Explored = true;
            // "index" is used to calculate y position.
            int index = 0;

            foreach (Node edgeNode in node.Children)
            {
                // Add connection (Now only use Connections[0], will modify).
                Node childNode  = edgeNode.Children[0];
                var  connection = new GraphGrammarConnection(Alphabet.Connections.Find(c => c.AlphabetID == edgeNode.AlphabetID));
                graphGrammar.Connections.Add(connection);
                // Set starting sticked attribute.
                _nodeMappingTable[node].AddStickiedConnection(connection, "start");
                connection.StartpointStickyOn = _nodeMappingTable[node];
                connection.StartPosition      = _nodeMappingTable[node].Position;
                // If mapping table have not contained this Node then add it.
                if (!_nodeMappingTable.ContainsKey(childNode))
                {
                    // Set position.
                    _nodeMappingTable[childNode] = new GraphGrammarNode(_referenceNodeTable[childNode.AlphabetID])
                    {
                        Position = new Vector2(LEFT_TOP_POSITION.x + layer * PADDING,
                                               LEFT_TOP_POSITION.y + (CountInLayer[layer] + index) * PADDING)
                    };
                    graphGrammar.Nodes.Add(_nodeMappingTable[childNode]);
                }
                // Set ending sticked attribute.
                _nodeMappingTable[childNode].AddStickiedConnection(connection, "end");
                connection.EndpointStickyOn = _nodeMappingTable[childNode];
                connection.EndPosition      = _nodeMappingTable[childNode].Position;
                // Check the mark exist.
                if (!childNode.Explored)
                {
                    // Search deeper, so "layer" must increase.
                    RecursionGraphGrammar(childNode, ref graphGrammar, layer + 1);
                }
                index++;
            }
            CountInLayer[layer] += index;
        }
Пример #9
0
 // No 3. IsolatedNode.
 private static bool ValidateIsolatedNode(MissionRule rule, GraphGrammar graphGrammar)
 {
     if (graphGrammar.Nodes.Count > 1)
     {
         if (graphGrammar.Connections.Count < graphGrammar.Nodes.Count - 1)
         {
             return(false);
         }
         foreach (GraphGrammarNode node in graphGrammar.Nodes)
         {
             // Connection.StickOn will remain the last node it sticked on, so use position to inforce validation.
             if (!graphGrammar.Connections.Where(c => (c.StartpointStickyOn == node || c.EndpointStickyOn == node)).Any())
             {
                 return(false);
             }
         }
     }
     return(true);
 }
Пример #10
0
        // Export the original structure from tree structure to canvas.
        public static GraphGrammar TransformFromGraph()
        {
            var graphGrammar = new GraphGrammar();

            // Get reference table (For getting the symbol of Alphabet.)
            _referenceNodeTable = Alphabet.ReferenceNodeTable;
            // _referenceConnectionTable = Alphabet.ReferenceConnectionTable;
            // Initialize mapping table.
            _nodeMappingTable = new Dictionary <Node, GraphGrammarNode>();
            // Add root node.
            _nodeMappingTable[_root] = new GraphGrammarNode(_referenceNodeTable[_root.AlphabetID])
            {
                Position = LEFT_TOP_POSITION
            };
            graphGrammar.Nodes.Add(_nodeMappingTable[_root]);
            CountInLayer.Clear();
            CountInLayer.Add(0);
            RecursionGraphGrammar(_root, ref graphGrammar, 1);
            ClearExplored(_root);
            ResultGraph = graphGrammar;
            return(graphGrammar);
        }
Пример #11
0
 // No 5. ExactlyDuplicated.
 private static bool ValidateExactlyDuplicated(MissionRule rule, GraphGrammar graphGrammar)
 {
     // Check the number of connections & nodes first.
     if (rule.SourceRule.Nodes.Count != rule.ReplacementRule.Nodes.Count ||
         rule.SourceRule.Connections.Count != rule.ReplacementRule.Connections.Count)
     {
         return(true);
     }
     // If find any difference in connections, then defined they are not isomorphic.
     foreach (var connectionA in rule.SourceRule.Connections)
     {
         if (!rule.ReplacementRule.Connections.Exists(connectionB =>
                                                      connectionB.AlphabetID == connectionA.AlphabetID &&
                                                      // Check the ordering they sticky on. If null, expresses zero.
                                                      (connectionB.StartpointStickyOn == null ? 0 : connectionB.StartpointStickyOn.Ordering) == (connectionA.StartpointStickyOn == null ? 0 : connectionA.StartpointStickyOn.Ordering) &&
                                                      (connectionB.EndpointStickyOn == null ? 0 : connectionB.EndpointStickyOn.Ordering) == (connectionA.EndpointStickyOn == null ? 0 : connectionA.EndpointStickyOn.Ordering)
                                                      ))
         {
             return(true);
         }
     }
     // If find any difference in nodes, then defined they are not isomorphic.
     foreach (var nodeA in rule.SourceRule.Nodes)
     {
         if (!rule.ReplacementRule.Nodes.Exists(nodeB =>
                                                nodeB.AlphabetID == nodeA.AlphabetID &&
                                                nodeB.Ordering == nodeA.Ordering &&
                                                nodeB.Children.Count == nodeA.Children.Count &&
                                                nodeB.Parents.Count == nodeA.Parents.Count
                                                ))
         {
             return(true);
         }
     }
     // It's illegal and isomorphic.
     return(false);
 }
Пример #12
0
 // No 8. OrphanNode.
 private static bool ValidateOrphanNode(MissionRule rule, GraphGrammar graphGrammar)
 {
     // If node has no parent, it is an orphan.
     // Indegree = 0 quantity cannot > 1.
     return(graphGrammar.Nodes.FindAll(n => n.Parents.Count == 0).Count == 1);
 }
Пример #13
0
 // Validate the graph grammar (one of pair of rule).
 public static KeyValuePair <ValidationLabel, string> Validate(MissionRule rule, GraphGrammar graphGrammar)
 {
     // Initial the error to none.
     _error = ValidationLabel.NoError;
     // Execute each method.
     foreach (var method in _validationMethods)
     {
         if (!method.Value.Invoke(rule, graphGrammar))
         {
             _error = (method.Key);
             break;
         }
     }
     // Return Error Message.
     return(new KeyValuePair <ValidationLabel, string>(_error, SelectErrorType(_error)));
 }
Пример #14
0
 // Buttons for operating the graph.
 private void LayoutFunctionButtons()
 {
     GUILayout.BeginArea(Container.FunctionButtonsArea);
     GUILayout.BeginVertical(SampleStyle.Frame(SampleStyle.ColorLightestGrey));
     GUILayout.BeginHorizontal();
     // Random seed.
     Seed = SampleStyle.IntFieldLabeled(Languages.GetText("GenerateMission-Seed"), Seed, SampleStyle.IntFieldLabel, SampleStyle.IntField, SampleStyle.IntFieldHeight);
     if (GUILayout.Button(Languages.GetText("GenerateMission-Random"), SampleStyle.GetButtonStyle(SampleStyle.ButtonType.Regular, SampleStyle.ButtonColor.Blue), SampleStyle.ButtonHeight))
     {
         Seed = Random.Range(1, 1000000);
         // Unfocus from the field.
         GUI.FocusControl("FocusToNothing");
     }
     GUILayout.EndHorizontal();
     // If error occur, disable apply button.
     EditorGUI.BeginDisabledGroup(_errorType != ErrorType.None);
     // Mission and Space Graph button.
     GUILayout.BeginHorizontal();
     if (GUILayout.Button(Languages.GetText("GenerateMission-Initial"), SampleStyle.GetButtonStyle(SampleStyle.ButtonType.Left, SampleStyle.ButtonColor.Blue), SampleStyle.ButtonHeight))
     {
         // Rewrite system initialization.
         Mission.RewriteSystem.Initial(Seed);
         _isRuleChanged = false;
         // Update the current graph.
         _currentGraph = Mission.RewriteSystem.TransformFromGraph();
         // Setting root node for CreVoxAttach.
         Mission.CreVoxAttach.SetCreVoxNodeRoot(_currentGraph.Nodes[0]);
     }
     EditorGUI.BeginDisabledGroup(_isRuleChanged);
     if (GUILayout.Button(Languages.GetText("GenerateMission-Iterate"), SampleStyle.GetButtonStyle(SampleStyle.ButtonType.Mid, SampleStyle.ButtonColor.Blue), SampleStyle.ButtonHeight))
     {
         // Rewrite system iteration.
         Mission.RewriteSystem.Iterate();
         // Update the current graph.
         _currentGraph = Mission.RewriteSystem.TransformFromGraph();
         // Setting root node for CreVoxAttach.
         Mission.CreVoxAttach.SetCreVoxNodeRoot(_currentGraph.Nodes[0]);
     }
     if (GUILayout.Button(Languages.GetText("GenerateMission-Complete"), SampleStyle.GetButtonStyle(SampleStyle.ButtonType.Right, SampleStyle.ButtonColor.Blue), SampleStyle.ButtonHeight))
     {
         var stopWatch = System.Diagnostics.Stopwatch.StartNew();
         // Iterate until finish.
         while (
             (
                 // Still exist non-terminal nodes.
                 _currentGraph.Nodes.Exists(n => n.Terminal == Mission.NodeTerminalType.NonTerminal)
                 // Have to exhauste all rules that set minimum.
                 || Mission.RewriteSystem.Rules.Sum(r => r.QuantityLimitMin) > 0
             )
             // Time limit is 3,000 ms.
             && stopWatch.ElapsedMilliseconds <= 3000
             )
         {
             // Rewrite system iteration.
             Mission.RewriteSystem.Iterate();
             // Update the current graph.
             _currentGraph = Mission.RewriteSystem.TransformFromGraph();
         }
         stopWatch.Stop();
         // Setting root node for CreVoxAttach.
         Mission.CreVoxAttach.SetCreVoxNodeRoot(_currentGraph.Nodes[0]);
     }
     EditorGUI.EndDisabledGroup();
     GUILayout.EndHorizontal();
     EditorGUI.EndDisabledGroup();
     GUILayout.EndVertical();
     GUILayout.EndArea();
 }
Пример #15
0
 // No 1. LeftMoreThanRight.
 private static bool ValidateLeftMoreThanRight(MissionRule rule, GraphGrammar graphGrammar)
 {
     // Are Nodes of sourceRule more than nodes of replacementRule?
     return(rule.SourceRule.Nodes.Count <= rule.ReplacementRule.Nodes.Count ? true : true);
 }
Пример #16
0
 // No 2. EmptyLeft.
 private static bool ValidateEmptyLeft(MissionRule rule, GraphGrammar graphGrammar)
 {
     // Is there no node in sourceRule?
     return(rule.SourceRule.Nodes.Count != 0 ? true : false);
 }
Пример #17
0
        // No 7. CyclicLink.
        private static bool ValidateCyclicLink(MissionRule rule, GraphGrammar graphGrammar)
        {
            // Store the parents and children to avoid the repeat call method.
            Dictionary <GraphGrammarNode, List <GraphGrammarNode> > parentsTable  = new Dictionary <GraphGrammarNode, List <GraphGrammarNode> >();
            Dictionary <GraphGrammarNode, List <GraphGrammarNode> > childrenTable = new Dictionary <GraphGrammarNode, List <GraphGrammarNode> >();

            foreach (var node in graphGrammar.Nodes)
            {
                parentsTable[node]  = node.Parents;
                childrenTable[node] = node.Children;
            }
            // Kahn's Algorithm
            // Array that record the removed edges.
            bool[,] _usedEdge = new bool[graphGrammar.Nodes.Count, graphGrammar.Nodes.Count];
            // Non-indegree queue.
            Queue <GraphGrammarNode> nonIndegree = new Queue <GraphGrammarNode>();

            // Push non-indegree node to queue.
            foreach (var node in graphGrammar.Nodes.FindAll(x => parentsTable[x].Count == 0 &&
                                                            // children can not be node itself.
                                                            (!childrenTable[x].Exists(p => p.Ordering == x.Ordering))))
            {
                nonIndegree.Enqueue(node);
            }

            // Bfs.
            while (nonIndegree.Count > 0)
            {
                // Pop.
                GraphGrammarNode popNode = nonIndegree.Dequeue();
                // Remove the edge between this node and children node.
                foreach (var childNode in childrenTable[popNode])
                {
                    // Remove edge.
                    _usedEdge[popNode.Ordering - 1, childNode.Ordering - 1] = true;
                    // Check this child if it is non-indegree or not.
                    bool hasInput = false;
                    foreach (var parentNode in parentsTable[childNode])
                    {
                        if (!_usedEdge[parentNode.Ordering - 1, childNode.Ordering - 1])
                        {
                            hasInput = true;
                            break;
                        }
                    }
                    // If it is non-indegree then push it.
                    if (!hasInput)
                    {
                        nonIndegree.Enqueue(childNode);
                    }
                }
            }
            // Return false when any edge exist. It represents that this is a cyclic link.
            foreach (var node in graphGrammar.Nodes)
            {
                foreach (var childNode in childrenTable[node])
                {
                    if (!_usedEdge[node.Ordering - 1, childNode.Ordering - 1])
                    {
                        return(false);
                    }
                }
            }
            // Otherwise, this is not cyclic link.
            return(true);
        }
Пример #18
0
 // No 4. IsolatedConnection.
 private static bool ValidateIsolatedConnection(MissionRule rule, GraphGrammar graphGrammar)
 {
     return(!(graphGrammar.Connections.Where(c => c.StartpointStickyOn == null || c.EndpointStickyOn == null).Any()));
 }