예제 #1
0
 public PathFindingVertex(PathFindingNode s, PathFindingNode e)
 {
     START = s;
     END = e;
 }
예제 #2
0
    //Pathfinding tattico: costruisce il percorso a costo minimo con A* con costi delle connessioni che tengono conto della mappa di influenza
    public List<PathFindingVertex> GetPath(Graph graph, int start, int goal)
    {
        PathFindingNode startNode = new PathFindingNode (start, 0, EstimateFrom(start,goal));

        PathFindingNode current = new PathFindingNode(-1,0,0);

        //Inizializza lista nodi chiusi (già visitati) e aperti (da visitare)
        PathFindingList open = new PathFindingList();
        PathFindingList closed = new PathFindingList();

        open.AddNode(startNode);

        //Itera tutti i nodi da visitare
        while (open.Length() > 0) {

            current = open.SmallestElement();

            //Se il nodo corrente da visitare è l'obiettivo, termina iterazione
            if (current.ID == goal){
                break;
            }

            List<Vertex> connections = graph.GetVertices(current.ID);

            //Itera tutte le connessioni che partono dal nodo corrente
            foreach (Vertex connection in connections){

                Node end = connection.END;
                float endCost = current.costSoFar + connection.Cost;
                float endHeuristic;
                PathFindingNode endRecord;

                //Se il nodo al termine della connessione è tra i chiusi....
                if (closed.Contains(end)){

                    //Record corrispondente al nodo terminale nella lista dei visitati
                    endRecord = closed.Find(end);

                    /*Se è stato trovato un percorso migliore verso il nodo terminale
                    rispetto a quello già registrato tra gli aperti...*/
                    if (endRecord!=null && endRecord.costSoFar > endCost) {

                        //Rimuove il nodo dai chiusi
                        closed.RemoveNode(endRecord);

                        //Usa i vecchi valori del nodo per ricalcolare l'euristica
                        endHeuristic = endRecord.estimatedTotalCost - endRecord.costSoFar;
                    }

                    else continue;

                }

                //Se invece il nodo terminale è tra gli aperti....
                else if (open.Contains(end)) {

                    //Record corrispondente al nodo terminale nella lista degli aperti
                    endRecord = open.Find(end);

                    /*Se è stato trovato un percorso migliore verso il nodo terminale
                    rispetto a quello già registrato tra gli aperti....*/
                    if (endRecord.costSoFar > endCost) {

                        //Uso i vecchi valori del nodo per ricalcolare l'euristica
                        endHeuristic = endRecord.estimatedTotalCost - endRecord.costSoFar;
                    }

                    else continue;

                }

                /*Se invece il nodo terminale non è nè tra i chiusi nè tra gli aperti, crea un nuovo record
                 * ed effettua la stima della distanza dall'obiettivo*/
                else {

                    endRecord = new PathFindingNode(end.ID);

                    endHeuristic = EstimateFrom(end.ID,goal);

                }

                //Aggiorno record con nuovi valori
                endRecord.costSoFar = endCost;
                endRecord.connection = new PathFindingVertex(current,endRecord);
                endRecord.estimatedTotalCost = endCost + endHeuristic;

                if (!open.Contains(end))
                    open.AddNode(endRecord);

            }

            open.RemoveNode(current);
            closed.AddNode(current);

        }

        //Se il nodo corrente non è l'obiettivo, il nodo non è stato trovato e restituisce null
        if (current.ID!=goal)
            return null;

        //Altrimenti ricostruisce il percorso all'indietro partendo dal nodo corrente.
        else{

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

            while (current.ID!=start){

                path.Add(current.connection);
                current = current.connection.START;

            }

            path.Reverse();

            return path;
        }
    }
예제 #3
0
 public void AddNode(PathFindingNode node)
 {
     list.Add (node);
 }
예제 #4
0
 public void RemoveNode(PathFindingNode node)
 {
     list.Remove(node);
 }
예제 #5
0
    public override List <PathFindingNode> FindPath(List <List <PathFindingNode> > grid, PathFindingNode origin, PathFindingNode destination)
    {
        _openNodes.Add(origin);
        while (_openNodes.Count != 0)
        {
            PathFindingNode node = _openNodes[_openNodes.Count - 1];
            if (node == destination)
            {
                List <PathFindingNode> path = GetPath(node);
                CleanValues(grid);
                return(path);
            }

            for (int i = 0; i < node.Adjacents.Count; i++)
            {
                PathFindingNode actualAdjacentNode = node.Adjacents[i];
                bool            isOnClosed         = false;
                bool            isOnOpen           = false;
                for (int j = 0; j < _closedNodes.Count; j++)
                {
                    if (actualAdjacentNode == _closedNodes[j])
                    {
                        isOnClosed = true;
                        j          = _closedNodes.Count;
                    }
                }
                for (int j = 0; j < _openNodes.Count; j++)
                {
                    if (actualAdjacentNode == _openNodes[j])
                    {
                        isOnOpen = true;
                        j        = _openNodes.Count;
                    }
                }

                if (!isOnClosed && !isOnOpen)
                {
                    actualAdjacentNode.Parent = node;
                    _openNodes.Add(actualAdjacentNode);
                }
            }
            _openNodes.Remove(node);
            _closedNodes.Add(node);
        }
        return(null);
    }
