- 8
- Posts
- 7
- Years
- Seen Nov 22, 2022
THIS RESEARCH IS UNDER DEVELOPMENT, SO IS NORMAL THAT IS FULL OF BUGS
Hi, I am quite new in the world of disassembly but I am working in some research fields:
This is one of my recent ones: The use of Artificial Intelligence to perform the applymovements automatically and online in-game.
It contains an implementation of a Dijkstra algorithm with informed heuristics (A*) that can make easy some Applimovements in the scripts:
https://github.com/J2M2/pokeemerald/tree/path_planner
![[PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding [PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding](https://whackahack.com/uploads/images/4bb840f9e7b151bb732a3a44f7f44183.png)
![[PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding [PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding](https://whackahack.com/uploads/images/5f904ffb09689b0ff1a44c489e318187.gif)
Adding an obstacle in the map editor changes the trajectory without change the script!
![[PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding [PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding](https://whackahack.com/uploads/images/836e0e60d6f6d5d98896afa703b87cbe.gif)
Features:
- A new command for scripting moveobjecttopos(ObjectID, X, Y, facing)
- Shortest path computation between the initial and final position
- The NPC's facing at the end of the movement can be chosen
- Obstacle and field objects avoidance
- Works in terrains with different elevations and bridges
- Easy to customize between Uniform Cost Search (Dijkstra), Greedy Best First Search, and A*
- Easy to execute, just a line of code
- Able to solve mazes
Usage:
Instead of use applymovement OBJECT_ID, sequence_of_movement you can just use moveobjecttopos OBJECT_ID, X, Y, FACING
With:
OBJECT_ID: The ID of the object (same as applymovement)
X and Y: the goal position
FACING: The orientation of the ObjectEvent at the end of the movement (0: down, 1: up, 2: left, 3: right)
![[PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding [PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding](https://i.imgur.com/1yVD67x.png)
It finds the shortest path between the current position of the NPC (or player) and the goal position and is able to cross bridges and use elevations
![[PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding [PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding](https://i.ibb.co/t2ZbWyS/ezgif-com-gif-maker-2.gif)
It also can plan the movement of the player
Known issues:
- It is new research, so the code can be full of bugs and memory errors (use under this warning!!)
- In open worlds may experiment overflow of memory and collapse (working in solution)
- For long movements (far away from the screen) it is possible that doesn't take into account some minisprites
- Maximum path of 200 steps
- Sometimes report problems with waitstate 0 when two consecutive movements are performed
Contributing:
- Help is needed in order to make the algorithm more robust and efficient in-memory consumption (for a detailed explanation of the code see below)
- Feel free to use and find and report bugs. I think is the best way to contribute.
- I am more experienced with C++, MATLAB, Python language code for search algorithms
Spoiler:
The intuition behind the path-planning given solution is the search algorithm based on Graph Search to find the path between an initial and final node.
The best balance between an optimal solution (that warrant always choose the shortest path) and a greedy solution (that prioritize find the best solution available and don't waste time in to find a better one) is the A* algorithm.
This algorithm can be found here https://github.com/J2M2/pokeemerald/blob/path_planner/src/movement_path_planning.c#L42 and follows the following structure:
Code:
function searchPath(object, x, y, facing) /* returns a solution or failure */
node ← a node with State derived from object and path-cost=0
frontier ← a priority queue by Path-Cost with node as the only element
explored ← an empty set
loop do
if Empty(frontier) then return failure
node ← Pop(frontier) /* chooses the lowest-cost node in frontier*/
if problem.Goal-Test(node.State) then return Solution(node)
add node.State to explored
for each action in possible_movements(DOWN, UP, LEFT, RIGHT) do
if not isMoveNotPossible(node, action)
child ← Child-Node( node, action)
if child.State is neither in explored nor frontier then
f(child) ← cost function for the child / *See below in the f(node) definition */
frontier ← Insert(child, frontier, f(child))
else if child.State is in frontier with higher Path-Cost then
replace that frontier node with child
The cost is the core of the optimization. Because it gives the priority to choose a new node or another one.
The A* algorithm evaluates nodes by combining the path cost g
f
where h
For vanilla Dijkstra (UCS) this h
The Greedy Best First Seach, don't use an accumulated path cost of the node g
The heuristic is usually the linear distance between the goal and the current node, this value is decreasing at the same time we are closer and closer to the goal node.
In Pokemon Emerald diagonal movement is not performed by the NPCs so the euclidean distance is not the best option.
However, the Manhattan (L1) distance could be a better alternative:
![[PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding [PokeCommunity.com] Applymovement vs A* Algorithm for Pathfinding](https://iq.opengenus.org/content/images/2018/12/distance.jpg)
See https://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html for more information about heuristics.
The constant HEUR_WEIGHT can be modified to change the weight that the heuristic is having, allowing you to use UCS when its value is 0, and Greedy Best-First when the value is much greater than 1. For standard, A* just use 1.
The nodes are defined in https://github.com/J2M2/pokeemerald/blob/path_planner/include/movement_path_planning.h#L37 and contain:
state: integer to represent the position of the node in the matrix (flatten into 1D) which use to do comparisons.
coords: coordinates x,y.
cost: integer, cost so far of the node
elevation: integer, current elevation (z coordinate)
path: an array of movements, the path so far until the node.
The https://github.com/J2M2/pokeemerald/blob/path_planner/include/movement_path_planning.h also contains some auxiliary functions to use the priority queue, the set, and the heuristic.
Last edited: