Exemple #1
0
void find_path(NavGridLocation from, NavGridLocation to)
{
    int grid_size = gs.grid.get_width() * gs.grid.get_height();
    int from_id = hash_location(from);

    std::vector<AiNode> nodes (grid_size);
    for (int i = 0; i < nodes.size(); i++) {
        AiNode& node = nodes[i];
        node.id = i;
        node.visited = false;
        node.prev_node = nullptr;
        node.true_score = std::numeric_limits<float>::max();
        node.guess_score = std::numeric_limits<float>::max();
        node.pq_node = nullptr;
    }
    nodes[from_id].true_score = 0.f;
    nodes[from_id].guess_score = heuristic_cost(unhash_location(from_id), to);
    PriorityQueue<AiNode*> pq;
    nodes[from_id].pq_node = pq.enqueue(&nodes[from_id], -nodes[from_id].guess_score);
    update_prev(nodes);
    while (!pq.is_empty()) {
        AiNode* current = pq.get_front();
        pq.dequeue();
        current->pq_node = nullptr;
        current->visited = true;
        if (current->id == hash_location(to)) {
            break;
        }
        for (const NavGridLocation& adj : gs.grid.get_adjacent(unhash_location(current->id))) {
            AiNode* adj_node = &nodes[hash_location(adj)];
            if (adj_node->visited) 
                continue;
            float new_score = current->true_score + 1;
            if (new_score >= adj_node->true_score)
                continue;
            adj_node->prev_node = current;
            adj_node->true_score = new_score;
            adj_node->guess_score = new_score + heuristic_cost(unhash_location(adj_node->id), to);
            if (adj_node->pq_node) {
                pq.update(adj_node->pq_node, -adj_node->guess_score);
            } else {
                adj_node->pq_node = pq.enqueue(adj_node, -adj_node->guess_score);
            }
        }
    }
    update_prev(nodes);
    update_path(nodes, to);
}
Exemple #2
0
list_t* astar(directed_graph_node_t* p_source,
              directed_graph_node_t* p_target,
              directed_graph_weight_function_t* p_weight_function,
              unordered_map_t* p_location_map_arg)
{
    search_state_t            state;

    list_t*                   p_list;
    heap_t*                   p_open_set;
    unordered_set_t*          p_closed_set;
    unordered_map_t*          p_parent_map;
    unordered_map_t*          p_cost_map;
    unordered_map_t*          p_location_map;
    directed_graph_node_t*    p_current;
    directed_graph_node_t*    p_child;
    unordered_set_iterator_t* p_child_iterator;

    /* Cannot pack a double into a void*, so use these simple structures. */
    weight_t*                 p_weight;
    weight_t*                 p_weight_f;
    list_t*                   p_weight_list;
    size_t                    i;

    if (!p_source)           return NULL;
    if (!p_target)           return NULL;
    if (!p_weight_function)  return NULL;
    if (!p_location_map_arg) return NULL;

    search_state_t_alloc(&state);

    if (!search_state_t_is_ready(&state)) 
    {
        search_state_t_free(&state);
        return NULL;
    }

    p_weight = malloc(sizeof(*p_weight));
    p_weight->weight = 0.0;

    p_open_set    = state.p_open_set;
    p_closed_set  = state.p_closed_set;
    p_weight_list = state.p_weight_list;
    p_cost_map    = state.p_cost_map;
    p_parent_map  = state.p_parent_map;

    p_location_map = p_location_map_arg;

    p_weight = malloc(sizeof(*p_weight));
    p_weight->weight = 0.0;

    heap_t_add(p_open_set, p_source, p_weight);
    unordered_map_t_put(p_parent_map, p_source, NULL);
    unordered_map_t_put(p_cost_map, p_source, p_weight);
    list_t_push_back(p_weight_list, p_weight);

    while (heap_t_size(p_open_set) > 0)
    {
        p_current = heap_t_extract_min(p_open_set);

        if (equals_function(p_current, p_target)) 
        {
            p_list = traceback_path(p_target, p_parent_map);
            search_state_t_free(&state);
            return p_list;
        }

        unordered_set_t_add(p_closed_set, p_current);

        p_child_iterator = 
                unordered_set_iterator_t_alloc(
                    directed_graph_node_t_children_set(p_current));

        while (unordered_set_iterator_t_has_next(p_child_iterator)) 
        {
            unordered_set_iterator_t_next(p_child_iterator, &p_child);

            if (unordered_set_t_contains(p_closed_set, p_child)) {
                continue;
            }

            double tmp_cost = 
                ((weight_t*) unordered_map_t_get(p_cost_map, 
                                                 p_current))->weight;

            tmp_cost += *directed_graph_weight_function_t_get(p_weight_function, 
                                                              p_current, 
                                                              p_child);

            double estimate = heuristic_cost(p_location_map, p_child, p_target);

            if (!unordered_map_t_contains_key(p_parent_map, p_child)) 
            {
                /* Prepare the distance so far to 'p_child'. */
                p_weight = malloc(sizeof(*p_weight));
                p_weight->weight = tmp_cost;

                /* Prepare the f-distance of 'p_child'. */
                p_weight_f = malloc(sizeof(*p_weight_f));
                p_weight_f->weight = tmp_cost + estimate;

                heap_t_add(p_open_set, p_child, p_weight_f);
                unordered_map_t_put(p_parent_map, p_child, p_current);
                unordered_map_t_put(p_cost_map, p_child, p_weight);

                /**********************************************************
                * Store the weight objects so that we can free them after *
                * the search.                                             *
                **********************************************************/
                list_t_push_back(p_weight_list, p_weight);
                list_t_push_back(p_weight_list, p_weight_f);
            }
            else if (tmp_cost < 
                    ((weight_t*) unordered_map_t_get(p_cost_map, 
                                                     p_child))->weight)
            {
                /* Prepare the distance so far to 'p_child'. */
                p_weight = malloc(sizeof(*p_weight));
                p_weight->weight = tmp_cost;

                /* Prepare the f-distance of 'p_child'. */
                p_weight_f = malloc(sizeof(*p_weight));
                p_weight_f->weight = tmp_cost + estimate;

                heap_t_decrease_key(p_open_set, p_child, p_weight_f);
                unordered_map_t_put(p_parent_map, p_child, p_current);
                unordered_map_t_put(p_cost_map, p_child, p_weight);

                /**********************************************************
                * Store the weight objects so that we can free them after *
                * the search.                                             *
                **********************************************************/
                list_t_push_back(p_weight_list, p_weight);
                list_t_push_back(p_weight_list, p_weight_f);
            }
        }

        unordered_set_iterator_t_free(p_child_iterator);
    }

    /* Once here, return a empty path in order to denote the fact that the 
       target node is not reachable from source node. */
    p_list = list_t_alloc(10);
    search_state_t_free(&state);

    /* Deallocate the weights. */
    for (i = 0; i < list_t_size(p_weight_list); ++i) 
    {
        free(list_t_get(p_weight_list, i));
    }

    return p_list;
}