예제 #6
0
        protected void ChaseSection(MazeSection destination)
        {
            //Localizações dos elementos
            var currLocation = this.Ghost.CurrentLocation;
            var currEndLocation = destination;
            var prevLocation = this.Ghost.PreviousLocation;

            //Essa é a seção inicial,
            PathFindingNode currNode = new PathFindingNode();
            currNode.h = 0;
            currNode.g = 0;
            currNode.parent = null;
            currNode.location = currLocation;

            List<PathFindingNode> closedSet = new List<PathFindingNode>();
            List<PathFindingNode> openSet = new List<PathFindingNode>();

            closedSet.Add(currNode);

            do
            {
                //Percorrendo as opções de caminho que temos
                List<MazeSection> opcoes = new List<MazeSection> { currLocation.W, currLocation.N, currLocation.E, currLocation.S };

                foreach (var o in opcoes)
                {

                    if (o != null)
                    {

                        //A seção precisa estar ativa e não ser a seção anteriormente visitada
                        if (o.Allowed && (prevLocation == null || o.ID != prevLocation.ID))
                        {
                            //Seção não deve existir na lista de seções fechadas
                            if (!closedSet.Any(x => x.location.ID == o.ID))
                            {
                                //...nem na lista de seções abertas
                                if (!openSet.Any(x => x.location.ID == o.ID))
                                {

                                    PathFindingNode node = new PathFindingNode();
                                    node.location = o;
                                    node.parent = currNode;
                                    node.h = this.Heuristics(node.location, currEndLocation); //heuristica manhattan

                                    //Ok, esse nó participará do teste
                                    openSet.Add(node);
                                }
                            }
                        }
                    }
                }

                if (openSet.Count == 0)
                {
                    break;
                }

                //Procuramos o melhor nó localizado (custo)
                var minNode = openSet[0];

                foreach (var m in openSet)
                {
                    if (m.h < minNode.h)
                    {
                        minNode = m;
                    }
                }

                currNode = minNode;
                currLocation = currNode.location;

                //Removendo da lista de nós abertos para pesquisa e incluíndo na lista de nós proibidos
                openSet.Remove(minNode);
                closedSet.Add(currNode);

            } while (currNode.location.ID != currEndLocation.ID);

            if (currNode.location.ID == currEndLocation.ID)
            {
                ///*

                LinkedList<PathFindingNode> path = new LinkedList<PathFindingNode>();
                PathFindingNode lastPathNode = currNode;
                MazeSection nextSectionToMove = null;
                MazeSection mySection = this.Ghost.CurrentLocation;

                while (lastPathNode != null)
                {
                    path.AddFirst(lastPathNode);
                    lastPathNode = lastPathNode.parent;
                }

                nextSectionToMove = path.Count > 1 ? path.First.Next.Value.location : path.First.Value.location;

                if (nextSectionToMove.ID == mySection.N.ID)
                {
                    this.nextDirection = EnumDirections.North;
                }
                else if (nextSectionToMove == mySection.S)
                {
                    this.nextDirection = EnumDirections.South;
                }
                else if (nextSectionToMove == mySection.E)
                {
                    this.nextDirection = EnumDirections.East;
                }
                else if (nextSectionToMove == mySection.W)
                {
                    this.nextDirection = EnumDirections.West;
                }

                this.Ghost.GoTo(this.nextDirection);
                //*/
            }
        }
