-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize pathfinding #4637
base: master
Are you sure you want to change the base?
Optimize pathfinding #4637
Conversation
I did a quick test but this PR doesn't work, the monsters walk randomly and move away from the target slowly until they disappear from sight, and the summons don't have any type of movement. |
This comment was marked as outdated.
This comment was marked as outdated.
The new constexpr update seems to have destroyed this edit: I think changing int_fast32_t, ect is the problem. |
Can someone test the last commit. I think this should fix the pathfinding again. I also tried to fix the reaction speed when a monster first targets a player that has changed floors. @floki21uu Keep in mind you will need to have updated to the new constexpr position methods. |
std::sqrt is running almost 3x faster than std::hypot |
FP math is orders of magnitude slower than integer math. I don't see why you changed the
How did you measure it? |
I used time measurements strictly around the sqrt operation. I checked 1sqm-100sqm paths. I also created a small project just as a frame of reference using only the sqrt and hypot so there wasn't any additional bloatware. All instances were 2-3x faster from what I saw. I also tried different data types with integers giving the best results with sqrt being 3-4x faster. With that being said, I am not aware of tools, ect that can be used so its just based on time measurements. Someone with more experience may be able to look into it more. As for what I changed to double I can revert some of the code back to using integers. I didn't realize I should leave out the heuristic from the g (walk) cost and place it in its own variable. However, I do think leaving the heuristic as a double is best as from everything I read about path finding the more precise the better for the heuristic. In other words I am still learning and did some things that weren't needed. I also didn't know it was done using order of magnitude which I am assuming is referencing the extra cost for fields and destroying creatures Edit: I have tried moving back to integers for the walk cost function and the result is that because of how big of a difference the integers are compared to the result of our heuristic the algorithm can no longer find the path properly. So keeping the walk cost as a float or double seems to be the best option and we will have to modify the extra costs to work properly assuming they dont. I do think it works as expected though because I have just divided the values by 10. We also may be able to just *10 the dx and dy before running sqrt on it as well. |
destroyed what? |
The path finding stopped working with @ranisalt's constexpr position change. I did revert the datatype changes in this repo for pathmatching so I think it should be working properly again. |
Lets get this added peeps |
When you made this using the constexpr positions you had problems. It seems there were problems with that commit that have since been fixed, have you tried using the current version of the constexpr positions? |
Yes, and the fixes did solve the problem. The system works as it is so I will push updates to get it ready to merge with tfs master when people have tested it and say it can be merged once its updated to lastest commits. I can't keep doing micro updates. |
Feel free to update this, once |
return; | ||
} | ||
|
||
if (lastPathUpdate - OTSYS_TIME() > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (lastPathUpdate - OTSYS_TIME() > 0) { | |
if (lastPathUpdate > OTSYS_TIME()) { |
Shouldn't this be called nextPathUpdate
? It's always set to a date in the future.
} | ||
|
||
std::list<Creature*> newList; | ||
newList.resize(followedByCreatures.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please do not use std::list
, and the way you use it doesn't make much sense, you resize it adding empty values, push to it and then clear it and never use any intermediate state, looks like it could be completely removed
creature->forceUpdatePath(); | ||
} | ||
++it; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use a range for here?
return nullptr; | ||
std::sort(nodes.begin(), nodes.end(), [](AStarNode* left, AStarNode* right) { return left->f > right->f; }); | ||
AStarNode* retNode = nodes.back(); | ||
nodes.pop_back(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use nth_element
to partially sort, bubbling the best element to the end (using the same comparison function) so it only performs N operations rather than N log N
++closedNodes; | ||
} | ||
uint16_t dx = std::abs(p1.x - p2.x); | ||
uint16_t dy = std::abs(p1.y - p2.y); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You must either use getX
and getY
or static cast both to a signed integer, otherwise they will overflow since both numbers are unsigned.
|
||
static int_fast32_t getMapWalkCost(AStarNode* node, const Position& neighborPos); | ||
static int_fast32_t getTileWalkCost(const Creature& creature, const Tile* tile); | ||
static double calculateHeuristic(const Position& p1, const Position& p2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function does not need to be member of AStarNode
, it can be a free function within map.cpp
Pull Request Prelude
Changes Proposed
This is a overhaul of when and how pathfinding is done. I did attempt this before but I closed the pull request due to congestion. I believe all problems from the original pull request have been fixed.
This will change the pathfinding to work as A* algorithm rather than djikstra's.
It will also add more pathfinding calls as needed fixing monster moving around slowly due to 1 second pathfinding interval.
This PR also includes separation of when creatures will update their path from creatures onThink.
Lastly it includes some fixes for bugs which were not detectable until pathfinding was able to be called more often.
Issues addressed:
Might fix: #4617