Home/Pathfinding/Jump point search
Search algorithmsCTRL K

Jump point search

· A* that skips straight runs
/pathfinding/jump-point-search
POPS
0
jump points expanded
SCANNED
0
cells passed while jumping
JUMP POINTS
0
found so far
OPEN SET
1
jump points waiting
PATH
—
length once the goal is reached
scanned while jumpingopen jump pointcurrentpathstart / goal
44×20 · 28% walls · seed 7 · 4-connected · 390 steps
step 0 / 389
Walls28
jump_point_search.ts
1
function jumpPointSearch(grid: Grid, start: Cell, goal: Cell) {
2
  const open = new MinHeap<Cell>([start]), distance = new Map([[start, 0]]), parent = new Map();
3
  while (open.size > 0) {
4
    const current = open.pop(); // lowest distance + heuristic
5
    if (current === goal) return rebuild(parent, current);
6
    for (const direction of directionsFrom(current, parent.get(current))) {
7
      const point = jump(grid, current, direction, goal);
8
      if (point === null) continue;
9
      const candidate = distance.get(current)! + manhattan(current, point);
10
      if (candidate >= (distance.get(point) ?? Infinity)) continue;
11
      distance.set(point, candidate); parent.set(point, current);
12
      open.push(point, candidate + manhattan(point, goal));
13
    }
14
  }
15
}
16
function jump(grid: Grid, from: Cell, direction: Direction, goal: Cell): Cell | null {
17
  const next = step(from, direction);
18
  if (!walkable(grid, next)) return null;
19
  if (next === goal || hasForcedNeighbor(grid, next, direction)) return next;
20
  if (isVertical(direction)) for (const side of [LEFT, RIGHT]) if (jump(grid, next, side, goal)) return next;
21
  return jump(grid, next, direction, goal);
22
}
CURRENT STEP
line 2

Start at (12, 1), goal at (5, 42). Instead of expanding every neighbour, JPS jumps along straight runs until something interesting.

// how it works

Understanding Jump point search

JPS · on an open grid, only the corners matter
01

The idea

On a uniform grid most of A*'s work is pointless: a cell in the middle of an open corridor has exactly one sensible successor, the next cell along. Jump point search keeps A*'s open set and heuristic, but instead of pushing every neighbour it jumps along a straight run and pushes only the cell where something changes: the goal, or a wall that forces a turn.

Those cells are the jump points. Scanning a run costs a few cheap array reads, while each pushed cell costs a heap operation, so JPS expands ten to a hundred times fewer nodes than A* and returns the same optimal path. It needs no preprocessing and no extra memory, only a uniform-cost grid.

02

The four stages

1
popthe jump point with the lowest g + h
2
jumpstraight until a forced turn, the goal or a wall
3
openthe jump point found, with its distance
4
pathfollow parents back to the start
03

Complexity

best
O(d)a straight corridor to the goal: one jump
average
O(E log V)same bound as A*, far fewer heap operations
worst
O(E log V)a maze of one-cell corridors: every cell is a jump point
space
O(V)the open set holds only jump points
04

Versus its siblings

CELLS EXPANDED · 44×20 MAZE
bfs
612
dijkstra
604
bidirectional
310
a*
188
greedy
96
jps
41
pops for JPS · the scanned cells are cheap array reads
05

Pseudocode

JPS(start, goal)
  A* over jump points: open ← {start}
  pop the jump point with the lowest g + h; if it is the goal, rebuild the path
  for each allowed direction: point ← JUMP(current, direction)
    if point exists and g(current) + distance < g(point): update, push point
JUMP(cell, direction): step once; stop at a wall (nothing), at the goal or at a forced turn (jump point); on a vertical run also try both sideways jumps; else keep going
06

When to use

Uniform-cost grids with open areas: real-time strategy games, tile maps, robot occupancy grids.
When A* is too slow and there is no time to precompute anything.
07

Pitfalls

Weighted cells break it: a jump may skip over a cheaper detour. JPS is for uniform grids only.
The 8-connected version has more pruning rules (diagonals) than the 4-connected one shown here; do not mix them.
Narrow mazes turn every cell into a jump point and the gain disappears; measure before switching.
08

History

Daniel Harabor and Alban Grastien presented jump point search in 2011 for 8-connected grids, and it became the reference for online grid pathfinding within a few years. JPS+ in 2014 precomputes the jump distances for another order of magnitude when the map is static.

Back to Pathfinding