0

Hi I'm having a few problems with my A* pathfinding algorithm. The algorithm does successfully execute, however in a debug environment it executes in about 10 seconds, in release it will still take 2-3 seconds. This speed is way too slow. I suspect this is either due to a bug in the code, or the fact it isn't well optimised.

The map that pathfinding is being used on is a 30*30 grid, with each square being 10 unites away from one another.

I have noticed when running the algorithm, that when the open and closed list are searched to see if a node already exists, the node already stored in one of the lists always has a lower cost, so there is no updating of nodes. Not sure if this is normal or not. Also, I am not sure if quicksort is a good sort to be using in this situation.

Here is the code:

The coords struture used as a node: struct coords { int x; int z; coords* parent; int cost; int score; };

The sort compare function:

bool decompare(coords* o1, coords* o2)
{
return (o1->score < o2->score);
}

The main pathfind loop:

    while (!goalFound) //While goal has not been found
    {
        current = openList.front(); //Retrieve current state from the open list
        openList.pop_front();

        for (int count = 1; count < 5; count++)
        {
            if (!goalFound)
            {
                coords* possibleState = new (coords); //Allocate new possible state
                found = false;
                if (count == 1)
                {
                    possibleState->x = current->x;
                    possibleState->z = current->z + 10; //North
                }

                else if (count == 2)
                {
                    possibleState->x = current->x + 10; //East
                    possibleState->z = current->z;
                }

                else if (count == 3)
                {
                    possibleState->x = current->x; //South
                    possibleState->z = current->z - 10;
                }

                else if (count == 4)
                {
                    possibleState->x = current->x - 10; //West
                    possibleState->z = current->z;
                }

                if (possibleState->x >-1 && possibleState->x <291 && possibleState->z >-1 && possibleState->z < 291) //If possible state is in game boundary
                {
                    possibleState->cost = current->cost + 10; //Add 10 to current state to get cost of new possible state
                    int a = (possibleState->x / 10) + (30 * (possibleState->z / 10)); //get index of map
                    if (map[a] != wallTest) //Test possible state is not inside a wall
                    {
                        p = openList.begin();
                        while (p != openList.end() && !found) //Search open list to see if possible state already exists
                        {
                            if (possibleState->x == (*p)->x && possibleState->z == (*p)->z) //Already exists
                            {
                                found = true;
                                if (!possibleState->cost >= (*p)->cost)  //Test possible state has lower cost
                                {
                                    (*p)->parent = current; //Update existing with attributes of possible state
                                    a = abs((*p)->x - goalState->x);
                                    b = abs((*p)->z - goalState->z);
                                    (*p)->cost = possibleState->cost;
                                    (*p)->score = (possibleState->cost) + ((a)+(b));

                                }

                            }

                            else
                            {
                                found = false; //Set not found
                            }
                            p++;
                        }
                        q = closedList.begin();
                        while (q != closedList.end())
                        {
                            if (possibleState->x == (*q)->x && possibleState->z == (*q)->z)
                            {
                                found = true;
                                int a = (*q)->cost;
                                if (possibleState->cost < a) //Test if on closed list
                                {
                                    (*q)->parent = current;
                                    a = abs((*q)->x - goalState->x);
                                    b = abs((*q)->z - goalState->z);
                                    (*q)->cost = possibleState->cost;
                                    (*q)->score = (possibleState->cost) + ((a)+(b)); //If cost lower push onto open list
                                    coords* newcoord;
                                    newcoord->x = (*q)->x;
                                    newcoord->z = (*q)->z;
                                    newcoord->score = (*q)->score;
                                    newcoord->cost = (*q)->cost;
                                    openList.push_back(newcoord);
                                    closedList.erase(q);
                                }
                            }
                            q++;
                        }

                        if (!found) //If not found on either list
                        {
                            possibleState->parent = current; //Push onto open list
                            a = abs((possibleState)->x / 10 - goalState->x / 10);
                            b = abs((possibleState)->z / 10 - goalState->z / 10);
                            (possibleState)->score = (possibleState->cost) + ((a)+(b));
                            openList.push_back(possibleState);
                        }
                        sort(openList.begin(), openList.end(), decompare); // Sort the open list by score
                    }

                    if (possibleState->x == goalState->x && possibleState->z == goalState->z) //if goal found
                    {
                        openList.push_back(possibleState);
                        node = possibleState;
                        goalFound = true;

                        while (node != 0)
                        {
                            wayPoints.push_back(*node);
                            node = node->parent;
                            wayCount = wayPoints.size() - 1;
                        }
                    }
                }
            }
        }

        closedList.push_back(current);
    }
    player->setWayPoints(wayPoints);
    wayPoints.clear();
    player->setMoved(2);
    player->setPath(1);
    openList.clear();
    closedList.clear();
    goalFound = false;
    player->setNewPath(1);
    return true;
}
else {
    return false;
}

}

Are there any bugs that need to be sorted in this code that anyone can see? Or is it just important optimizations that need making? Thanks

user3427689
  • 167
  • 1
  • 2
  • 12
  • Why are you allocating `coords` on the heap? Also `newcoord` is corrupting random memory. You should probably use an heap rather than a sorted vector. – Mooing Duck Feb 09 '15 at 23:24
  • Thanks for the answer, I'm aware that the solution is nowhere near memory safe at this time ha, would using a heap greatly increase the speed, compared to using the sort algorithm? Just trying to find exactly what is bottle necking this the most. – user3427689 Feb 09 '15 at 23:37
  • I have no idea what the bottlenecks are, I just glanced over the code and made a few observations. However, the dynamic memory and the `std::sort` are potentially bottlenecks. Replace the `std::vector` with a `std::priority_queue` and you _might_ see a speedup. Or not. – Mooing Duck Feb 09 '15 at 23:40
  • Depending on your IDE, you should try to use a profiler, such as this one for Visual Studio: https://msdn.microsoft.com/en-us/magazine/cc337887.aspx – Mooing Duck Feb 09 '15 at 23:41
  • Sadly I can't use a priority queue as I need to be able to iterate through it – user3427689 Feb 10 '15 at 01:07
  • Why do you need to iterate? Does it need to iterate "in order"? Could you use a `std::vector` and keep it heaped via [make_heap](http://en.cppreference.com/w/cpp/algorithm/make_heap) and [push_heap](http://en.cppreference.com/w/cpp/algorithm/push_heap) and similar? – Mooing Duck Feb 10 '15 at 17:29

0 Answers0