Skip to content

Instantly share code, notes, and snippets.

@Langerz82
Created April 23, 2020 08:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Langerz82/570cc1ad5431ad5ade0b661d8d7a2350 to your computer and use it in GitHub Desktop.
Save Langerz82/570cc1ad5431ad5ade0b661d8d7a2350 to your computer and use it in GitHub Desktop.
define(function() {
var AStar = (function () {
/**
* A* (A-Star) algorithm for a path finder
* @originalauthor Andrea Giammarchi
* @revisedauthor Langerz82
* @license Proprietary.
*/
function diagonalSuccessors($N, $S, $E, $W, N, S, E, W, grid, rows, cols, result, i) {
if($N) {
$E && !grid[N][E] && (result[i++] = {x:E, y:N});
$W && !grid[N][W] && (result[i++] = {x:W, y:N});
}
if($S){
$E && !grid[S][E] && (result[i++] = {x:E, y:S});
$W && !grid[S][W] && (result[i++] = {x:W, y:S});
}
return result;
}
function diagonalSuccessorsFree($N, $S, $E, $W, N, S, E, W, grid, rows, cols, result, i) {
$N = N > -1;
$S = S < rows;
$E = E < cols;
$W = W > -1;
if($E) {
$N && !grid[N][E] && (result[i++] = {x:E, y:N});
$S && !grid[S][E] && (result[i++] = {x:E, y:S});
}
if($W) {
$N && !grid[N][W] && (result[i++] = {x:W, y:N});
$S && !grid[S][W] && (result[i++] = {x:W, y:S});
}
return result;
}
function nothingToDo($N, $S, $E, $W, N, S, E, W, grid, rows, cols, result, i) {
return result;
}
function successors(find, x, y, grid, rows, cols){
var result = [],
i = 0;
var
Ny = (y - 1),
X1 = (x % 1 == 0) ? x : Math.floor(x),
X2 = (x % 1 == 0) ? x : Math.ceil(x),
Sy = (y + 1),
Wx = (x - 1),
Y1 = (y % 1 == 0) ? y : Math.floor(y),
Y2 = (y % 1 == 0) ? y : Math.ceil(y),
Ex = (x + 1);
var $N, $S, $E, $W;
if ((y % 1 == 0) && (x % 1 == 0))
{
$N = Ny >= 0 && !grid[Ny][x];
$S = Sy <= (rows-1) && !grid[Sy][x];
$E = Ex <= (cols-1) && !grid[y][Ex];
$W = Wx >= 0 && !grid[y][Wx];
}
else
{
$N = Ny >= 0 && !grid[Ny][X1] && Ny >= 0 && !grid[Ny][X2];
$S = Sy <= (rows-1) && !grid[Sy][X1] && Sy <= (rows-1) && !grid[Sy][X2];
$E = Ex <= (cols-1) && !grid[Y1][Ex] && Ex <= (cols-1) && !grid[Y2][Wx];
$W = Wx >= 0 && !grid[Y1][Wx] && Wx >= 0 && !grid[Y2][Wx];
}
$N && (result[i++] = {x:x, y:Ny});
$E && (result[i++] = {x:Ex, y:y});
$S && (result[i++] = {x:x, y:Sy});
$W && (result[i++] = {x:Wx, y:y});
return find($N, $S, $E, $W, Ny, Sy, Ex, Wx, grid, rows, cols, result, i);
}
function diagonal(start, end, f1, f2) {
return f2(f1(start.x - end.x), f1(start.y - end.y));
}
function euclidean(start, end, f1, f2) {
var
x = start.x - end.x,
y = start.y - end.y
;
return f2(x * x + y * y);
}
function manhattan(start, end, f1, f2) {
return f1(start.x - end.x) + f1(start.y - end.y);
}
function AStar(grid, start, end, f) {
var
cols = grid[0].length,
rows = grid.length,
limit = (cols * rows),
f1 = Math.abs,
f2 = Math.max,
list = {},
result = [],
open = [{x:start[0], y:start[1], rx:start[0], ry:start[1], f:0, g:0, v:start[0] + start[1]*cols}],
length = 1,
adj, distance, find, i, j, max, min, current, next
;
end2 = {x:end[0], y:end[1], rx:end[0], ry:end[1], v:end[0] + end[1]*cols};
switch (f) {
case "Diagonal":
find = diagonalSuccessors;
case "DiagonalFree":
distance = diagonal;
break;
case "Euclidean":
find = diagonalSuccessors;
case "EuclideanFree":
f2 = Math.sqrt;
distance = euclidean;
break;
default:
distance = manhattan;
find = nothingToDo;
break;
}
find || (find = diagonalSuccessorsFree);
do {
max = limit;
min = 0;
for(i = 0; i < length; ++i) {
if((f = open[i].f) < max) {
max = f;
min = i;
}
};
current = open.splice(min, 1)[0];
if (current.v != end2.v) {
--length;
next = successors(find, current.x, current.y, grid, rows, cols);
for(i = 0, j = next.length; i < j; ++i){
(adj = next[i]).p = current;
adj.f = adj.g = 0;
adj.v = adj.x + adj.y * cols;
if(!(adj.v in list)){
adj.f = (adj.g = current.g + distance(adj, current, f1, f2)) + distance(adj, end, f1, f2);
open[length++] = adj;
list[adj.v] = 1;
}
}
} else {
i = length = 0;
do {
result[i++] = [current.rx, current.ry];
} while (current = current.p);
result.reverse();
}
} while (length);
log.error(JSON.stringify(result));
/*for (var i=3; i < (result.length-1); ++i)
{
if ((Math.abs(result[i-2][0] - result[i][0]) >= 2 && Math.abs(result[i-2][1] - result[i][1]) == 0) ||
(Math.abs(result[i-2][1] - result[i][1]) >= 2 && Math.abs(result[i-2][0] - result[i][0]) == 0))
result.splice(--i,1);
}*/
return [];
}
return {AStar};
}());
return AStar;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment