@flare-engine/pathfinding 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -21
- package/NOTICE +2 -0
- package/README.md +4 -5
- package/dist/index.d.mts +56 -72
- package/dist/index.d.mts.map +1 -0
- package/dist/index.d.ts +56 -72
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +655 -640
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +640 -599
- package/dist/index.mjs.map +1 -1
- package/package.json +17 -9
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/grid.ts","../src/astar.ts","../src/jps.ts","../src/navmesh.ts"],"sourcesContent":["export {\n type Grid,\n type GridConfig,\n createGrid,\n inBounds,\n isWalkable,\n getCost,\n setWalkable,\n setCost,\n} from './grid.js';\n\nexport {\n type PathResult,\n type PathOptions,\n findPath,\n manhattanDistance,\n octileDistance,\n chebyshevDistance,\n euclideanDistance,\n} from './astar.js';\n\nexport { type JpsOptions, findPathJPS } from './jps.js';\n\nexport {\n type NavMeshPolygon,\n type Portal,\n type NavMesh,\n type NavMeshPathResult,\n createNavMesh,\n findPolygonAt,\n findNavMeshPath,\n} from './navmesh.js';\n","/**\n * Grid data structure for tile-based pathfinding.\n * Uses a flat Uint8Array: 0 = blocked, 1+ = walkable (value = movement cost).\n */\n\nexport interface Grid {\n readonly width: number;\n readonly height: number;\n readonly data: Uint8Array;\n}\n\nexport interface GridConfig {\n width: number;\n height: number;\n /** Pre-filled grid data. Length must equal width * height. */\n data?: Uint8Array;\n /** Default cost for all cells when `data` is not provided. 0 = blocked, 1+ = walkable cost. Default 1. */\n defaultCost?: number;\n}\n\nexport function createGrid(config: GridConfig): Grid {\n const { width, height, defaultCost = 1 } = config;\n if (width <= 0 || height <= 0) {\n throw new RangeError('Grid dimensions must be positive');\n }\n const w = width | 0;\n const h = height | 0;\n let data: Uint8Array;\n if (config.data) {\n if (config.data.length !== w * h) {\n throw new RangeError(`Grid data length ${config.data.length} does not match ${w}x${h}`);\n }\n data = config.data;\n } else {\n data = new Uint8Array(w * h);\n if (defaultCost > 0) {\n data.fill(defaultCost);\n }\n }\n return { width: w, height: h, data };\n}\n\nexport function inBounds(grid: Grid, x: number, y: number): boolean {\n return x >= 0 && y >= 0 && x < grid.width && y < grid.height;\n}\n\nexport function isWalkable(grid: Grid, x: number, y: number): boolean {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return false;\n return grid.data[(y | 0) * grid.width + (x | 0)]! > 0;\n}\n\nexport function getCost(grid: Grid, x: number, y: number): number {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return 0;\n return grid.data[(y | 0) * grid.width + (x | 0)]!;\n}\n\nexport function setWalkable(grid: Grid, x: number, y: number, walkable: boolean): void {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;\n grid.data[(y | 0) * grid.width + (x | 0)] = walkable ? 1 : 0;\n}\n\nexport function setCost(grid: Grid, x: number, y: number, cost: number): void {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;\n grid.data[(y | 0) * grid.width + (x | 0)] = cost > 255 ? 255 : cost < 0 ? 0 : cost | 0;\n}\n","/**\n * A* pathfinding on a Grid. Supports 4-directional and 8-directional movement\n * with weighted costs. Uses a binary min-heap for the open set.\n */\n\nimport type { Grid } from './grid.js';\nimport { isWalkable } from './grid.js';\n\nexport interface PathResult {\n /** Grid coordinates from start to end, inclusive. */\n path: { x: number; y: number }[];\n /** Total movement cost. */\n cost: number;\n /** Number of nodes explored. */\n explored: number;\n}\n\nexport interface PathOptions {\n /** Allow diagonal movement. Default: true. */\n diagonal?: boolean;\n /** Custom heuristic. Default: octile distance (diagonal) or Manhattan (4-dir). */\n heuristic?: (ax: number, ay: number, bx: number, by: number) => number;\n /** Max nodes to explore before giving up. Default: width * height. */\n maxIterations?: number;\n}\n\n// ─── Heuristics ──────────────────────────────────────────────────\n\nconst SQRT2 = Math.SQRT2;\n\nexport function manhattanDistance(ax: number, ay: number, bx: number, by: number): number {\n return Math.abs(ax - bx) + Math.abs(ay - by);\n}\n\nexport function octileDistance(ax: number, ay: number, bx: number, by: number): number {\n const dx = Math.abs(ax - bx);\n const dy = Math.abs(ay - by);\n return dx > dy ? dx + (SQRT2 - 1) * dy : dy + (SQRT2 - 1) * dx;\n}\n\nexport function chebyshevDistance(ax: number, ay: number, bx: number, by: number): number {\n return Math.max(Math.abs(ax - bx), Math.abs(ay - by));\n}\n\nexport function euclideanDistance(ax: number, ay: number, bx: number, by: number): number {\n const dx = ax - bx;\n const dy = ay - by;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n// ─── Binary min-heap ─────────────────────────────────────────────\n\n// Indices into the heap are stored as flat integers; each entry is (f, node-index).\n// We use two parallel Float64Arrays to avoid object allocation.\ninterface Heap {\n f: Float64Array;\n idx: Int32Array;\n size: number;\n}\n\nfunction heapCreate(capacity: number): Heap {\n return {\n f: new Float64Array(capacity),\n idx: new Int32Array(capacity),\n size: 0,\n };\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n let i = h.size++;\n h.f[i] = f;\n h.idx[i] = nodeIdx;\n // Bubble up\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (h.f[parent]! <= h.f[i]!) break;\n // Swap\n const tf = h.f[parent]!;\n const ti = h.idx[parent]!;\n h.f[parent] = h.f[i]!;\n h.idx[parent] = h.idx[i]!;\n h.f[i] = tf;\n h.idx[i] = ti;\n i = parent;\n }\n}\n\nfunction heapPop(h: Heap): number {\n const result = h.idx[0]!;\n h.size--;\n if (h.size > 0) {\n h.f[0] = h.f[h.size]!;\n h.idx[0] = h.idx[h.size]!;\n // Sift down\n let i = 0;\n for (;;) {\n let smallest = i;\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n if (left < h.size && h.f[left]! < h.f[smallest]!) smallest = left;\n if (right < h.size && h.f[right]! < h.f[smallest]!) smallest = right;\n if (smallest === i) break;\n const tf = h.f[i]!;\n const ti = h.idx[i]!;\n h.f[i] = h.f[smallest]!;\n h.idx[i] = h.idx[smallest]!;\n h.f[smallest] = tf;\n h.idx[smallest] = ti;\n i = smallest;\n }\n }\n return result;\n}\n\n// ─── Neighbors (pre-computed offsets) ────────────────────────────\n\n// 4-directional: N, E, S, W\nconst DIR4_X = [0, 1, 0, -1];\nconst DIR4_Y = [-1, 0, 1, 0];\n\n// 8-directional: N, NE, E, SE, S, SW, W, NW\nconst DIR8_X = [0, 1, 1, 1, 0, -1, -1, -1];\nconst DIR8_Y = [-1, -1, 0, 1, 1, 1, 0, -1];\nconst DIR8_COST = [1, SQRT2, 1, SQRT2, 1, SQRT2, 1, SQRT2];\n\n// ─── A* ──────────────────────────────────────────────────────────\n\nexport function findPath(\n grid: Grid,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: PathOptions,\n): PathResult | null {\n const sx = startX | 0;\n const sy = startY | 0;\n const ex = endX | 0;\n const ey = endY | 0;\n\n // Quick rejects\n if (!isWalkable(grid, sx, sy) || !isWalkable(grid, ex, ey)) return null;\n if (sx === ex && sy === ey) return { path: [{ x: sx, y: sy }], cost: 0, explored: 0 };\n\n const diagonal = options?.diagonal !== false;\n const maxIter = options?.maxIterations ?? grid.width * grid.height;\n const heuristic = options?.heuristic ?? (diagonal ? octileDistance : manhattanDistance);\n\n const w = grid.width;\n const total = w * grid.height;\n\n // gScore and closed set\n const g = new Float64Array(total);\n g.fill(Number.POSITIVE_INFINITY);\n const closed = new Uint8Array(total);\n const cameFrom = new Int32Array(total);\n cameFrom.fill(-1);\n\n const startIdx = sy * w + sx;\n const endIdx = ey * w + ex;\n g[startIdx] = 0;\n\n const heap = heapCreate(Math.min(total, 4096));\n heapPush(heap, heuristic(sx, sy, ex, ey), startIdx);\n\n const dirX = diagonal ? DIR8_X : DIR4_X;\n const dirY = diagonal ? DIR8_Y : DIR4_Y;\n const dirCost = diagonal ? DIR8_COST : null;\n const dirCount = dirX.length;\n\n let explored = 0;\n\n while (heap.size > 0 && explored < maxIter) {\n const currentIdx = heapPop(heap);\n if (currentIdx === endIdx) {\n return reconstructPath(cameFrom, w, currentIdx, g[currentIdx]!, explored);\n }\n if (closed[currentIdx]) continue;\n closed[currentIdx] = 1;\n explored++;\n\n const cx = currentIdx % w;\n const cy = (currentIdx / w) | 0;\n const currentG = g[currentIdx]!;\n\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dirX[d]!;\n const ny = cy + dirY[d]!;\n if (nx < 0 || ny < 0 || nx >= w || ny >= grid.height) continue;\n\n const nIdx = ny * w + nx;\n if (closed[nIdx]) continue;\n\n const tileCost = grid.data[nIdx]!;\n if (tileCost === 0) continue;\n\n // For diagonal movement, check that both cardinal neighbors are walkable (corner-cutting)\n if (diagonal && d & 1) {\n const dx = dirX[d]!;\n const dy = dirY[d]!;\n if (!isWalkable(grid, cx + dx, cy) || !isWalkable(grid, cx, cy + dy)) continue;\n }\n\n const moveCost = dirCost ? dirCost[d]! * tileCost : tileCost;\n const tentativeG = currentG + moveCost;\n\n if (tentativeG < g[nIdx]!) {\n g[nIdx] = tentativeG;\n cameFrom[nIdx] = currentIdx;\n const f = tentativeG + heuristic(nx, ny, ex, ey);\n heapPush(heap, f, nIdx);\n }\n }\n }\n\n return null;\n}\n\nfunction reconstructPath(\n cameFrom: Int32Array,\n w: number,\n endIdx: number,\n cost: number,\n explored: number,\n): PathResult {\n const path: { x: number; y: number }[] = [];\n let idx = endIdx;\n while (idx !== -1) {\n path.push({ x: idx % w, y: (idx / w) | 0 });\n idx = cameFrom[idx]!;\n }\n path.reverse();\n return { path, cost, explored };\n}\n","/**\n * Jump Point Search — an optimization over A* for uniform-cost grids.\n * Only works when all walkable tiles have cost 1. Falls back to A* behavior\n * if weighted costs are detected.\n *\n * JPS prunes symmetric paths by \"jumping\" along directions until hitting\n * a wall, the goal, or a forced neighbor.\n */\n\nimport type { PathResult } from './astar.js';\nimport { octileDistance } from './astar.js';\nimport type { Grid } from './grid.js';\nimport { isWalkable } from './grid.js';\n\n// ─── Binary min-heap (duplicated from astar for tree-shakeability) ─\n\ninterface Heap {\n f: Float64Array;\n idx: Int32Array;\n size: number;\n}\n\nfunction heapCreate(capacity: number): Heap {\n return {\n f: new Float64Array(capacity),\n idx: new Int32Array(capacity),\n size: 0,\n };\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n let i = h.size++;\n h.f[i] = f;\n h.idx[i] = nodeIdx;\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (h.f[parent]! <= h.f[i]!) break;\n const tf = h.f[parent]!;\n const ti = h.idx[parent]!;\n h.f[parent] = h.f[i]!;\n h.idx[parent] = h.idx[i]!;\n h.f[i] = tf;\n h.idx[i] = ti;\n i = parent;\n }\n}\n\nfunction heapPop(h: Heap): number {\n const result = h.idx[0]!;\n h.size--;\n if (h.size > 0) {\n h.f[0] = h.f[h.size]!;\n h.idx[0] = h.idx[h.size]!;\n let i = 0;\n for (;;) {\n let smallest = i;\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n if (left < h.size && h.f[left]! < h.f[smallest]!) smallest = left;\n if (right < h.size && h.f[right]! < h.f[smallest]!) smallest = right;\n if (smallest === i) break;\n const tf = h.f[i]!;\n const ti = h.idx[i]!;\n h.f[i] = h.f[smallest]!;\n h.idx[i] = h.idx[smallest]!;\n h.f[smallest] = tf;\n h.idx[smallest] = ti;\n i = smallest;\n }\n }\n return result;\n}\n\n// ─── JPS ─────────────────────────────────────────────────────────\n\nconst SQRT2 = Math.SQRT2;\n\nexport interface JpsOptions {\n /** Max nodes to explore before giving up. Default: width * height. */\n maxIterations?: number;\n /** Custom heuristic. Default: octile distance. */\n heuristic?: (ax: number, ay: number, bx: number, by: number) => number;\n}\n\nexport function findPathJPS(\n grid: Grid,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: JpsOptions,\n): PathResult | null {\n const sx = startX | 0;\n const sy = startY | 0;\n const ex = endX | 0;\n const ey = endY | 0;\n\n if (!isWalkable(grid, sx, sy) || !isWalkable(grid, ex, ey)) return null;\n if (sx === ex && sy === ey) return { path: [{ x: sx, y: sy }], cost: 0, explored: 0 };\n\n const w = grid.width;\n const h = grid.height;\n const total = w * h;\n const maxIter = options?.maxIterations ?? total;\n const heuristic = options?.heuristic ?? octileDistance;\n\n const g = new Float64Array(total);\n g.fill(Number.POSITIVE_INFINITY);\n const closed = new Uint8Array(total);\n const cameFrom = new Int32Array(total);\n cameFrom.fill(-1);\n\n const startIdx = sy * w + sx;\n const endIdx = ey * w + ex;\n g[startIdx] = 0;\n\n const heap = heapCreate(Math.min(total, 4096));\n heapPush(heap, heuristic(sx, sy, ex, ey), startIdx);\n\n let explored = 0;\n\n while (heap.size > 0 && explored < maxIter) {\n const currentIdx = heapPop(heap);\n if (currentIdx === endIdx) {\n return buildPath(cameFrom, w, currentIdx, g[currentIdx]!, explored);\n }\n if (closed[currentIdx]) continue;\n closed[currentIdx] = 1;\n explored++;\n\n const cx = currentIdx % w;\n const cy = (currentIdx / w) | 0;\n\n const neighbors = identifySuccessors(grid, cx, cy, cameFrom, w, h, ex, ey);\n for (let i = 0; i < neighbors.length; i += 2) {\n const nx = neighbors[i]!;\n const ny = neighbors[i + 1]!;\n const nIdx = ny * w + nx;\n if (closed[nIdx]) continue;\n\n const dx = Math.abs(nx - cx);\n const dy = Math.abs(ny - cy);\n const diag = Math.min(dx, dy);\n const straight = Math.abs(dx - dy);\n const dist = diag * SQRT2 + straight;\n const tentativeG = g[currentIdx]! + dist;\n if (tentativeG < g[nIdx]!) {\n g[nIdx] = tentativeG;\n cameFrom[nIdx] = currentIdx;\n heapPush(heap, tentativeG + heuristic(nx, ny, ex, ey), nIdx);\n }\n }\n }\n\n return null;\n}\n\nfunction identifySuccessors(\n grid: Grid,\n cx: number,\n cy: number,\n cameFrom: Int32Array,\n w: number,\n h: number,\n ex: number,\n ey: number,\n): number[] {\n const results: number[] = [];\n const parentIdx = cameFrom[cy * w + cx]!;\n\n if (parentIdx === -1) {\n // Start node: explore all 8 directions\n for (let dx = -1; dx <= 1; dx++) {\n for (let dy = -1; dy <= 1; dy++) {\n if (dx === 0 && dy === 0) continue;\n const jp = jump(grid, cx, cy, dx, dy, w, h, ex, ey);\n if (jp !== -1) {\n results.push(jp % w, (jp / w) | 0);\n }\n }\n }\n } else {\n const px = parentIdx % w;\n const py = (parentIdx / w) | 0;\n const dx = clampDir(cx - px);\n const dy = clampDir(cy - py);\n\n if (dx !== 0 && dy !== 0) {\n // Diagonal move: check straight and diagonal successors\n if (isWalkable(grid, cx, cy + dy)) {\n const jp = jump(grid, cx, cy, 0, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (isWalkable(grid, cx + dx, cy)) {\n const jp = jump(grid, cx, cy, dx, 0, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (isWalkable(grid, cx + dx, cy + dy)) {\n const jp = jump(grid, cx, cy, dx, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n // Forced neighbors\n if (!isWalkable(grid, cx - dx, cy) && isWalkable(grid, cx - dx, cy + dy)) {\n const jp = jump(grid, cx, cy, -dx, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy - dy) && isWalkable(grid, cx + dx, cy - dy)) {\n const jp = jump(grid, cx, cy, dx, -dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n } else if (dx !== 0) {\n // Horizontal move\n if (isWalkable(grid, cx + dx, cy)) {\n const jp = jump(grid, cx, cy, dx, 0, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy + 1) && isWalkable(grid, cx + dx, cy + 1)) {\n const jp = jump(grid, cx, cy, dx, 1, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy - 1) && isWalkable(grid, cx + dx, cy - 1)) {\n const jp = jump(grid, cx, cy, dx, -1, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n } else {\n // Vertical move\n if (isWalkable(grid, cx, cy + dy)) {\n const jp = jump(grid, cx, cy, 0, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx + 1, cy) && isWalkable(grid, cx + 1, cy + dy)) {\n const jp = jump(grid, cx, cy, 1, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx - 1, cy) && isWalkable(grid, cx - 1, cy + dy)) {\n const jp = jump(grid, cx, cy, -1, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n }\n }\n\n return results;\n}\n\nfunction jump(\n grid: Grid,\n cx: number,\n cy: number,\n dx: number,\n dy: number,\n w: number,\n h: number,\n ex: number,\n ey: number,\n): number {\n const nx = cx + dx;\n const ny = cy + dy;\n\n if (!isWalkable(grid, nx, ny)) return -1;\n if (nx === ex && ny === ey) return ny * w + nx;\n\n // Forced neighbor check\n if (dx !== 0 && dy !== 0) {\n // Diagonal\n if (\n (!isWalkable(grid, nx - dx, ny) && isWalkable(grid, nx - dx, ny + dy)) ||\n (!isWalkable(grid, nx, ny - dy) && isWalkable(grid, nx + dx, ny - dy))\n ) {\n return ny * w + nx;\n }\n // Recurse in cardinal directions\n if (jump(grid, nx, ny, dx, 0, w, h, ex, ey) !== -1) return ny * w + nx;\n if (jump(grid, nx, ny, 0, dy, w, h, ex, ey) !== -1) return ny * w + nx;\n } else if (dx !== 0) {\n // Horizontal\n if (\n (!isWalkable(grid, nx, ny + 1) && isWalkable(grid, nx + dx, ny + 1)) ||\n (!isWalkable(grid, nx, ny - 1) && isWalkable(grid, nx + dx, ny - 1))\n ) {\n return ny * w + nx;\n }\n } else {\n // Vertical\n if (\n (!isWalkable(grid, nx + 1, ny) && isWalkable(grid, nx + 1, ny + dy)) ||\n (!isWalkable(grid, nx - 1, ny) && isWalkable(grid, nx - 1, ny + dy))\n ) {\n return ny * w + nx;\n }\n }\n\n // Keep jumping (iterative for cardinal, recursive for diagonal via identifySuccessors)\n return jump(grid, nx, ny, dx, dy, w, h, ex, ey);\n}\n\nfunction clampDir(v: number): number {\n return v > 0 ? 1 : v < 0 ? -1 : 0;\n}\n\nfunction buildPath(\n cameFrom: Int32Array,\n w: number,\n endIdx: number,\n cost: number,\n explored: number,\n): PathResult {\n // JPS produces jump points — we interpolate the full path\n const jumpPoints: number[] = [];\n let idx = endIdx;\n while (idx !== -1) {\n jumpPoints.push(idx);\n idx = cameFrom[idx]!;\n }\n jumpPoints.reverse();\n\n const path: { x: number; y: number }[] = [];\n for (let i = 0; i < jumpPoints.length; i++) {\n const jpIdx = jumpPoints[i]!;\n const jx = jpIdx % w;\n const jy = (jpIdx / w) | 0;\n if (i === 0) {\n path.push({ x: jx, y: jy });\n } else {\n const prev = path[path.length - 1]!;\n // Interpolate from prev to current jump point\n let cx = prev.x;\n let cy = prev.y;\n while (cx !== jx || cy !== jy) {\n if (cx < jx) cx++;\n else if (cx > jx) cx--;\n if (cy < jy) cy++;\n else if (cy > jy) cy--;\n path.push({ x: cx, y: cy });\n }\n }\n }\n\n return { path, cost, explored };\n}\n","/**\n * Lightweight navmesh pathfinding for polygon-based environments.\n * Supports convex polygon navigation with A* over the polygon graph\n * and the Simple Stupid Funnel Algorithm for path smoothing.\n */\n\nimport type { Vec2 } from '@flare-engine/math';\n\n// ─── Types ───────────────────────────────────────────────────────\n\nexport interface NavMeshPolygon {\n readonly id: number;\n /** Convex polygon vertices in winding order. */\n readonly vertices: readonly Vec2[];\n /** Ids of neighboring polygons (sharing an edge). */\n readonly neighbors: readonly number[];\n /** Shared edge per neighbor: [neighborId] → { a, b } portal endpoints. */\n readonly portals: readonly Portal[];\n}\n\nexport interface Portal {\n /** Neighbor polygon id. */\n neighborId: number;\n /** Left endpoint of the shared edge (from the perspective of travel). */\n a: Vec2;\n /** Right endpoint of the shared edge. */\n b: Vec2;\n}\n\nexport interface NavMesh {\n readonly polygons: readonly NavMeshPolygon[];\n}\n\nexport interface NavMeshPathResult {\n /** Smoothed world-space waypoints. */\n path: Vec2[];\n /** Polygon ids traversed. */\n corridor: number[];\n}\n\n// ─── Construction ────────────────────────────────────────────────\n\nexport function createNavMesh(polygons: NavMeshPolygon[]): NavMesh {\n return { polygons };\n}\n\n// ─── Point-in-polygon ────────────────────────────────────────────\n\nfunction pointInConvexPolygon(verts: readonly Vec2[], px: number, py: number): boolean {\n const n = verts.length;\n if (n < 3) return false;\n let sign = 0;\n for (let i = 0; i < n; i++) {\n const a = verts[i]!;\n const b = verts[(i + 1) % n]!;\n const cross = (b.x - a.x) * (py - a.y) - (b.y - a.y) * (px - a.x);\n if (cross !== 0) {\n const s = cross > 0 ? 1 : -1;\n if (sign === 0) sign = s;\n else if (sign !== s) return false;\n }\n }\n return true;\n}\n\nexport function findPolygonAt(mesh: NavMesh, x: number, y: number): number {\n for (let i = 0; i < mesh.polygons.length; i++) {\n if (pointInConvexPolygon(mesh.polygons[i]!.vertices, x, y)) {\n return mesh.polygons[i]!.id;\n }\n }\n return -1;\n}\n\n// ─── Polygon centroid ────────────────────────────────────────────\n\nfunction centroid(verts: readonly Vec2[]): Vec2 {\n let cx = 0;\n let cy = 0;\n for (let i = 0; i < verts.length; i++) {\n cx += verts[i]!.x;\n cy += verts[i]!.y;\n }\n const n = verts.length;\n return { x: cx / n, y: cy / n };\n}\n\n// ─── A* over polygon graph ───────────────────────────────────────\n\nfunction distSq(ax: number, ay: number, bx: number, by: number): number {\n const dx = ax - bx;\n const dy = ay - by;\n return dx * dx + dy * dy;\n}\n\nfunction dist(ax: number, ay: number, bx: number, by: number): number {\n return Math.sqrt(distSq(ax, ay, bx, by));\n}\n\nexport function findNavMeshPath(mesh: NavMesh, start: Vec2, end: Vec2): NavMeshPathResult | null {\n const startPolyId = findPolygonAt(mesh, start.x, start.y);\n const endPolyId = findPolygonAt(mesh, end.x, end.y);\n if (startPolyId === -1 || endPolyId === -1) return null;\n if (startPolyId === endPolyId) {\n return {\n path: [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ],\n corridor: [startPolyId],\n };\n }\n\n // Build index: id → polygon\n const byId = new Map<number, NavMeshPolygon>();\n for (let i = 0; i < mesh.polygons.length; i++) {\n const p = mesh.polygons[i]!;\n byId.set(p.id, p);\n }\n\n // A* on polygon graph\n const gScore = new Map<number, number>();\n const fScore = new Map<number, number>();\n const cameFrom = new Map<number, number>();\n\n gScore.set(startPolyId, 0);\n\n const endPoly = byId.get(endPolyId)!;\n const endCenter = centroid(endPoly.vertices);\n const startPoly = byId.get(startPolyId)!;\n const startCenter = centroid(startPoly.vertices);\n\n fScore.set(startPolyId, dist(startCenter.x, startCenter.y, endCenter.x, endCenter.y));\n\n // Simple array-based open set (fine for typical navmeshes with <1000 polygons)\n const open: number[] = [startPolyId];\n const inOpen = new Set<number>([startPolyId]);\n const closed = new Set<number>();\n\n while (open.length > 0) {\n // Find lowest f-score\n let bestI = 0;\n let bestF = fScore.get(open[0]!) ?? Number.POSITIVE_INFINITY;\n for (let i = 1; i < open.length; i++) {\n const f = fScore.get(open[i]!) ?? Number.POSITIVE_INFINITY;\n if (f < bestF) {\n bestF = f;\n bestI = i;\n }\n }\n const currentId = open[bestI]!;\n\n if (currentId === endPolyId) {\n // Reconstruct corridor\n const corridor: number[] = [];\n let id: number | undefined = endPolyId;\n while (id !== undefined) {\n corridor.push(id);\n id = cameFrom.get(id);\n }\n corridor.reverse();\n const path = funnelSmooth(mesh, byId, corridor, start, end);\n return { path, corridor };\n }\n\n // Remove from open\n open[bestI] = open[open.length - 1]!;\n open.length--;\n inOpen.delete(currentId);\n closed.add(currentId);\n\n const current = byId.get(currentId)!;\n const currentCenter = centroid(current.vertices);\n const currentG = gScore.get(currentId)!;\n\n for (let i = 0; i < current.portals.length; i++) {\n const portal = current.portals[i]!;\n const neighborId = portal.neighborId;\n if (closed.has(neighborId)) continue;\n\n const neighbor = byId.get(neighborId);\n if (!neighbor) continue;\n\n const portalMidX = (portal.a.x + portal.b.x) * 0.5;\n const portalMidY = (portal.a.y + portal.b.y) * 0.5;\n const tentativeG = currentG + dist(currentCenter.x, currentCenter.y, portalMidX, portalMidY);\n\n const prevG = gScore.get(neighborId);\n if (prevG !== undefined && tentativeG >= prevG) continue;\n\n gScore.set(neighborId, tentativeG);\n cameFrom.set(neighborId, currentId);\n\n const neighborCenter = centroid(neighbor.vertices);\n fScore.set(\n neighborId,\n tentativeG + dist(neighborCenter.x, neighborCenter.y, endCenter.x, endCenter.y),\n );\n\n if (!inOpen.has(neighborId)) {\n open.push(neighborId);\n inOpen.add(neighborId);\n }\n }\n }\n\n return null;\n}\n\n// ─── Simple Stupid Funnel Algorithm ──────────────────────────────\n\nfunction funnelSmooth(\n _mesh: NavMesh,\n byId: Map<number, NavMeshPolygon>,\n corridor: number[],\n start: Vec2,\n end: Vec2,\n): Vec2[] {\n if (corridor.length <= 1) {\n return [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ];\n }\n\n // Build portal list from corridor\n const portalsLeft: Vec2[] = [];\n const portalsRight: Vec2[] = [];\n\n portalsLeft.push({ x: start.x, y: start.y });\n portalsRight.push({ x: start.x, y: start.y });\n\n for (let i = 0; i < corridor.length - 1; i++) {\n const poly = byId.get(corridor[i]!)!;\n const nextId = corridor[i + 1]!;\n // Find the portal to the next polygon\n let found = false;\n for (let j = 0; j < poly.portals.length; j++) {\n if (poly.portals[j]!.neighborId === nextId) {\n portalsLeft.push(poly.portals[j]!.a);\n portalsRight.push(poly.portals[j]!.b);\n found = true;\n break;\n }\n }\n if (!found) {\n // Fallback: straight line through centroids\n const c = centroid(poly.vertices);\n portalsLeft.push(c);\n portalsRight.push(c);\n }\n }\n\n portalsLeft.push({ x: end.x, y: end.y });\n portalsRight.push({ x: end.x, y: end.y });\n\n // Simple Stupid Funnel Algorithm (Mononen)\n // Walk the portal list and maintain a funnel (apex, left, right).\n const path: Vec2[] = [];\n\n let apexPt = portalsLeft[0]!; // start point\n let leftPt = portalsLeft[0]!;\n let rightPt = portalsRight[0]!;\n let apexIdx = 0;\n let leftIdx = 0;\n let rightIdx = 0;\n\n path.push({ x: apexPt.x, y: apexPt.y });\n\n const n = portalsLeft.length;\n\n for (let i = 1; i < n; i++) {\n const pL = portalsLeft[i]!;\n const pR = portalsRight[i]!;\n\n // Try to tighten the right side\n if (triArea2(apexPt, rightPt, pR) <= 0) {\n if (vEqual(apexPt, rightPt) || triArea2(apexPt, leftPt, pR) > 0) {\n // Tighten\n rightPt = pR;\n rightIdx = i;\n } else {\n // Right crossed over left → left becomes new apex\n addUnique(path, leftPt);\n apexPt = leftPt;\n apexIdx = leftIdx;\n // Reset funnel\n leftPt = apexPt;\n rightPt = apexPt;\n leftIdx = apexIdx;\n rightIdx = apexIdx;\n // Restart scan from the portal after the new apex\n i = apexIdx;\n continue;\n }\n }\n\n // Try to tighten the left side\n if (triArea2(apexPt, leftPt, pL) >= 0) {\n if (vEqual(apexPt, leftPt) || triArea2(apexPt, rightPt, pL) < 0) {\n // Tighten\n leftPt = pL;\n leftIdx = i;\n } else {\n // Left crossed over right → right becomes new apex\n addUnique(path, rightPt);\n apexPt = rightPt;\n apexIdx = rightIdx;\n // Reset funnel\n leftPt = apexPt;\n rightPt = apexPt;\n leftIdx = apexIdx;\n rightIdx = apexIdx;\n // Restart scan from the portal after the new apex\n i = apexIdx;\n }\n }\n }\n\n addUnique(path, end);\n\n return path;\n}\n\nfunction addUnique(path: Vec2[], p: Vec2): void {\n const last = path[path.length - 1];\n if (!last || last.x !== p.x || last.y !== p.y) {\n path.push({ x: p.x, y: p.y });\n }\n}\n\n/** Twice the signed area of the triangle (a, b, c). Positive = CCW. */\nfunction triArea2(a: Vec2, b: Vec2, c: Vec2): number {\n return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);\n}\n\nfunction vEqual(a: Vec2, b: Vec2): boolean {\n return a.x === b.x && a.y === b.y;\n}\n"],"mappings":"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","names":["heapCreate","heapPush","heapPop","SQRT2","dist"]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["SQRT2","heapCreate","heapPush","heapPop"],"sources":["../src/grid.ts","../src/astar.ts","../src/jps.ts","../src/navmesh.ts"],"sourcesContent":["/**\n * Grid data structure for tile-based pathfinding.\n * Uses a flat Uint8Array: 0 = blocked, 1+ = walkable (value = movement cost).\n */\n\nexport interface Grid {\n readonly width: number;\n readonly height: number;\n readonly data: Uint8Array;\n}\n\nexport interface GridConfig {\n width: number;\n height: number;\n /** Pre-filled grid data. Length must equal width * height. */\n data?: Uint8Array;\n /** Default cost for all cells when `data` is not provided. 0 = blocked, 1+ = walkable cost. Default 1. */\n defaultCost?: number;\n}\n\nexport function createGrid(config: GridConfig): Grid {\n const { width, height, defaultCost = 1 } = config;\n if (width <= 0 || height <= 0) {\n throw new RangeError('Grid dimensions must be positive');\n }\n const w = width | 0;\n const h = height | 0;\n let data: Uint8Array;\n if (config.data) {\n if (config.data.length !== w * h) {\n throw new RangeError(`Grid data length ${config.data.length} does not match ${w}x${h}`);\n }\n data = config.data;\n } else {\n data = new Uint8Array(w * h);\n if (defaultCost > 0) {\n data.fill(defaultCost);\n }\n }\n return { width: w, height: h, data };\n}\n\nexport function inBounds(grid: Grid, x: number, y: number): boolean {\n return x >= 0 && y >= 0 && x < grid.width && y < grid.height;\n}\n\nexport function isWalkable(grid: Grid, x: number, y: number): boolean {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return false;\n return grid.data[(y | 0) * grid.width + (x | 0)]! > 0;\n}\n\nexport function getCost(grid: Grid, x: number, y: number): number {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return 0;\n return grid.data[(y | 0) * grid.width + (x | 0)]!;\n}\n\nexport function setWalkable(grid: Grid, x: number, y: number, walkable: boolean): void {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;\n grid.data[(y | 0) * grid.width + (x | 0)] = walkable ? 1 : 0;\n}\n\nexport function setCost(grid: Grid, x: number, y: number, cost: number): void {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;\n grid.data[(y | 0) * grid.width + (x | 0)] = cost > 255 ? 255 : cost < 0 ? 0 : cost | 0;\n}\n","/**\n * A* pathfinding on a Grid. Supports 4-directional and 8-directional movement\n * with weighted costs. Uses a binary min-heap for the open set.\n */\n\nimport type { Grid } from './grid.js';\nimport { isWalkable } from './grid.js';\n\nexport interface PathResult {\n /** Grid coordinates from start to end, inclusive. */\n path: { x: number; y: number }[];\n /** Total movement cost. */\n cost: number;\n /** Number of nodes explored. */\n explored: number;\n}\n\nexport interface PathOptions {\n /** Allow diagonal movement. Default: true. */\n diagonal?: boolean;\n /** Custom heuristic. Default: octile distance (diagonal) or Manhattan (4-dir). */\n heuristic?: (ax: number, ay: number, bx: number, by: number) => number;\n /** Max nodes to explore before giving up. Default: width * height. */\n maxIterations?: number;\n}\n\n// ─── Heuristics ──────────────────────────────────────────────────\n\nconst SQRT2 = Math.SQRT2;\n\nexport function manhattanDistance(ax: number, ay: number, bx: number, by: number): number {\n return Math.abs(ax - bx) + Math.abs(ay - by);\n}\n\nexport function octileDistance(ax: number, ay: number, bx: number, by: number): number {\n const dx = Math.abs(ax - bx);\n const dy = Math.abs(ay - by);\n return dx > dy ? dx + (SQRT2 - 1) * dy : dy + (SQRT2 - 1) * dx;\n}\n\nexport function chebyshevDistance(ax: number, ay: number, bx: number, by: number): number {\n return Math.max(Math.abs(ax - bx), Math.abs(ay - by));\n}\n\nexport function euclideanDistance(ax: number, ay: number, bx: number, by: number): number {\n const dx = ax - bx;\n const dy = ay - by;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n// ─── Binary min-heap ─────────────────────────────────────────────\n\n// Indices into the heap are stored as flat integers; each entry is (f, node-index).\n// We use two parallel Float64Arrays to avoid object allocation.\ninterface Heap {\n f: Float64Array;\n idx: Int32Array;\n size: number;\n}\n\nfunction heapCreate(capacity: number): Heap {\n return {\n f: new Float64Array(capacity),\n idx: new Int32Array(capacity),\n size: 0,\n };\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n let i = h.size++;\n h.f[i] = f;\n h.idx[i] = nodeIdx;\n // Bubble up\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (h.f[parent]! <= h.f[i]!) break;\n // Swap\n const tf = h.f[parent]!;\n const ti = h.idx[parent]!;\n h.f[parent] = h.f[i]!;\n h.idx[parent] = h.idx[i]!;\n h.f[i] = tf;\n h.idx[i] = ti;\n i = parent;\n }\n}\n\nfunction heapPop(h: Heap): number {\n const result = h.idx[0]!;\n h.size--;\n if (h.size > 0) {\n h.f[0] = h.f[h.size]!;\n h.idx[0] = h.idx[h.size]!;\n // Sift down\n let i = 0;\n for (;;) {\n let smallest = i;\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n if (left < h.size && h.f[left]! < h.f[smallest]!) smallest = left;\n if (right < h.size && h.f[right]! < h.f[smallest]!) smallest = right;\n if (smallest === i) break;\n const tf = h.f[i]!;\n const ti = h.idx[i]!;\n h.f[i] = h.f[smallest]!;\n h.idx[i] = h.idx[smallest]!;\n h.f[smallest] = tf;\n h.idx[smallest] = ti;\n i = smallest;\n }\n }\n return result;\n}\n\n// ─── Neighbors (pre-computed offsets) ────────────────────────────\n\n// 4-directional: N, E, S, W\nconst DIR4_X = [0, 1, 0, -1];\nconst DIR4_Y = [-1, 0, 1, 0];\n\n// 8-directional: N, NE, E, SE, S, SW, W, NW\nconst DIR8_X = [0, 1, 1, 1, 0, -1, -1, -1];\nconst DIR8_Y = [-1, -1, 0, 1, 1, 1, 0, -1];\nconst DIR8_COST = [1, SQRT2, 1, SQRT2, 1, SQRT2, 1, SQRT2];\n\n// ─── A* ──────────────────────────────────────────────────────────\n\nexport function findPath(\n grid: Grid,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: PathOptions,\n): PathResult | null {\n const sx = startX | 0;\n const sy = startY | 0;\n const ex = endX | 0;\n const ey = endY | 0;\n\n // Quick rejects\n if (!isWalkable(grid, sx, sy) || !isWalkable(grid, ex, ey)) return null;\n if (sx === ex && sy === ey) return { path: [{ x: sx, y: sy }], cost: 0, explored: 0 };\n\n const diagonal = options?.diagonal !== false;\n const maxIter = options?.maxIterations ?? grid.width * grid.height;\n const heuristic = options?.heuristic ?? (diagonal ? octileDistance : manhattanDistance);\n\n const w = grid.width;\n const total = w * grid.height;\n\n // gScore and closed set\n const g = new Float64Array(total);\n g.fill(Number.POSITIVE_INFINITY);\n const closed = new Uint8Array(total);\n const cameFrom = new Int32Array(total);\n cameFrom.fill(-1);\n\n const startIdx = sy * w + sx;\n const endIdx = ey * w + ex;\n g[startIdx] = 0;\n\n const heap = heapCreate(Math.min(total, 4096));\n heapPush(heap, heuristic(sx, sy, ex, ey), startIdx);\n\n const dirX = diagonal ? DIR8_X : DIR4_X;\n const dirY = diagonal ? DIR8_Y : DIR4_Y;\n const dirCost = diagonal ? DIR8_COST : null;\n const dirCount = dirX.length;\n\n let explored = 0;\n\n while (heap.size > 0 && explored < maxIter) {\n const currentIdx = heapPop(heap);\n if (currentIdx === endIdx) {\n return reconstructPath(cameFrom, w, currentIdx, g[currentIdx]!, explored);\n }\n if (closed[currentIdx]) continue;\n closed[currentIdx] = 1;\n explored++;\n\n const cx = currentIdx % w;\n const cy = (currentIdx / w) | 0;\n const currentG = g[currentIdx]!;\n\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dirX[d]!;\n const ny = cy + dirY[d]!;\n if (nx < 0 || ny < 0 || nx >= w || ny >= grid.height) continue;\n\n const nIdx = ny * w + nx;\n if (closed[nIdx]) continue;\n\n const tileCost = grid.data[nIdx]!;\n if (tileCost === 0) continue;\n\n // For diagonal movement, check that both cardinal neighbors are walkable (corner-cutting)\n if (diagonal && d & 1) {\n const dx = dirX[d]!;\n const dy = dirY[d]!;\n if (!isWalkable(grid, cx + dx, cy) || !isWalkable(grid, cx, cy + dy)) continue;\n }\n\n const moveCost = dirCost ? dirCost[d]! * tileCost : tileCost;\n const tentativeG = currentG + moveCost;\n\n if (tentativeG < g[nIdx]!) {\n g[nIdx] = tentativeG;\n cameFrom[nIdx] = currentIdx;\n const f = tentativeG + heuristic(nx, ny, ex, ey);\n heapPush(heap, f, nIdx);\n }\n }\n }\n\n return null;\n}\n\nfunction reconstructPath(\n cameFrom: Int32Array,\n w: number,\n endIdx: number,\n cost: number,\n explored: number,\n): PathResult {\n const path: { x: number; y: number }[] = [];\n let idx = endIdx;\n while (idx !== -1) {\n path.push({ x: idx % w, y: (idx / w) | 0 });\n idx = cameFrom[idx]!;\n }\n path.reverse();\n return { path, cost, explored };\n}\n","/**\n * Jump Point Search — an optimization over A* for uniform-cost grids.\n * Only works when all walkable tiles have cost 1. Falls back to A* behavior\n * if weighted costs are detected.\n *\n * JPS prunes symmetric paths by \"jumping\" along directions until hitting\n * a wall, the goal, or a forced neighbor.\n */\n\nimport type { PathResult } from './astar.js';\nimport { octileDistance } from './astar.js';\nimport type { Grid } from './grid.js';\nimport { isWalkable } from './grid.js';\n\n// ─── Binary min-heap (duplicated from astar for tree-shakeability) ─\n\ninterface Heap {\n f: Float64Array;\n idx: Int32Array;\n size: number;\n}\n\nfunction heapCreate(capacity: number): Heap {\n return {\n f: new Float64Array(capacity),\n idx: new Int32Array(capacity),\n size: 0,\n };\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n let i = h.size++;\n h.f[i] = f;\n h.idx[i] = nodeIdx;\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (h.f[parent]! <= h.f[i]!) break;\n const tf = h.f[parent]!;\n const ti = h.idx[parent]!;\n h.f[parent] = h.f[i]!;\n h.idx[parent] = h.idx[i]!;\n h.f[i] = tf;\n h.idx[i] = ti;\n i = parent;\n }\n}\n\nfunction heapPop(h: Heap): number {\n const result = h.idx[0]!;\n h.size--;\n if (h.size > 0) {\n h.f[0] = h.f[h.size]!;\n h.idx[0] = h.idx[h.size]!;\n let i = 0;\n for (;;) {\n let smallest = i;\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n if (left < h.size && h.f[left]! < h.f[smallest]!) smallest = left;\n if (right < h.size && h.f[right]! < h.f[smallest]!) smallest = right;\n if (smallest === i) break;\n const tf = h.f[i]!;\n const ti = h.idx[i]!;\n h.f[i] = h.f[smallest]!;\n h.idx[i] = h.idx[smallest]!;\n h.f[smallest] = tf;\n h.idx[smallest] = ti;\n i = smallest;\n }\n }\n return result;\n}\n\n// ─── JPS ─────────────────────────────────────────────────────────\n\nconst SQRT2 = Math.SQRT2;\n\nexport interface JpsOptions {\n /** Max nodes to explore before giving up. Default: width * height. */\n maxIterations?: number;\n /** Custom heuristic. Default: octile distance. */\n heuristic?: (ax: number, ay: number, bx: number, by: number) => number;\n}\n\nexport function findPathJPS(\n grid: Grid,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: JpsOptions,\n): PathResult | null {\n const sx = startX | 0;\n const sy = startY | 0;\n const ex = endX | 0;\n const ey = endY | 0;\n\n if (!isWalkable(grid, sx, sy) || !isWalkable(grid, ex, ey)) return null;\n if (sx === ex && sy === ey) return { path: [{ x: sx, y: sy }], cost: 0, explored: 0 };\n\n const w = grid.width;\n const h = grid.height;\n const total = w * h;\n const maxIter = options?.maxIterations ?? total;\n const heuristic = options?.heuristic ?? octileDistance;\n\n const g = new Float64Array(total);\n g.fill(Number.POSITIVE_INFINITY);\n const closed = new Uint8Array(total);\n const cameFrom = new Int32Array(total);\n cameFrom.fill(-1);\n\n const startIdx = sy * w + sx;\n const endIdx = ey * w + ex;\n g[startIdx] = 0;\n\n const heap = heapCreate(Math.min(total, 4096));\n heapPush(heap, heuristic(sx, sy, ex, ey), startIdx);\n\n let explored = 0;\n\n while (heap.size > 0 && explored < maxIter) {\n const currentIdx = heapPop(heap);\n if (currentIdx === endIdx) {\n return buildPath(cameFrom, w, currentIdx, g[currentIdx]!, explored);\n }\n if (closed[currentIdx]) continue;\n closed[currentIdx] = 1;\n explored++;\n\n const cx = currentIdx % w;\n const cy = (currentIdx / w) | 0;\n\n const neighbors = identifySuccessors(grid, cx, cy, cameFrom, w, h, ex, ey);\n for (let i = 0; i < neighbors.length; i += 2) {\n const nx = neighbors[i]!;\n const ny = neighbors[i + 1]!;\n const nIdx = ny * w + nx;\n if (closed[nIdx]) continue;\n\n const dx = Math.abs(nx - cx);\n const dy = Math.abs(ny - cy);\n const diag = Math.min(dx, dy);\n const straight = Math.abs(dx - dy);\n const dist = diag * SQRT2 + straight;\n const tentativeG = g[currentIdx]! + dist;\n if (tentativeG < g[nIdx]!) {\n g[nIdx] = tentativeG;\n cameFrom[nIdx] = currentIdx;\n heapPush(heap, tentativeG + heuristic(nx, ny, ex, ey), nIdx);\n }\n }\n }\n\n return null;\n}\n\nfunction identifySuccessors(\n grid: Grid,\n cx: number,\n cy: number,\n cameFrom: Int32Array,\n w: number,\n h: number,\n ex: number,\n ey: number,\n): number[] {\n const results: number[] = [];\n const parentIdx = cameFrom[cy * w + cx]!;\n\n if (parentIdx === -1) {\n // Start node: explore all 8 directions\n for (let dx = -1; dx <= 1; dx++) {\n for (let dy = -1; dy <= 1; dy++) {\n if (dx === 0 && dy === 0) continue;\n const jp = jump(grid, cx, cy, dx, dy, w, h, ex, ey);\n if (jp !== -1) {\n results.push(jp % w, (jp / w) | 0);\n }\n }\n }\n } else {\n const px = parentIdx % w;\n const py = (parentIdx / w) | 0;\n const dx = clampDir(cx - px);\n const dy = clampDir(cy - py);\n\n if (dx !== 0 && dy !== 0) {\n // Diagonal move: check straight and diagonal successors\n if (isWalkable(grid, cx, cy + dy)) {\n const jp = jump(grid, cx, cy, 0, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (isWalkable(grid, cx + dx, cy)) {\n const jp = jump(grid, cx, cy, dx, 0, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (isWalkable(grid, cx + dx, cy + dy)) {\n const jp = jump(grid, cx, cy, dx, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n // Forced neighbors\n if (!isWalkable(grid, cx - dx, cy) && isWalkable(grid, cx - dx, cy + dy)) {\n const jp = jump(grid, cx, cy, -dx, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy - dy) && isWalkable(grid, cx + dx, cy - dy)) {\n const jp = jump(grid, cx, cy, dx, -dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n } else if (dx !== 0) {\n // Horizontal move\n if (isWalkable(grid, cx + dx, cy)) {\n const jp = jump(grid, cx, cy, dx, 0, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy + 1) && isWalkable(grid, cx + dx, cy + 1)) {\n const jp = jump(grid, cx, cy, dx, 1, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy - 1) && isWalkable(grid, cx + dx, cy - 1)) {\n const jp = jump(grid, cx, cy, dx, -1, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n } else {\n // Vertical move\n if (isWalkable(grid, cx, cy + dy)) {\n const jp = jump(grid, cx, cy, 0, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx + 1, cy) && isWalkable(grid, cx + 1, cy + dy)) {\n const jp = jump(grid, cx, cy, 1, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx - 1, cy) && isWalkable(grid, cx - 1, cy + dy)) {\n const jp = jump(grid, cx, cy, -1, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n }\n }\n\n return results;\n}\n\nfunction jump(\n grid: Grid,\n cx: number,\n cy: number,\n dx: number,\n dy: number,\n w: number,\n h: number,\n ex: number,\n ey: number,\n): number {\n const nx = cx + dx;\n const ny = cy + dy;\n\n if (!isWalkable(grid, nx, ny)) return -1;\n if (nx === ex && ny === ey) return ny * w + nx;\n\n // Forced neighbor check\n if (dx !== 0 && dy !== 0) {\n // Diagonal\n if (\n (!isWalkable(grid, nx - dx, ny) && isWalkable(grid, nx - dx, ny + dy)) ||\n (!isWalkable(grid, nx, ny - dy) && isWalkable(grid, nx + dx, ny - dy))\n ) {\n return ny * w + nx;\n }\n // Recurse in cardinal directions\n if (jump(grid, nx, ny, dx, 0, w, h, ex, ey) !== -1) return ny * w + nx;\n if (jump(grid, nx, ny, 0, dy, w, h, ex, ey) !== -1) return ny * w + nx;\n } else if (dx !== 0) {\n // Horizontal\n if (\n (!isWalkable(grid, nx, ny + 1) && isWalkable(grid, nx + dx, ny + 1)) ||\n (!isWalkable(grid, nx, ny - 1) && isWalkable(grid, nx + dx, ny - 1))\n ) {\n return ny * w + nx;\n }\n } else {\n // Vertical\n if (\n (!isWalkable(grid, nx + 1, ny) && isWalkable(grid, nx + 1, ny + dy)) ||\n (!isWalkable(grid, nx - 1, ny) && isWalkable(grid, nx - 1, ny + dy))\n ) {\n return ny * w + nx;\n }\n }\n\n // Keep jumping (iterative for cardinal, recursive for diagonal via identifySuccessors)\n return jump(grid, nx, ny, dx, dy, w, h, ex, ey);\n}\n\nfunction clampDir(v: number): number {\n return v > 0 ? 1 : v < 0 ? -1 : 0;\n}\n\nfunction buildPath(\n cameFrom: Int32Array,\n w: number,\n endIdx: number,\n cost: number,\n explored: number,\n): PathResult {\n // JPS produces jump points — we interpolate the full path\n const jumpPoints: number[] = [];\n let idx = endIdx;\n while (idx !== -1) {\n jumpPoints.push(idx);\n idx = cameFrom[idx]!;\n }\n jumpPoints.reverse();\n\n const path: { x: number; y: number }[] = [];\n for (let i = 0; i < jumpPoints.length; i++) {\n const jpIdx = jumpPoints[i]!;\n const jx = jpIdx % w;\n const jy = (jpIdx / w) | 0;\n if (i === 0) {\n path.push({ x: jx, y: jy });\n } else {\n const prev = path[path.length - 1]!;\n // Interpolate from prev to current jump point\n let cx = prev.x;\n let cy = prev.y;\n while (cx !== jx || cy !== jy) {\n if (cx < jx) cx++;\n else if (cx > jx) cx--;\n if (cy < jy) cy++;\n else if (cy > jy) cy--;\n path.push({ x: cx, y: cy });\n }\n }\n }\n\n return { path, cost, explored };\n}\n","/**\n * Lightweight navmesh pathfinding for polygon-based environments.\n * Supports convex polygon navigation with A* over the polygon graph\n * and the Simple Stupid Funnel Algorithm for path smoothing.\n */\n\nimport type { Vec2 } from '@flare-engine/math';\n\n// ─── Types ───────────────────────────────────────────────────────\n\nexport interface NavMeshPolygon {\n readonly id: number;\n /** Convex polygon vertices in winding order. */\n readonly vertices: readonly Vec2[];\n /** Ids of neighboring polygons (sharing an edge). */\n readonly neighbors: readonly number[];\n /** Shared edge per neighbor: [neighborId] → { a, b } portal endpoints. */\n readonly portals: readonly Portal[];\n}\n\nexport interface Portal {\n /** Neighbor polygon id. */\n neighborId: number;\n /** Left endpoint of the shared edge (from the perspective of travel). */\n a: Vec2;\n /** Right endpoint of the shared edge. */\n b: Vec2;\n}\n\nexport interface NavMesh {\n readonly polygons: readonly NavMeshPolygon[];\n}\n\nexport interface NavMeshPathResult {\n /** Smoothed world-space waypoints. */\n path: Vec2[];\n /** Polygon ids traversed. */\n corridor: number[];\n}\n\n// ─── Construction ────────────────────────────────────────────────\n\nexport function createNavMesh(polygons: NavMeshPolygon[]): NavMesh {\n return { polygons };\n}\n\n// ─── Point-in-polygon ────────────────────────────────────────────\n\nfunction pointInConvexPolygon(verts: readonly Vec2[], px: number, py: number): boolean {\n const n = verts.length;\n if (n < 3) return false;\n let sign = 0;\n for (let i = 0; i < n; i++) {\n const a = verts[i]!;\n const b = verts[(i + 1) % n]!;\n const cross = (b.x - a.x) * (py - a.y) - (b.y - a.y) * (px - a.x);\n if (cross !== 0) {\n const s = cross > 0 ? 1 : -1;\n if (sign === 0) sign = s;\n else if (sign !== s) return false;\n }\n }\n return true;\n}\n\nexport function findPolygonAt(mesh: NavMesh, x: number, y: number): number {\n for (let i = 0; i < mesh.polygons.length; i++) {\n if (pointInConvexPolygon(mesh.polygons[i]!.vertices, x, y)) {\n return mesh.polygons[i]!.id;\n }\n }\n return -1;\n}\n\n// ─── Polygon centroid ────────────────────────────────────────────\n\nfunction centroid(verts: readonly Vec2[]): Vec2 {\n let cx = 0;\n let cy = 0;\n for (let i = 0; i < verts.length; i++) {\n cx += verts[i]!.x;\n cy += verts[i]!.y;\n }\n const n = verts.length;\n return { x: cx / n, y: cy / n };\n}\n\n// ─── A* over polygon graph ───────────────────────────────────────\n\nfunction distSq(ax: number, ay: number, bx: number, by: number): number {\n const dx = ax - bx;\n const dy = ay - by;\n return dx * dx + dy * dy;\n}\n\nfunction dist(ax: number, ay: number, bx: number, by: number): number {\n return Math.sqrt(distSq(ax, ay, bx, by));\n}\n\nexport function findNavMeshPath(mesh: NavMesh, start: Vec2, end: Vec2): NavMeshPathResult | null {\n const startPolyId = findPolygonAt(mesh, start.x, start.y);\n const endPolyId = findPolygonAt(mesh, end.x, end.y);\n if (startPolyId === -1 || endPolyId === -1) return null;\n if (startPolyId === endPolyId) {\n return {\n path: [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ],\n corridor: [startPolyId],\n };\n }\n\n // Build index: id → polygon\n const byId = new Map<number, NavMeshPolygon>();\n for (let i = 0; i < mesh.polygons.length; i++) {\n const p = mesh.polygons[i]!;\n byId.set(p.id, p);\n }\n\n // A* on polygon graph\n const gScore = new Map<number, number>();\n const fScore = new Map<number, number>();\n const cameFrom = new Map<number, number>();\n\n gScore.set(startPolyId, 0);\n\n const endPoly = byId.get(endPolyId)!;\n const endCenter = centroid(endPoly.vertices);\n const startPoly = byId.get(startPolyId)!;\n const startCenter = centroid(startPoly.vertices);\n\n fScore.set(startPolyId, dist(startCenter.x, startCenter.y, endCenter.x, endCenter.y));\n\n // Simple array-based open set (fine for typical navmeshes with <1000 polygons)\n const open: number[] = [startPolyId];\n const inOpen = new Set<number>([startPolyId]);\n const closed = new Set<number>();\n\n while (open.length > 0) {\n // Find lowest f-score\n let bestI = 0;\n let bestF = fScore.get(open[0]!) ?? Number.POSITIVE_INFINITY;\n for (let i = 1; i < open.length; i++) {\n const f = fScore.get(open[i]!) ?? Number.POSITIVE_INFINITY;\n if (f < bestF) {\n bestF = f;\n bestI = i;\n }\n }\n const currentId = open[bestI]!;\n\n if (currentId === endPolyId) {\n // Reconstruct corridor\n const corridor: number[] = [];\n let id: number | undefined = endPolyId;\n while (id !== undefined) {\n corridor.push(id);\n id = cameFrom.get(id);\n }\n corridor.reverse();\n const path = funnelSmooth(mesh, byId, corridor, start, end);\n return { path, corridor };\n }\n\n // Remove from open\n open[bestI] = open[open.length - 1]!;\n open.length--;\n inOpen.delete(currentId);\n closed.add(currentId);\n\n const current = byId.get(currentId)!;\n const currentCenter = centroid(current.vertices);\n const currentG = gScore.get(currentId)!;\n\n for (let i = 0; i < current.portals.length; i++) {\n const portal = current.portals[i]!;\n const neighborId = portal.neighborId;\n if (closed.has(neighborId)) continue;\n\n const neighbor = byId.get(neighborId);\n if (!neighbor) continue;\n\n const portalMidX = (portal.a.x + portal.b.x) * 0.5;\n const portalMidY = (portal.a.y + portal.b.y) * 0.5;\n const tentativeG = currentG + dist(currentCenter.x, currentCenter.y, portalMidX, portalMidY);\n\n const prevG = gScore.get(neighborId);\n if (prevG !== undefined && tentativeG >= prevG) continue;\n\n gScore.set(neighborId, tentativeG);\n cameFrom.set(neighborId, currentId);\n\n const neighborCenter = centroid(neighbor.vertices);\n fScore.set(\n neighborId,\n tentativeG + dist(neighborCenter.x, neighborCenter.y, endCenter.x, endCenter.y),\n );\n\n if (!inOpen.has(neighborId)) {\n open.push(neighborId);\n inOpen.add(neighborId);\n }\n }\n }\n\n return null;\n}\n\n// ─── Simple Stupid Funnel Algorithm ──────────────────────────────\n\nfunction funnelSmooth(\n _mesh: NavMesh,\n byId: Map<number, NavMeshPolygon>,\n corridor: number[],\n start: Vec2,\n end: Vec2,\n): Vec2[] {\n if (corridor.length <= 1) {\n return [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ];\n }\n\n // Build portal list from corridor\n const portalsLeft: Vec2[] = [];\n const portalsRight: Vec2[] = [];\n\n portalsLeft.push({ x: start.x, y: start.y });\n portalsRight.push({ x: start.x, y: start.y });\n\n for (let i = 0; i < corridor.length - 1; i++) {\n const poly = byId.get(corridor[i]!)!;\n const nextId = corridor[i + 1]!;\n // Find the portal to the next polygon\n let found = false;\n for (let j = 0; j < poly.portals.length; j++) {\n if (poly.portals[j]!.neighborId === nextId) {\n portalsLeft.push(poly.portals[j]!.a);\n portalsRight.push(poly.portals[j]!.b);\n found = true;\n break;\n }\n }\n if (!found) {\n // Fallback: straight line through centroids\n const c = centroid(poly.vertices);\n portalsLeft.push(c);\n portalsRight.push(c);\n }\n }\n\n portalsLeft.push({ x: end.x, y: end.y });\n portalsRight.push({ x: end.x, y: end.y });\n\n // Simple Stupid Funnel Algorithm (Mononen)\n // Walk the portal list and maintain a funnel (apex, left, right).\n const path: Vec2[] = [];\n\n let apexPt = portalsLeft[0]!; // start point\n let leftPt = portalsLeft[0]!;\n let rightPt = portalsRight[0]!;\n let apexIdx = 0;\n let leftIdx = 0;\n let rightIdx = 0;\n\n path.push({ x: apexPt.x, y: apexPt.y });\n\n const n = portalsLeft.length;\n\n for (let i = 1; i < n; i++) {\n const pL = portalsLeft[i]!;\n const pR = portalsRight[i]!;\n\n // Try to tighten the right side\n if (triArea2(apexPt, rightPt, pR) <= 0) {\n if (vEqual(apexPt, rightPt) || triArea2(apexPt, leftPt, pR) > 0) {\n // Tighten\n rightPt = pR;\n rightIdx = i;\n } else {\n // Right crossed over left → left becomes new apex\n addUnique(path, leftPt);\n apexPt = leftPt;\n apexIdx = leftIdx;\n // Reset funnel\n leftPt = apexPt;\n rightPt = apexPt;\n leftIdx = apexIdx;\n rightIdx = apexIdx;\n // Restart scan from the portal after the new apex\n i = apexIdx;\n continue;\n }\n }\n\n // Try to tighten the left side\n if (triArea2(apexPt, leftPt, pL) >= 0) {\n if (vEqual(apexPt, leftPt) || triArea2(apexPt, rightPt, pL) < 0) {\n // Tighten\n leftPt = pL;\n leftIdx = i;\n } else {\n // Left crossed over right → right becomes new apex\n addUnique(path, rightPt);\n apexPt = rightPt;\n apexIdx = rightIdx;\n // Reset funnel\n leftPt = apexPt;\n rightPt = apexPt;\n leftIdx = apexIdx;\n rightIdx = apexIdx;\n // Restart scan from the portal after the new apex\n i = apexIdx;\n }\n }\n }\n\n addUnique(path, end);\n\n return path;\n}\n\nfunction addUnique(path: Vec2[], p: Vec2): void {\n const last = path[path.length - 1];\n if (!last || last.x !== p.x || last.y !== p.y) {\n path.push({ x: p.x, y: p.y });\n }\n}\n\n/** Twice the signed area of the triangle (a, b, c). Positive = CCW. */\nfunction triArea2(a: Vec2, b: Vec2, c: Vec2): number {\n return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);\n}\n\nfunction vEqual(a: Vec2, b: Vec2): boolean {\n return a.x === b.x && a.y === b.y;\n}\n"],"mappings":"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"}
|