///scr_findPath(startNode, endNode, ds_list<obj_node>, max range)
var startNode = argument0;
var endNode = argument1;
var pathNodes = argument2;
var maxRange = argument3;
var openSet = ds_list_create(); //create open set
var closedSet = ds_list_create(); //create closed set
ds_list_add(openSet,startNode); //add starting node to open set
//while there are nodes in the open set, do the algorithm
//otherwise return false (path not found)
while(ds_list_size(openSet) > 0)
{
//here we get the node with the lowest F cost (G cost + H cost)
//from all the nodes in the open set
//and remove it from the open set and
//add it to the closed set
var currentNode = ds_list_find_value(openSet,0);
var index = 0;
for (var i=0;i<ds_list_size(openSet);++i)
{
var tmpNode = ds_list_find_value(openSet,i);
if (tmpNode.fCost < currentNode.fCost)
{
currentNode = tmpNode;
index = i;
}
}
ds_list_delete(openSet,index);
ds_list_add(closedSet,currentNode);
//if our current node (from the open set) is our end node
//return true (path found) and retrace path from end to start
//and add nodes to the list
if (currentNode == endNode)
{
ds_list_destroy(openSet);
ds_list_destroy(closedSet);
var currentNode = endNode;
while (currentNode != startNode)
{
ds_list_insert(pathNodes,0,currentNode);
currentNode = currentNode.parent;
}
ds_list_insert(pathNodes,0,startNode);
return true;
}
//get neighbour nodes from current node
var neighbours = scr_getNeighbours(currentNode,maxRange);
//for each neighbour
for (var i=0;i<ds_list_size(neighbours);++i)
{
var neighbourNode = ds_list_find_value(neighbours,i);
//if the neighbour nodes is in the closed set
//set the boolean closedSetContains to true, else false
var closedSetContains = false;
for (var j=0;j<ds_list_size(closedSet);++j)
{
var tmpNode = ds_list_find_value(closedSet,j);
if (tmpNode == neighbourNode)
{
closedSetContains = true;
break;
}
}
//if the neighbour node isn't in the closed set
if (!closedSetContains)
{
//calculates new distance for the node
var newMovementCost = currentNode.gCost +
scr_getDistance(currentNode,neighbourNode);
//if the neighbour nodes is in the open set
//set the boolean openSetContains to true, else false
var openSetContains = false;
for (var j=0;j<ds_list_size(openSet);++j)
{
var tmpNode = ds_list_find_value(openSet,j);
if (tmpNode == neighbourNode)
{
openSetContains = true;
break;
}
}
//if our new calculated movement cost is smaller than
//the neighbour node G cost, OR the neighbour node is not
//in the open set, then
if (newMovementCost < neighbourNode.gCost || !openSetContains)
{
//recalculate all the costs
neighbourNode.gCost = newMovementCost;
neighbourNode.hCost = scr_getDistance(neighbourNode,endNode);
neighbourNode.fCost = neighbourNode.gCost + neighbourNode.hCost;
//set the parent to our current node (so we can retrace later)
neighbourNode.parent = currentNode;
//and finally, if the neighbour node is not in the open set
//add it to the open set
if (!openSetContains)
ds_list_add(openSet,neighbourNode);
}
}
}
//destroying temporary ds_list otherwise we will get a memory leak
ds_list_destroy(neighbours);
}
//destroying temporary ds_lists otherwise we will get a memory leak
ds_list_destroy(openSet);
ds_list_destroy(closedSet);
//if our code doesn't return in the while statement,
//a path has not been found - return false;
return false;