Add penalties for turns to avoid staircasing in A* algorithm#150
Add penalties for turns to avoid staircasing in A* algorithm#150ivanmayes wants to merge 4 commits intoqiao:masterfrom
Conversation
Can you review and fix the above issue ? @ivanmayes |
|
Nice work! 👏 It actually solved the problem I had! PS: The same logic could be applied for |
|
Thanks so much for the fix. By itself, it works surprisingly well. I'm trying to recreate the path finding of an old school game and added some tweaks to improve the behavior to match up with the expected result like @cuixiping pointed out. In particular, when two moves are tied, this game's path finding prefers:
I implemented a tiebreaker to be able to replicate these behaviors. I also added a momentum to paths, so that 'straighter' paths receive a small reward. The 'solution,' if we can call it that, wasn't particularly pretty. I ended up doing the following:
I'm not sure if there's a way to coerce A* into taking the optimal path on the first iteration. I kept running into the problem where the algorithm would get tunnel-visioned on one particular path and completely ignore exploring the alternatives. A* will forsake considering a more optimal route if the route it's going down is 'optimal enough'. But many times that 'optimal enough' route isn't the one we want, and it often looks a lot like what @cuixiping posted. On the bright side, I don't think there should be too much of a loss in performance with an extra iteration (hopefully). If your use case is a very large grid, you might see a bit of a slowdown. Happy travels, fellow internet wanderer 👋 |
|
@MajesticGoodness I wrote a A* demo of finding shortest and least turns path years ago, and I may not be able to find the old code. |
I'm sorry to hear you haven't been able to locate your old source code. Sadly, I have none of my own to share. I'm merely creating a bot for this particular game, and I needed to replicate its path finding so that my bot would know in advance which moves would be advantageous. The game is very dead and no one plays anymore 😔. My hope is to at least populate it with bots so that the few people who do still play have a slightly better experience. If you are curious about the game, you can check out some game play footage here. Take care! |
|
I found a demo file, you can take a look. |
| * (defaults to manhattan). | ||
| * @param {number} opt.weight Weight to apply to the heuristic to allow for | ||
| * suboptimal paths, in order to speed up the search. | ||
| * @param {number} opt.avoidStarcasing Add penalties to discourage turning and |
There was a problem hiding this comment.
| * @param {number} opt.avoidStarcasing Add penalties to discourage turning and | |
| * @param {boolean} opt.avoidStaircase Add penalties to discourage turning and |
| lastDirection = node.parent === undefined? undefined : { x : node.x - node.parent.x, y : node.y - node.parent.y }; | ||
| var turned = lastDirection === undefined? 0 : lastDirection.x !== x - node.x || lastDirection.y !== y - node.y; |
There was a problem hiding this comment.
| lastDirection = node.parent === undefined? undefined : { x : node.x - node.parent.x, y : node.y - node.parent.y }; | |
| var turned = lastDirection === undefined? 0 : lastDirection.x !== x - node.x || lastDirection.y !== y - node.y; | |
| lastDirection = node.parent === undefined ? undefined : { x: node.x - node.parent.x, y: node.y - node.parent.y }; | |
| var turned = lastDirection === undefined ? 0 : lastDirection.x !== x - node.x || lastDirection.y !== y - node.y; |
| <label class="option_label">Weight</label> <br> | ||
| <br> | ||
| <input type="checkbox" class="avoid_staircase"> | ||
| <label class="option_label">Avoid staircasing</label> <br> |
There was a problem hiding this comment.
| <label class="option_label">Avoid staircasing</label> <br> | |
| <label class="option_label">Avoid staircase</label> <br> |


Refactored this from #32 into the
srcand added a configuration to set what the turn penalty is to enforce even more straight paths.