All you need to do is a breadth-first search. Essentially
Dijkstra's Algorithm, but with the modification that when it adds a node to the visited set, if it's an air space, the algorithm can terminate right there since it knows it's found the nearest free space. (So it's Dijkstra's goal-path algorithm, only where any and all open spaces are valid goals).
In my implementation, I'll be using a temporary ds_grid to contain the distances of each cell from the center. I'm also using a ds_map to store the visited nodes since that will make it faster when checking if a node has been visited or not (O(log n) instead of O(n) like a list would be).
var visited, dists, Q, xx, yy, found, tdist, dist, cdist, tx, ty, cx, cy;
Q=ds_queue_create();
visited=ds_map_create();
dists=ds_grid_create(global.width, global.height);
ds_grid_clear(dists, -1);
ds_queue_enqueue(Q, global.width/2);
ds_queue_enqueue(Q, global.height/2);
ds_grid_set(dists, global.width/2, global.height/2, 0);
found=false;
while (!ds_queue_empty(Q)) {
xx=ds_queue_dequeue(Q);
yy=ds_queue_dequeue(Q);
dist=ds_grid_get(dists, xx, yy);
cdist=global.width*global.height+128;
cx=-1;
cy=-1;
if (ds_grid_get(global.dungeon, xx, yy)==dt_air) {
found=true;
cx=xx;
cy=yy;
break;
}
for (tx=-1; tx<=1; tx+=1) {
for (ty=-1; ty<=1; ty+=1) {
if (ty==0 && tx==0) { continue; }
if (xx+tx<0 || yy+ty<0 || xx+tx>=global.width || yy+ty>=global.height) { continue; }
if (ds_map_exists(visited, string(xx+tx)+"|"+string(yy+ty))) {
tdist=ds_grid_get(dists, xx+tx, yy+ty);
tdist=min(tdist, cdist+1);
if (tdist<0 || tdist==cdist+1) {
ds_grid_set(dists, xx+tx, yy+ty, tdist);
}
if (tdist<cdist) {
cdist=tdist;
cx=xx+tx;
cy=yy+ty;
}
}
}
}
ds_map_add(visited, string(xx)+"|"+string(yy), 0);
if (cx!=-1 && cy!=-1) {
ds_queue_enqueue(Q, cx);
ds_queue_enqueue(Q, cy);
}
}
ds_queue_destroy(Q);
ds_map_destroy(visited);
ds_grid_destroy(dists);
if (found) {
ret=ds_list_create();
ds_list_add(ret, cx);
ds_list_add(ret, cy);
return ret;
}
else { return -1; }It returns -1 if no air spaces were found or a 2-element ds_list containing the (x, y) position
in the ds_grid of the nearest air space.
-IMP