Exemple #1
0
        private List <int> RetracePath(AbstractNode startNode, AbstractNode endNode, bool retracePath)
        {
            if (!limitPrevious)
            {
                previousAbstractNodes.Clear();
            }

            List <int> path = new List <int>();

            if (retracePath)
            {
                AbstractNode currentNode = endNode;
                if (!limitPrevious)
                {
                    previousAbstractNodes.Add(currentNode);// visual
                }
                path.Add(currentNode.worldAreaIndex);
                path.Add(currentNode.sector);

                while (currentNode != startNode)
                {// if sector OR worldArea dont match, its a new one
                    if (path[path.Count - 1] != currentNode.sector || path[path.Count - 2] != currentNode.worldAreaIndex)
                    {
                        path.Add(currentNode.worldAreaIndex);
                        path.Add(currentNode.sector);
                    }

                    if (!limitPrevious)
                    {
                        previousAbstractNodes.Add(currentNode);// visual
                    }
                    currentNode = currentNode.parent;
                }

                if (path[path.Count - 1] != currentNode.sector)
                {
                    if (!limitPrevious)
                    {
                        previousAbstractNodes.Add(currentNode); // visual
                    }
                    path.Add(currentNode.worldAreaIndex);
                    path.Add(currentNode.sector);
                }
            }
            else
            {
                path.Add(0);
                AbstractNode currentNode = endNode;

                while (currentNode != startNode)
                {
                    if (currentNode.connections.ContainsKey(currentNode.parent))
                    {
                        path[0] += currentNode.connections[currentNode.parent];
                    }
                    else
                    {
                        path[0] += 1;
                    }

                    currentNode = currentNode.parent;
                }
            }


            return(path);
        }