예제 #7
0
 //DEBUG///////////////////////////////////////////////////////////
 public override void FindPathToDebug(List <List <PathFindingNode> > grid, PathFindingNode origin,
                                      PathFindingNode destination)
 {
     _debugModeEnabled = true;
     StartCoroutine(FindPathDebug(grid, origin, destination));
 }
    /// <summary>
    /// Calculates the shortest Path from the startNode to the endNode.
    /// </summary>
    /// <param name="startNode">The node this path is supposed to start on</param>
    /// <param name="endNode">The node this path is supposed to end on</param>
    /// <returns></returns>
    public override Path FindPath(PathFindingNode startNode, PathFindingNode endNode)
    {
        List <NetworkNode>        openSet   = new List <NetworkNode>();        // List of nodes that need to be checked
        HashSet <PathFindingNode> closedSet = new HashSet <PathFindingNode>(); // List of nodes that have been visited

        openSet.Add(new NetworkNode(startNode));                               // Add the first entry

        while (openSet.Count > 0)
        {
            // Move entry to closedSet
            NetworkNode currentNetworkNode = openSet[0];
            openSet.RemoveAt(0);
            closedSet.Add(currentNetworkNode.PathFindingNode);

            // Loop over all neighbors
            foreach (PathFindingNode neighbor in currentNetworkNode.PathFindingNode.NeighborNodes)
            {
                if (!neighbor)
                {
                    continue;
                }
                // Check if the end of this path is in the neighborhood
                if (neighbor.Equals(endNode))
                {
                    int         endNetworkNodeGCost = currentNetworkNode.GCost + GetDistance(currentNetworkNode.PathFindingNode, neighbor);
                    int         endNetworkNodeHCost = GetDistance(neighbor, endNode);
                    NetworkNode endNetworkNode      = new NetworkNode(neighbor, endNetworkNodeHCost, endNetworkNodeGCost)
                    {
                        Parent = currentNetworkNode
                    };
                    return(RetracePath(startNode, endNetworkNode));
                }

                // Check if the current neighbor is supposed to be visited
                bool isWalkable    = neighbor.IsTraversable();
                bool isInClosedSet = closedSet.Contains(neighbor);
                if (!isWalkable || isInClosedSet)
                {
                    continue;                                               // Continue if it is not supposed to be visited
                }
                // Calculate heuristics
                int gCost = currentNetworkNode.GCost + GetDistance(currentNetworkNode.PathFindingNode, neighbor);
                int hCost = GetDistance(neighbor, endNode);

                // Update heuristics values on the neighbor or create a new instance
                NetworkNode neighborNode = openSet.Find(x => x.PathFindingNode.Equals(neighbor));
                if (neighborNode != null)
                {
                    if (gCost < neighborNode.GCost)
                    {
                        neighborNode.GCost  = gCost;
                        neighborNode.HCost  = hCost;
                        neighborNode.Parent = currentNetworkNode;
                    }
                }
                else
                {
                    neighborNode = new NetworkNode(neighbor, hCost, gCost)
                    {
                        Parent = currentNetworkNode
                    };
                    openSet.Add(neighborNode);
                }
                openSet.Sort();                 // Sort ascending on fCost
            }
        }
        return(null);        // There is no path from startNode to endNode
    }
예제 #9
0
 public ScheduledMover(WaypointMoverController waypointMover, Vector3 intersectionVec3, PathFindingNode from,
                       PathFindingNode to)
 {
     _waypointMover    = waypointMover;
     _intersectionVec3 = intersectionVec3;
     _from             = from;
     _to = to;
 }
예제 #10
0
    protected void FindPath()
    {
        path.Clear();
        openNodes.Clear();
        closedNodes.Clear();

        Vector2Int goal    = (Vector2Int)FullWallTilemap.WorldToCell(player.transform.position);
        Vector2Int nodePos = (Vector2Int)FullWallTilemap.WorldToCell(transform.position);

        openNodes.Add(new PathFindingNode(nodePos, null, 0f, (goal - nodePos).magnitude));
        PathFindingNode?node    = null;
        bool            success = false;

        while (openNodes.Count > 0)
        {
            node = openNodes.PopBestNode();
            if (node.Value == goal)
            {
                success = true;
                break;
            }
            closedNodes.Add(node.Value);
            float goalDistance = (goal - node.Value).magnitude;
            foreach (Vector2Int direction in adjacents)
            {
                Vector2Int      newNodePos  = node.Value + direction;
                Vector3Int      newNodePos3 = new Vector3Int(newNodePos.x, newNodePos.y, 0);
                PathFindingNode newNode     = new PathFindingNode(newNodePos, node, node.Distance + 1, goalDistance);
                if (!closedNodes.Contains(newNodePos))
                {
                    if (FullWallTilemap.HasTile(newNodePos3) || HalfWallTilemap.HasTile(newNodePos3))
                    {
                        closedNodes.Add(newNodePos);
                    }
                    else
                    {
                        openNodes.Add(newNode);
                    }
                }
            }

            foreach (Vector2Int direction in diagonals)
            {
                Vector2Int      newNodePos      = node.Value + direction;
                Vector3Int      newNodePos3     = new Vector3Int(newNodePos.x, newNodePos.y, 0);
                PathFindingNode newNode         = new PathFindingNode(newNodePos, node, node.Distance + 1.41421356f, goalDistance);
                Vector3Int[]    cornerAdjacents = new Vector3Int[] {
                    new Vector3Int(newNodePos.x, node.Value.y, 0),
                    new Vector3Int(node.Value.x, newNodePos.y, 0)
                };
                if (!closedNodes.Contains(newNodePos))
                {
                    if (FullWallTilemap.HasTile(newNodePos3) || HalfWallTilemap.HasTile(newNodePos3) ||
                        FullWallTilemap.HasTile(cornerAdjacents[0]) || HalfWallTilemap.HasTile(cornerAdjacents[0]) ||
                        FullWallTilemap.HasTile(cornerAdjacents[1]) || HalfWallTilemap.HasTile(cornerAdjacents[1]))
                    {
                        closedNodes.Add(newNodePos);
                    }
                    else
                    {
                        openNodes.Add(newNode);
                    }
                }
            }
        }

        if (success)
        {
            while (node != null)
            {
                path.AddFirst((Vector2)FullWallTilemap.CellToWorld(new Vector3Int(node.Value.x, node.Value.y, 0)) + new Vector2(0.5f, 0.5f));
                node = node.Parent;
            }
        }
    }
예제 #11
0
    private bool CanReachNode(PathFindingNode a, PathFindingNode b)
    {
        bool hit = Physics.Linecast(a.Position, b.Position);

        return(!hit);
    }