function jpsPathfind(grid, start, end, allowDiag = true) {
const rows = grid.length;
const cols = grid[0].length;
const h = allowDiag ? HEURISTICS.octile : HEURISTICS.manhattan;
const rootDirections = allowDiag ? DIRS_8 : DIRS_4;
const gScore = Matrix(rows, cols, Infinity);
const prev = new Map();
const visited = new Set();
const open = PriorityQueue("f");
function blocked(r, c) {
return !inBounds(rows, cols, r, c) || grid[r][c] === WALL;
}
function jump(r, c, dr, dc, gCost) {
const nr = r + dr;
const nc = c + dc;
if (blocked(nr, nc)) return null;
const step = dr !== 0 && dc !== 0 ? Math.SQRT2 : 1;
const ng = gCost + step;
if (nr === end[0] && nc === end[1]) return {
r: nr,
c: nc,
g: ng
};
visitNode(nr, nc);
if (!allowDiag) {
if (dr !== 0) {
if (blocked(nr, nc - 1) && !blocked(nr + dr, nc - 1) || blocked(nr, nc + 1) && !blocked(nr + dr, nc + 1)) {
return {
r: nr,
c: nc,
g: ng
};
}
} else if (blocked(nr - 1, nc) && !blocked(nr - 1, nc + dc) || blocked(nr + 1, nc) && !blocked(nr + 1, nc + dc)) {
return {
r: nr,
c: nc,
g: ng
};
}
if (blocked(nr + dr, nc + dc)) {
return {
r: nr,
c: nc,
g: ng
};
}
return jump(nr, nc, dr, dc, ng);
}
if (dr !== 0 && dc !== 0) {
if (!blocked(nr - dr, nc + dc) && blocked(nr - dr, nc) || !blocked(nr + dr, nc - dc) && blocked(nr, nc - dc)) {
return {
r: nr,
c: nc,
g: ng
};
}
const j1 = jump(nr, nc, dr, 0, ng);
if (j1) return {
r: nr,
c: nc,
g: ng
};
const j2 = jump(nr, nc, 0, dc, ng);
if (j2) return {
r: nr,
c: nc,
g: ng
};
} else if (dr !== 0) {
if (!blocked(nr + dr, nc + 1) && blocked(nr, nc + 1) || !blocked(nr + dr, nc - 1) && blocked(nr, nc - 1)) {
return {
r: nr,
c: nc,
g: ng
};
}
} else if (!blocked(nr + 1, nc + dc) && blocked(nr + 1, nc) || !blocked(nr - 1, nc + dc) && blocked(nr - 1, nc)) {
return {
r: nr,
c: nc,
g: ng
};
}
return jump(nr, nc, dr, dc, ng);
}
function neighborsWithPruning(r, c, parent) {
if (!parent) return rootDirections;
const dirs = [];
const __pattern1 = parent;
const pr = __pattern1[0];
const pc = __pattern1[1];
const dr = Math.sign(r - pr);
const dc = Math.sign(c - pc);
if (!allowDiag) {
return DIRS_4;
}
if (dr !== 0 && dc !== 0) {
dirs.push([dr, dc], [dr, 0], [0, dc]);
if (!blocked(r - dr, c + dc)) dirs.push([-dr, dc]);
if (!blocked(r + dr, c - dc)) dirs.push([dr, -dc]);
} else if (dr !== 0) {
dirs.push([dr, 0], [dr, 1], [dr, -1]);
} else {
dirs.push([0, dc], [1, dc], [-1, dc]);
}
return dirs;
}
gScore[start[0]][start[1]] = 0;
priorityQueuePush(open, {
f: h(start[0], start[1], end[0], end[1]),
r: start[0],
c: start[1],
parent: null
});
while (priorityQueueSize(open)) {
const __pattern2 = priorityQueuePop(open);
const r = __pattern2.r;
const c = __pattern2.c;
const parent = __pattern2.parent;
const currentKey = key(r, c);
if (visited.has(currentKey)) continue;
visited.add(currentKey);
visitNode(r, c);
if (r === end[0] && c === end[1]) {
reconstructPath(prev, start, end);
return;
}
for (const [dr, dc] of neighborsWithPruning(r, c, parent)) {
const jp = jump(r, c, dr, dc, gScore[r][c]);
if (!jp) continue;
const jumpKey = key(jp.r, jp.c);
const tentative = gScore[r][c] + Math.hypot(jp.r - r, jp.c - c);
if (tentative < gScore[jp.r][jp.c]) {
gScore[jp.r][jp.c] = tentative;
prev.set(jumpKey, [r, c]);
priorityQueuePush(open, {
f: tentative + h(jp.r, jp.c, end[0], end[1]),
r: jp.r,
c: jp.c,
parent: [r, c]
});
pushFrontier(jp.r, jp.c);
}
}
}
reportNoPath();
} def jpsPathfind(grid, start, end, ):
rows = grid.length
cols = grid[0].length
h = (HEURISTICS.octile if allowDiag else HEURISTICS.manhattan)
rootDirections = (DIRS_8 if allowDiag else DIRS_4)
gScore = Matrix(rows, cols, Infinity)
prev = Map()
visited = Set()
open = PriorityQueue("f")
def blocked(r, c):
return (not inBounds(rows, cols, r, c) or (grid[r][c] == WALL))
def jump(r, c, dr, dc, gCost):
nr = (r + dr)
nc = (c + dc)
if blocked(nr, nc):
return None
step = (Math.SQRT2 if ((dr != 0) and (dc != 0)) else 1)
ng = (gCost + step)
if ((nr == end[0]) and (nc == end[1])):
return {r: nr, c: nc, g: ng}
visitNode(nr, nc)
if not allowDiag:
if (dr != 0):
if ((blocked(nr, (nc - 1)) and not blocked((nr + dr), (nc - 1))) or (blocked(nr, (nc + 1)) and not blocked((nr + dr), (nc + 1)))):
return {r: nr, c: nc, g: ng}
elif ((blocked((nr - 1), nc) and not blocked((nr - 1), (nc + dc))) or (blocked((nr + 1), nc) and not blocked((nr + 1), (nc + dc)))):
return {r: nr, c: nc, g: ng}
if blocked((nr + dr), (nc + dc)):
return {r: nr, c: nc, g: ng}
return jump(nr, nc, dr, dc, ng)
if ((dr != 0) and (dc != 0)):
if ((not blocked((nr - dr), (nc + dc)) and blocked((nr - dr), nc)) or (not blocked((nr + dr), (nc - dc)) and blocked(nr, (nc - dc)))):
return {r: nr, c: nc, g: ng}
j1 = jump(nr, nc, dr, 0, ng)
if j1:
return {r: nr, c: nc, g: ng}
j2 = jump(nr, nc, 0, dc, ng)
if j2:
return {r: nr, c: nc, g: ng}
elif (dr != 0):
if ((not blocked((nr + dr), (nc + 1)) and blocked(nr, (nc + 1))) or (not blocked((nr + dr), (nc - 1)) and blocked(nr, (nc - 1)))):
return {r: nr, c: nc, g: ng}
else:
if ((not blocked((nr + 1), (nc + dc)) and blocked((nr + 1), nc)) or (not blocked((nr - 1), (nc + dc)) and blocked((nr - 1), nc))):
return {r: nr, c: nc, g: ng}
return jump(nr, nc, dr, dc, ng)
def neighborsWithPruning(r, c, parent):
if not parent:
return rootDirections
dirs = []
__pattern1 = parent
pr = __pattern1[0]
pc = __pattern1[1]
dr = sign((r - pr))
dc = sign((c - pc))
if not allowDiag:
return DIRS_4
if ((dr != 0) and (dc != 0)):
dirs.push([dr, dc])
if not blocked((r - dr), (c + dc)):
dirs.push([-dr, dc])
if not blocked((r + dr), (c - dc)):
dirs.push([dr, -dc])
elif (dr != 0):
dirs.push([dr, 0])
else:
dirs.push([0, dc])
return dirs
gScore[start[0]][start[1]] = 0
priorityQueuePush(open, {f: h(start[0], start[1], end[0], end[1]), r: start[0], c: start[1], parent: None})
while priorityQueueSize(open):
__pattern2 = priorityQueuePop(open)
r = __pattern2.r
c = __pattern2.c
parent = __pattern2.parent
currentKey = key(r, c)
if visited.has(currentKey):
continue
visited.add(currentKey)
visitNode(r, c)
if ((r == end[0]) and (c == end[1])):
reconstructPath(prev, start, end)
return
for dr, dc in neighborsWithPruning(r, c, parent):
jp = jump(r, c, dr, dc, gScore[r][c])
if not jp:
continue
jumpKey = key(jp.r, jp.c)
tentative = (gScore[r][c] + hypot((jp.r - r), (jp.c - c)))
if (tentative < gScore[jp.r][jp.c]):
gScore[jp.r][jp.c] = tentative
prev.set(jumpKey, [r, c])
priorityQueuePush(open, {f: (tentative + h(jp.r, jp.c, end[0], end[1])), r: jp.r, c: jp.c, parent: [r, c]})
pushFrontier(jp.r, jp.c)
reportNoPath() #include <vector>
#include <algorithm>
void jpsPathfind(int grid, int start, int end, int ) {
auto rows = grid.length;
auto cols = grid[0].length;
auto h = ((allowDiag) ? (HEURISTICS.octile) : (HEURISTICS.manhattan));
auto rootDirections = ((allowDiag) ? (DIRS_8) : (DIRS_4));
auto gScore = Matrix(rows, cols, Infinity);
auto prev = Map();
auto visited = Set();
auto open = PriorityQueue("f");
int blocked(int r, int c) {
return (!inBounds(rows, cols, r, c) || (grid[r][c] == WALL));
}
int jump(int r, int c, int dr, int dc, int gCost) {
auto nr = (r + dr);
auto nc = (c + dc);
if(blocked(nr, nc)) {
return null;
}
auto step = ((((dr != 0) && (dc != 0))) ? (Math.SQRT2) : (1));
auto ng = (gCost + step);
if(((nr == end[0]) && (nc == end[1]))) {
return {r: nr, c: nc, g: ng};
}
visitNode(nr, nc);
if(!allowDiag) {
if((dr != 0)) {
if(((blocked(nr, (nc - 1)) && !blocked((nr + dr), (nc - 1))) || (blocked(nr, (nc + 1)) && !blocked((nr + dr), (nc + 1))))) {
return {r: nr, c: nc, g: ng};
}
} else if(((blocked((nr - 1), nc) && !blocked((nr - 1), (nc + dc))) || (blocked((nr + 1), nc) && !blocked((nr + 1), (nc + dc))))) {
return {r: nr, c: nc, g: ng};
}
if(blocked((nr + dr), (nc + dc))) {
return {r: nr, c: nc, g: ng};
}
return jump(nr, nc, dr, dc, ng);
}
if(((dr != 0) && (dc != 0))) {
if(((!blocked((nr - dr), (nc + dc)) && blocked((nr - dr), nc)) || (!blocked((nr + dr), (nc - dc)) && blocked(nr, (nc - dc))))) {
return {r: nr, c: nc, g: ng};
}
auto j1 = jump(nr, nc, dr, 0, ng);
if(j1) {
return {r: nr, c: nc, g: ng};
}
auto j2 = jump(nr, nc, 0, dc, ng);
if(j2) {
return {r: nr, c: nc, g: ng};
}
} else if((dr != 0)) {
if(((!blocked((nr + dr), (nc + 1)) && blocked(nr, (nc + 1))) || (!blocked((nr + dr), (nc - 1)) && blocked(nr, (nc - 1))))) {
return {r: nr, c: nc, g: ng};
}
} else {
if(((!blocked((nr + 1), (nc + dc)) && blocked((nr + 1), nc)) || (!blocked((nr - 1), (nc + dc)) && blocked((nr - 1), nc)))) {
return {r: nr, c: nc, g: ng};
}
}
return jump(nr, nc, dr, dc, ng);
}
int neighborsWithPruning(int r, int c, int parent) {
if(!parent) {
return rootDirections;
}
auto dirs = [];
auto __pattern1 = parent;
auto pr = __pattern1[0];
auto pc = __pattern1[1];
auto dr = std::sign((r - pr));
auto dc = std::sign((c - pc));
if(!allowDiag) {
return DIRS_4;
}
if(((dr != 0) && (dc != 0))) {
dirs.push([dr, dc]);
if(!blocked((r - dr), (c + dc))) {
dirs.push([-dr, dc]);
}
if(!blocked((r + dr), (c - dc))) {
dirs.push([dr, -dc]);
}
} else if((dr != 0)) {
dirs.push([dr, 0]);
} else {
dirs.push([0, dc]);
}
return dirs;
}
gScore[start[0]][start[1]] = 0;
priorityQueuePush(open, {f: h(start[0], start[1], end[0], end[1]), r: start[0], c: start[1], parent: null});
while(priorityQueueSize(open)) {
auto __pattern2 = priorityQueuePop(open);
auto r = __pattern2.r;
auto c = __pattern2.c;
auto parent = __pattern2.parent;
auto currentKey = key(r, c);
if(visited.has(currentKey)) {
continue;
}
visited.add(currentKey);
visitNode(r, c);
if(((r == end[0]) && (c == end[1]))) {
reconstructPath(prev, start, end);
return;
}
for(auto& [dr, dc] : neighborsWithPruning(r, c, parent)) {
auto jp = jump(r, c, dr, dc, gScore[r][c]);
if(!jp) {
continue;
}
auto jumpKey = key(jp.r, jp.c);
auto tentative = (gScore[r][c] + std::hypot((jp.r - r), (jp.c - c)));
if((tentative < gScore[jp.r][jp.c])) {
gScore[jp.r][jp.c] = tentative;
prev.set(jumpKey, [r, c]);
priorityQueuePush(open, {f: (tentative + h(jp.r, jp.c, end[0], end[1])), r: jp.r, c: jp.c, parent: [r, c]});
pushFrontier(jp.r, jp.c);
}
}
}
reportNoPath();
} public void jpsPathfind(int grid, int start, int end, int ) {
var rows = grid.length;
var cols = grid[0].length;
var h = ((allowDiag) ? (HEURISTICS.octile) : (HEURISTICS.manhattan));
var rootDirections = ((allowDiag) ? (DIRS_8) : (DIRS_4));
var gScore = Matrix(rows, cols, Infinity);
var prev = Map();
var visited = Set();
var open = PriorityQueue("f");
int blocked(int r, int c) {
return (!inBounds(rows, cols, r, c) || (grid[r][c] == WALL));
}
int jump(int r, int c, int dr, int dc, int gCost) {
var nr = (r + dr);
var nc = (c + dc);
if(blocked(nr, nc)) {
return null;
}
var step = ((((dr != 0) && (dc != 0))) ? (Math.SQRT2) : (1));
var ng = (gCost + step);
if(((nr == end[0]) && (nc == end[1]))) {
return {r: nr, c: nc, g: ng};
}
visitNode(nr, nc);
if(!allowDiag) {
if((dr != 0)) {
if(((blocked(nr, (nc - 1)) && !blocked((nr + dr), (nc - 1))) || (blocked(nr, (nc + 1)) && !blocked((nr + dr), (nc + 1))))) {
return {r: nr, c: nc, g: ng};
}
} else if(((blocked((nr - 1), nc) && !blocked((nr - 1), (nc + dc))) || (blocked((nr + 1), nc) && !blocked((nr + 1), (nc + dc))))) {
return {r: nr, c: nc, g: ng};
}
if(blocked((nr + dr), (nc + dc))) {
return {r: nr, c: nc, g: ng};
}
return jump(nr, nc, dr, dc, ng);
}
if(((dr != 0) && (dc != 0))) {
if(((!blocked((nr - dr), (nc + dc)) && blocked((nr - dr), nc)) || (!blocked((nr + dr), (nc - dc)) && blocked(nr, (nc - dc))))) {
return {r: nr, c: nc, g: ng};
}
var j1 = jump(nr, nc, dr, 0, ng);
if(j1) {
return {r: nr, c: nc, g: ng};
}
var j2 = jump(nr, nc, 0, dc, ng);
if(j2) {
return {r: nr, c: nc, g: ng};
}
} else if((dr != 0)) {
if(((!blocked((nr + dr), (nc + 1)) && blocked(nr, (nc + 1))) || (!blocked((nr + dr), (nc - 1)) && blocked(nr, (nc - 1))))) {
return {r: nr, c: nc, g: ng};
}
} else {
if(((!blocked((nr + 1), (nc + dc)) && blocked((nr + 1), nc)) || (!blocked((nr - 1), (nc + dc)) && blocked((nr - 1), nc)))) {
return {r: nr, c: nc, g: ng};
}
}
return jump(nr, nc, dr, dc, ng);
}
int neighborsWithPruning(int r, int c, int parent) {
if(!parent) {
return rootDirections;
}
var dirs = [];
var __pattern1 = parent;
var pr = __pattern1[0];
var pc = __pattern1[1];
var dr = sign((r - pr));
var dc = sign((c - pc));
if(!allowDiag) {
return DIRS_4;
}
if(((dr != 0) && (dc != 0))) {
dirs.push([dr, dc]);
if(!blocked((r - dr), (c + dc))) {
dirs.push([-dr, dc]);
}
if(!blocked((r + dr), (c - dc))) {
dirs.push([dr, -dc]);
}
} else if((dr != 0)) {
dirs.push([dr, 0]);
} else {
dirs.push([0, dc]);
}
return dirs;
}
gScore[start[0]][start[1]] = 0;
priorityQueuePush(open, {f: h(start[0], start[1], end[0], end[1]), r: start[0], c: start[1], parent: null});
while(priorityQueueSize(open)) {
var __pattern2 = priorityQueuePop(open);
var r = __pattern2.r;
var c = __pattern2.c;
var parent = __pattern2.parent;
var currentKey = key(r, c);
if(visited.has(currentKey)) {
continue;
}
visited.add(currentKey);
visitNode(r, c);
if(((r == end[0]) && (c == end[1]))) {
reconstructPath(prev, start, end);
return;
}
foreach(var (dr, dc) in neighborsWithPruning(r, c, parent)) {
var jp = jump(r, c, dr, dc, gScore[r][c]);
if(!jp) {
continue;
}
var jumpKey = key(jp.r, jp.c);
var tentative = (gScore[r][c] + hypot((jp.r - r), (jp.c - c)));
if((tentative < gScore[jp.r][jp.c])) {
gScore[jp.r][jp.c] = tentative;
prev.set(jumpKey, [r, c]);
priorityQueuePush(open, {f: (tentative + h(jp.r, jp.c, end[0], end[1])), r: jp.r, c: jp.c, parent: [r, c]});
pushFrontier(jp.r, jp.c);
}
}
}
reportNoPath();
} #include <stdio.h>
void jpsPathfind(int grid, int start, int end, int ) {
var rows = grid.length;
var cols = grid[0].length;
var h = ((allowDiag) ? (HEURISTICS.octile) : (HEURISTICS.manhattan));
var rootDirections = ((allowDiag) ? (DIRS_8) : (DIRS_4));
var gScore = Matrix(rows, cols, Infinity);
var prev = Map();
var visited = Set();
var open = PriorityQueue("f");
int blocked(int r, int c) {
return (!inBounds(rows, cols, r, c) || (grid[r][c] == WALL));
}
int jump(int r, int c, int dr, int dc, int gCost) {
var nr = (r + dr);
var nc = (c + dc);
if(blocked(nr, nc)) {
return null;
}
var step = ((((dr != 0) && (dc != 0))) ? (Math.SQRT2) : (1));
var ng = (gCost + step);
if(((nr == end[0]) && (nc == end[1]))) {
return {r: nr, c: nc, g: ng};
}
visitNode(nr, nc);
if(!allowDiag) {
if((dr != 0)) {
if(((blocked(nr, (nc - 1)) && !blocked((nr + dr), (nc - 1))) || (blocked(nr, (nc + 1)) && !blocked((nr + dr), (nc + 1))))) {
return {r: nr, c: nc, g: ng};
}
} else if(((blocked((nr - 1), nc) && !blocked((nr - 1), (nc + dc))) || (blocked((nr + 1), nc) && !blocked((nr + 1), (nc + dc))))) {
return {r: nr, c: nc, g: ng};
}
if(blocked((nr + dr), (nc + dc))) {
return {r: nr, c: nc, g: ng};
}
return jump(nr, nc, dr, dc, ng);
}
if(((dr != 0) && (dc != 0))) {
if(((!blocked((nr - dr), (nc + dc)) && blocked((nr - dr), nc)) || (!blocked((nr + dr), (nc - dc)) && blocked(nr, (nc - dc))))) {
return {r: nr, c: nc, g: ng};
}
var j1 = jump(nr, nc, dr, 0, ng);
if(j1) {
return {r: nr, c: nc, g: ng};
}
var j2 = jump(nr, nc, 0, dc, ng);
if(j2) {
return {r: nr, c: nc, g: ng};
}
} else if((dr != 0)) {
if(((!blocked((nr + dr), (nc + 1)) && blocked(nr, (nc + 1))) || (!blocked((nr + dr), (nc - 1)) && blocked(nr, (nc - 1))))) {
return {r: nr, c: nc, g: ng};
}
} else {
if(((!blocked((nr + 1), (nc + dc)) && blocked((nr + 1), nc)) || (!blocked((nr - 1), (nc + dc)) && blocked((nr - 1), nc)))) {
return {r: nr, c: nc, g: ng};
}
}
return jump(nr, nc, dr, dc, ng);
}
int neighborsWithPruning(int r, int c, int parent) {
if(!parent) {
return rootDirections;
}
var dirs = [];
var __pattern1 = parent;
var pr = __pattern1[0];
var pc = __pattern1[1];
var dr = sign((r - pr));
var dc = sign((c - pc));
if(!allowDiag) {
return DIRS_4;
}
if(((dr != 0) && (dc != 0))) {
dirs.push([dr, dc]);
if(!blocked((r - dr), (c + dc))) {
dirs.push([-dr, dc]);
}
if(!blocked((r + dr), (c - dc))) {
dirs.push([dr, -dc]);
}
} else if((dr != 0)) {
dirs.push([dr, 0]);
} else {
dirs.push([0, dc]);
}
return dirs;
}
gScore[start[0]][start[1]] = 0;
priorityQueuePush(open, {f: h(start[0], start[1], end[0], end[1]), r: start[0], c: start[1], parent: null});
while(priorityQueueSize(open)) {
var __pattern2 = priorityQueuePop(open);
var r = __pattern2.r;
var c = __pattern2.c;
var parent = __pattern2.parent;
var currentKey = key(r, c);
if(visited.has(currentKey)) {
continue;
}
visited.add(currentKey);
visitNode(r, c);
if(((r == end[0]) && (c == end[1]))) {
reconstructPath(prev, start, end);
return;
}
for(int _fod_i = 0; _fod_i < neighborsWithPruning(r, c, parent)_len; _fod_i++) {
int dr = neighborsWithPruning(r, c, parent)[_fod_i][0];
int dc = neighborsWithPruning(r, c, parent)[_fod_i][1];
var jp = jump(r, c, dr, dc, gScore[r][c]);
if(!jp) {
continue;
}
var jumpKey = key(jp.r, jp.c);
var tentative = (gScore[r][c] + hypot((jp.r - r), (jp.c - c)));
if((tentative < gScore[jp.r][jp.c])) {
gScore[jp.r][jp.c] = tentative;
prev.set(jumpKey, [r, c]);
priorityQueuePush(open, {f: (tentative + h(jp.r, jp.c, end[0], end[1])), r: jp.r, c: jp.c, parent: [r, c]});
pushFrontier(jp.r, jp.c);
}
}
}
reportNoPath();
}