Exemplo n.º 1
0
        public MoveState(Character character, Pathfinder.GoalEvaluator goalEvaluator, List <Tile> path, State nextState = null)
            : base("Move", character, nextState)
        {
            hasReachedDestination = goalEvaluator;
            this.path             = path;

            DebugLog("created with path length: {0}", path.Count);
        }
Exemplo n.º 2
0
    public Path_AStar(World world, Tile tileStart, Pathfinder.GoalEvaluator isGoal, Pathfinder.PathfindingHeuristic costEstimate)
    {
        float startTime = Time.realtimeSinceStartup;

        // Set path to empty Queue so that there always is something to check count on
        path = new Queue <Tile>();

        // if tileEnd is null, then we are simply scanning for the nearest objectType.
        // We can do this by ignoring the heuristic component of AStar, which basically
        // just turns this into an over-engineered Dijkstra's algo

        // Check to see if we have a valid tile graph
        if (world.tileGraph == null)
        {
            world.tileGraph = new Path_TileGraph(world);
        }

        // Check to see if we have a valid tile graph
        if (world.roomGraph == null)
        {
            world.roomGraph = new Path_RoomGraph(world);
        }

        // A dictionary of all valid, walkable nodes.
        Dictionary <Tile, Path_Node <Tile> > nodes = world.tileGraph.nodes;

        // Make sure our start/end tiles are in the list of nodes!
        if (nodes.ContainsKey(tileStart) == false)
        {
            UnityDebugger.Debugger.LogError("Path_AStar", "The starting tile isn't in the list of nodes!");

            return;
        }

        Path_Node <Tile> start = nodes[tileStart];

        /*
         * Mostly following this pseusocode:
         * https://en.wikipedia.org/wiki/A*_search_algorithm
         */
        HashSet <Path_Node <Tile> > closedSet = new HashSet <Path_Node <Tile> >();

        /*
         * List<Path_Node<Tile>> openSet = new List<Path_Node<Tile>>();
         *        openSet.Add( start );
         */

        PathfindingPriorityQueue <Path_Node <Tile> > openSet = new PathfindingPriorityQueue <Path_Node <Tile> >();

        openSet.Enqueue(start, 0);

        Dictionary <Path_Node <Tile>, Path_Node <Tile> > came_From = new Dictionary <Path_Node <Tile>, Path_Node <Tile> >();

        Dictionary <Path_Node <Tile>, float> g_score = new Dictionary <Path_Node <Tile>, float>();

        g_score[start] = 0;

        Dictionary <Path_Node <Tile>, float> f_score = new Dictionary <Path_Node <Tile>, float>();

        f_score[start] = costEstimate(start.data);

        while (openSet.Count > 0)
        {
            Path_Node <Tile> current = openSet.Dequeue();

            // Check to see if we are there.
            if (isGoal(current.data))
            {
                Duration = Time.realtimeSinceStartup - startTime;
                Reconstruct_path(came_From, current);
                return;
            }

            closedSet.Add(current);

            foreach (Path_Edge <Tile> edge_neighbor in current.edges)
            {
                Path_Node <Tile> neighbor = edge_neighbor.node;

                if (closedSet.Contains(neighbor))
                {
                    continue; // ignore this already completed neighbor
                }

                float pathfinding_cost_to_neighbor = neighbor.data.PathfindingCost * Dist_between(current, neighbor);

                float tentative_g_score = g_score[current] + pathfinding_cost_to_neighbor;

                if (openSet.Contains(neighbor) && tentative_g_score >= g_score[neighbor])
                {
                    continue;
                }

                came_From[neighbor] = current;
                g_score[neighbor]   = tentative_g_score;
                f_score[neighbor]   = g_score[neighbor] + costEstimate(neighbor.data);

                openSet.EnqueueOrUpdate(neighbor, f_score[neighbor]);
            } // foreach neighbour
        }     // while

        // If we reached here, it means that we've burned through the entire
        // openSet without ever reaching a point where current == goal.
        // This happens when there is no path from start to goal
        // (so there's a wall or missing floor or something).

        // We don't have a failure state, maybe? It's just that the
        // path list will be null.
        Duration = Time.realtimeSinceStartup - startTime;
    }