Exemple #2
0
        // find path on higher level between start and goal/destination
        public List <List <int> > FindPaths(Dictionary <IntVector2, Tile> startingPoints, Tile destinationTile, WorldArea destinationArea)
        {
            multiSectorNodes = new List <AbstractNode>();

            int maxLevelAmount = worldData.pathfinder.maxLevelAmount;

            if (maxLevelAmount == 0)
            {
                if (worldData.pathfinder.worldIsMultiLayered)
                {
                    Debug.Log("Invalid search: A  Multi Layerd world cannot find paths with no Levels Of Abstraction ");
                    return(null);
                }
                else
                {
                    maxLevelAmount = 1;
                }
            }
            // adding all the start/destination nodes per level.
            for (int i = 0; i < maxLevelAmount; i++)
            {
                foreach (IntVector2 key in startingPoints.Keys)
                {
                    Tile startTile = startingPoints[key];

                    startNodeSector      = worldData.multiLevelSectorManager.GetSectorOfTile(i, startTile, worldData.worldAreas[key.x]);
                    startMultiSectorNode = worldData.multiLevelSectorManager.CreateAbstractNodeInSector(startNodeSector, startTile, worldData.worldAreas[key.x]);

                    worldData.multiLevelSectorManager.ConnectNodeInSector(startNodeSector, startMultiSectorNode, worldData.worldAreas[key.x]);//, new List<HigherNode>());
                    multiSectorNodes.Add(startMultiSectorNode);
                }

                // create temporary highlevel node on the start node
                // calculate its distance to the other high level nodes in the same sector, build connections between them
                destinationNodeSector      = worldData.multiLevelSectorManager.GetSectorOfTile(i, destinationTile, destinationArea);
                destinationMultiSectorNode = worldData.multiLevelSectorManager.CreateAbstractNodeInSector(destinationNodeSector, destinationTile, destinationArea);
                worldData.multiLevelSectorManager.ConnectNodeInSector(destinationNodeSector, destinationMultiSectorNode, destinationArea);

                multiSectorNodes.Add(destinationMultiSectorNode);
            }

            bool nextStep = false;

            AbstractNode start;
            AbstractNode destination;

            previousNodesStartingPointCount = startingPoints.Count;
            sectorIndexesAllLowerPaths.Clear();


            for (int j = 0; j < startingPoints.Count; j++) // for each starting point
            {
                for (int i = multiSectorNodes.Count - 1; i > -1; i -= startingPoints.Count + 1)
                {
                    nextStep = false;
                    int level = i / (startingPoints.Count + 1);

                    start       = multiSectorNodes[i - (j + 1)];
                    destination = multiSectorNodes[i];

                    if (start.sector == destination.sector)// starting point == destination
                    {
                        if (worldData.pathfinder.maxLevelAmount == 0)
                        {
                            AddToPath(new List <int> {
                                start.worldAreaIndex, start.sector
                            });
                            nextStep = true;
                        }
                        else
                        {
                            foreach (AbstractNode sectorNode in destination.connections.Keys)
                            {
                                if (sectorNode == start) // direct connection in sector
                                {
                                    if (level != 0)      // go to the next layer
                                    {
                                        nextStep = true;
                                    }
                                    else // level = 0, our goal is right next to us

                                    {
                                        AddToPath(new List <int> {
                                            start.worldAreaIndex, start.sector
                                        });
                                    }

                                    break;
                                }
                            }
                        }
                    }

                    //validSectorsFound
                    if (!nextStep)
                    {
                        if (level != 0) // we have to search the path between them, using A-star on the high level network
                        {
                            List <int> sectorIndexes = null;

                            if (validSectorsFound.Count == 0)
                            {
                                sectorIndexes = SearchHighLevelPath(start, destination, true);
                            }
                            else
                            {
                                sectorIndexes = SearchHighLevelPath(start, destination, validSectorsFound, true);
                            }


                            if (sectorIndexes == null)
                            {
                                Debug.Log("indexes ARE null,  no Path  on this hierachal Level: " + level);
                            }
                            else
                            {
                                validSectorsFound.Clear();
                                for (int k = 0; k < sectorIndexes.Count; k += 2)
                                {
                                    foreach (int[] list in worldData.multiLevelSectorManager.GetLowerSectorsFromHigher(level, sectorIndexes[k + 1], worldData.worldAreas[sectorIndexes[k]]))
                                    {
                                        foreach (int lowerIndex in list)
                                        {
                                            validSectorsFound.Add(new IntVector2(sectorIndexes[k], lowerIndex), false);
                                        }
                                    }
                                }
                            }
                        }
                        else // lowest level reached
                        {
                            List <int> sectorIndexes = null;

                            if (validSectorsFound.Count == 0)
                            {
                                sectorIndexes = SearchHighLevelPath(start, destination, true);
                            }
                            else
                            {
                                sectorIndexes = SearchHighLevelPath(start, destination, validSectorsFound, true);
                            }

                            validSectorsFound.Clear();

                            if (sectorIndexes != null)
                            {
                                AddToPath(sectorIndexes);
                            }
                        }
                    }
                }
            }

            return(sectorIndexesAllLowerPaths);
        }
        // cacluate distances to other high level nodes
        public void ConnectNodeInSector(MultiLevelSector sector, AbstractNode sectorNode, WorldArea area)
        {
            int maxNodes = sector.worldAreaNodes.Count + sector.sectorNodesOnEdge[0].Count + sector.sectorNodesOnEdge[1].Count + sector.sectorNodesOnEdge[2].Count + sector.sectorNodesOnEdge[3].Count;

            //Debug.Log("lowlevel sector ConnectNodeInSector " + maxNodes);

            // 2 sectorNodes on same location, connect them
            if (area.tileSectorNodeConnections[sector.level][sectorNode.tileConnection].Count > 1 && area.tileSectorNodeConnections[sector.level].ContainsKey(sectorNode.tileConnection))
            {
                maxNodes--;
                manager.ConnectSectorNodes(area.tileSectorNodeConnections[sector.level][sectorNode.tileConnection][0], area.tileSectorNodeConnections[sector.level][sectorNode.tileConnection][1], 0);
            }

            openSet.Clear();
            closedSet.Clear();

            openSet.Add(sectorNode.tileConnection);
            openSet[0].integrationValue = 0;

            // Debug.Log("max nodes " + maxNodes);
            while (openSet.Count > 0 && maxNodes != 0)
            {
                Tile currentNode = openSet[0];

                foreach (Tile neighbour in manager.worldData.tileManager.GetAllNeighboursForSectorNodeSearch(currentNode, area))
                {
                    //Debug.Log("neighbur");
                    if (!openSet.Contains(neighbour))
                    {
                        openSet.Add(neighbour);

                        // if true, there is a higher node here
                        if (neighbour.hasAbstractNodeConnection)//.higherLevelNodeIndex.Count > 0)
                        {
                            //Debug.Log("found connection");
                            //Get all HigherNodes on this Lower Node  & connect them
                            List <AbstractNode> neighbourSectorNodes = area.tileSectorNodeConnections[sector.level][neighbour]; // GetHigherLevelNodeList(neighbour, sector);
                            manager.ConnectSectorNodes(sectorNode, neighbourSectorNodes, neighbour.integrationValue / 10);      // 10 times scaling   //more accurate but slower/ Mathf.FloorToInt((neighbour.totalPathCost / 10f) + 0.5f)
                            maxNodes -= neighbourSectorNodes.Count;
                        }
                    }
                }

                closedSet.Add(currentNode);
                openSet.Remove(currentNode);
            }


            //Debug.Log("sectorNode connections " + sectorNode.connections.Count);



            // reset
            foreach (Tile tile in openSet)
            {
                tile.integrationValue = manager.worldData.tileManager.tileResetIntegrationValue;
            }

            foreach (Tile tile in closedSet)
            {
                tile.integrationValue = manager.worldData.tileManager.tileResetIntegrationValue;
            }
        }