@flare-engine/pathfinding 0.4.6 → 0.4.7

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/dist/index.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Vec2 } from "@flare-engine/math";
2
- //#region src/grid.d.ts
3
2
  /**
4
3
  * Grid data structure for tile-based pathfinding.
5
4
  * Uses a flat Uint8Array: 0 = blocked, 1+ = walkable (value = movement cost).
@@ -17,14 +16,12 @@ interface GridConfig {
17
16
  /** Default cost for all cells when `data` is not provided. 0 = blocked, 1+ = walkable cost. Default 1. */
18
17
  defaultCost?: number;
19
18
  }
20
- declare function createGrid(config: GridConfig): Grid;
21
- declare function inBounds(grid: Grid, x: number, y: number): boolean;
22
- declare function isWalkable(grid: Grid, x: number, y: number): boolean;
23
- declare function getCost(grid: Grid, x: number, y: number): number;
24
- declare function setWalkable(grid: Grid, x: number, y: number, walkable: boolean): void;
25
- declare function setCost(grid: Grid, x: number, y: number, cost: number): void;
26
- //#endregion
27
- //#region src/astar.d.ts
19
+ export declare function createGrid(config: GridConfig): Grid;
20
+ export declare function inBounds(grid: Grid, x: number, y: number): boolean;
21
+ export declare function isWalkable(grid: Grid, x: number, y: number): boolean;
22
+ export declare function getCost(grid: Grid, x: number, y: number): number;
23
+ export declare function setWalkable(grid: Grid, x: number, y: number, walkable: boolean): void;
24
+ export declare function setCost(grid: Grid, x: number, y: number, cost: number): void;
28
25
  interface PathResult {
29
26
  /** Grid coordinates from start to end, inclusive. */
30
27
  path: {
@@ -44,22 +41,18 @@ interface PathOptions {
44
41
  /** Max nodes to explore before giving up. Default: width * height. */
45
42
  maxIterations?: number;
46
43
  }
47
- declare function manhattanDistance(ax: number, ay: number, bx: number, by: number): number;
48
- declare function octileDistance(ax: number, ay: number, bx: number, by: number): number;
49
- declare function chebyshevDistance(ax: number, ay: number, bx: number, by: number): number;
50
- declare function euclideanDistance(ax: number, ay: number, bx: number, by: number): number;
51
- declare function findPath(grid: Grid, startX: number, startY: number, endX: number, endY: number, options?: PathOptions): PathResult | null;
52
- //#endregion
53
- //#region src/jps.d.ts
44
+ export declare function manhattanDistance(ax: number, ay: number, bx: number, by: number): number;
45
+ export declare function octileDistance(ax: number, ay: number, bx: number, by: number): number;
46
+ export declare function chebyshevDistance(ax: number, ay: number, bx: number, by: number): number;
47
+ export declare function euclideanDistance(ax: number, ay: number, bx: number, by: number): number;
48
+ export declare function findPath(grid: Grid, startX: number, startY: number, endX: number, endY: number, options?: PathOptions): PathResult | null;
54
49
  interface JpsOptions {
55
50
  /** Max nodes to explore before giving up. Default: width * height. */
56
51
  maxIterations?: number;
57
52
  /** Custom heuristic. Default: octile distance. */
58
53
  heuristic?: (ax: number, ay: number, bx: number, by: number) => number;
59
54
  }
60
- declare function findPathJPS(grid: Grid, startX: number, startY: number, endX: number, endY: number, options?: JpsOptions): PathResult | null;
61
- //#endregion
62
- //#region src/navmesh.d.ts
55
+ export declare function findPathJPS(grid: Grid, startX: number, startY: number, endX: number, endY: number, options?: JpsOptions): PathResult | null;
63
56
  interface NavMeshPolygon {
64
57
  readonly id: number;
65
58
  /** Convex polygon vertices in winding order. */
@@ -84,9 +77,8 @@ interface NavMeshPathResult {
84
77
  /** Polygon ids traversed. */
85
78
  corridor: number[];
86
79
  }
87
- declare function createNavMesh(polygons: NavMeshPolygon[]): NavMesh;
88
- declare function findPolygonAt(mesh: NavMesh, x: number, y: number): number;
89
- declare function findNavMeshPath(mesh: NavMesh, start: Vec2, end: Vec2): NavMeshPathResult | null;
90
- //#endregion
91
- export { type Grid, type GridConfig, type JpsOptions, type NavMesh, type NavMeshPathResult, type NavMeshPolygon, type PathOptions, type PathResult, type Portal, chebyshevDistance, createGrid, createNavMesh, euclideanDistance, findNavMeshPath, findPath, findPathJPS, findPolygonAt, getCost, inBounds, isWalkable, manhattanDistance, octileDistance, setCost, setWalkable };
80
+ export declare function createNavMesh(polygons: NavMeshPolygon[]): NavMesh;
81
+ export declare function findPolygonAt(mesh: NavMesh, x: number, y: number): number;
82
+ export declare function findNavMeshPath(mesh: NavMesh, start: Vec2, end: Vec2): NavMeshPathResult | null;
83
+ export type { Grid, GridConfig, JpsOptions, NavMesh, NavMeshPathResult, NavMeshPolygon, PathOptions, PathResult, Portal };
92
84
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/grid.ts","../src/astar.ts","../src/jps.ts","../src/navmesh.ts"],"mappings":";;;;;;UAKiB;WACN;WACA;WACA,MAAM;;UAGA;EACf;EACA;;EAEA,OAAO;;EAEP;;iBAGc,WAAW,QAAQ,aAAa;iBAsBhC,SAAS,MAAM,MAAM,WAAW;iBAIhC,WAAW,MAAM,MAAM,WAAW;iBAKlC,QAAQ,MAAM,MAAM,WAAW;iBAK/B,YAAY,MAAM,MAAM,WAAW,WAAW;iBAK9C,QAAQ,MAAM,MAAM,WAAW,WAAW;;;UCrDzC;;EAEf;IAAQ;IAAW;;;EAEnB;;EAEA;;UAGe;;EAEf;;EAEA,aAAa,YAAY,YAAY,YAAY;;EAEjD;;iBAOc,kBAAkB,YAAY,YAAY,YAAY;iBAItD,eAAe,YAAY,YAAY,YAAY;iBAMnD,kBAAkB,YAAY,YAAY,YAAY;iBAItD,kBAAkB,YAAY,YAAY,YAAY;iBAwGtD,SACd,MAAM,MACN,gBACA,gBACA,cACA,cACA,UAAU,cACT;;;UC/Cc;;EAEf;;EAEA,aAAa,YAAY,YAAY,YAAY;;iBAGnC,YACd,MAAM,MACN,gBACA,gBACA,cACA,cACA,UAAU,aACT;;;UChHc;WACN;;WAEA,mBAAmB;;WAEnB,kBAAkB;;UAGZ;;EAEf;;EAEA,GAAG;;EAEH,GAAG;;UAGY;WACN,mBAAmB;;UAGb;;EAEf,MAAM;;EAEN;;iBAKc,cAAc,UAAU,mBAAmB;iBAuB3C,cAAc,MAAM,SAAS,WAAW;iBAkCxC,gBAAgB,MAAM,SAAS,OAAO,MAAM,KAAK,OAAO"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/grid.ts","../src/astar.ts","../src/jps.ts","../src/navmesh.ts"],"mappings":";;;;;UAKiB;WACN;WACA;WACA,MAAM;;UAGA;EACf;EACA;;EAEA,OAAO;;EAEP;;wBAGc,WAAW,QAAQ,aAAa;wBAsBhC,SAAS,MAAM,MAAM,WAAW;wBAIhC,WAAW,MAAM,MAAM,WAAW;wBAKlC,QAAQ,MAAM,MAAM,WAAW;wBAK/B,YAAY,MAAM,MAAM,WAAW,WAAW;wBAK9C,QAAQ,MAAM,MAAM,WAAW,WAAW;UCrDzC;;EAEf;IAAQ;IAAW;;;EAEnB;;EAEA;;UAGe;;EAEf;;EAEA,aAAa,YAAY,YAAY,YAAY;;EAEjD;;wBAOc,kBAAkB,YAAY,YAAY,YAAY;wBAItD,eAAe,YAAY,YAAY,YAAY;wBAMnD,kBAAkB,YAAY,YAAY,YAAY;wBAItD,kBAAkB,YAAY,YAAY,YAAY;wBAwGtD,SACd,MAAM,MACN,gBACA,gBACA,cACA,cACA,UAAU,cACT;UC/Cc;;EAEf;;EAEA,aAAa,YAAY,YAAY,YAAY;;wBAGnC,YACd,MAAM,MACN,gBACA,gBACA,cACA,cACA,UAAU,aACT;UChHc;WACN;;WAEA,mBAAmB;;WAEnB,kBAAkB;;UAGZ;;EAEf;;EAEA,GAAG;;EAEH,GAAG;;UAGY;WACN,mBAAmB;;UAGb;;EAEf,MAAM;;EAEN;;wBAKc,cAAc,UAAU,mBAAmB;wBAuB3C,cAAc,MAAM,SAAS,WAAW;wBAkCxC,gBAAgB,MAAM,SAAS,OAAO,MAAM,KAAK,OAAO"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { Vec2 } from "@flare-engine/math";
2
- //#region src/grid.d.ts
3
2
  /**
4
3
  * Grid data structure for tile-based pathfinding.
5
4
  * Uses a flat Uint8Array: 0 = blocked, 1+ = walkable (value = movement cost).
@@ -17,14 +16,12 @@ interface GridConfig {
17
16
  /** Default cost for all cells when `data` is not provided. 0 = blocked, 1+ = walkable cost. Default 1. */
18
17
  defaultCost?: number;
19
18
  }
20
- declare function createGrid(config: GridConfig): Grid;
21
- declare function inBounds(grid: Grid, x: number, y: number): boolean;
22
- declare function isWalkable(grid: Grid, x: number, y: number): boolean;
23
- declare function getCost(grid: Grid, x: number, y: number): number;
24
- declare function setWalkable(grid: Grid, x: number, y: number, walkable: boolean): void;
25
- declare function setCost(grid: Grid, x: number, y: number, cost: number): void;
26
- //#endregion
27
- //#region src/astar.d.ts
19
+ export declare function createGrid(config: GridConfig): Grid;
20
+ export declare function inBounds(grid: Grid, x: number, y: number): boolean;
21
+ export declare function isWalkable(grid: Grid, x: number, y: number): boolean;
22
+ export declare function getCost(grid: Grid, x: number, y: number): number;
23
+ export declare function setWalkable(grid: Grid, x: number, y: number, walkable: boolean): void;
24
+ export declare function setCost(grid: Grid, x: number, y: number, cost: number): void;
28
25
  interface PathResult {
29
26
  /** Grid coordinates from start to end, inclusive. */
30
27
  path: {
@@ -44,22 +41,18 @@ interface PathOptions {
44
41
  /** Max nodes to explore before giving up. Default: width * height. */
45
42
  maxIterations?: number;
46
43
  }
47
- declare function manhattanDistance(ax: number, ay: number, bx: number, by: number): number;
48
- declare function octileDistance(ax: number, ay: number, bx: number, by: number): number;
49
- declare function chebyshevDistance(ax: number, ay: number, bx: number, by: number): number;
50
- declare function euclideanDistance(ax: number, ay: number, bx: number, by: number): number;
51
- declare function findPath(grid: Grid, startX: number, startY: number, endX: number, endY: number, options?: PathOptions): PathResult | null;
52
- //#endregion
53
- //#region src/jps.d.ts
44
+ export declare function manhattanDistance(ax: number, ay: number, bx: number, by: number): number;
45
+ export declare function octileDistance(ax: number, ay: number, bx: number, by: number): number;
46
+ export declare function chebyshevDistance(ax: number, ay: number, bx: number, by: number): number;
47
+ export declare function euclideanDistance(ax: number, ay: number, bx: number, by: number): number;
48
+ export declare function findPath(grid: Grid, startX: number, startY: number, endX: number, endY: number, options?: PathOptions): PathResult | null;
54
49
  interface JpsOptions {
55
50
  /** Max nodes to explore before giving up. Default: width * height. */
56
51
  maxIterations?: number;
57
52
  /** Custom heuristic. Default: octile distance. */
58
53
  heuristic?: (ax: number, ay: number, bx: number, by: number) => number;
59
54
  }
60
- declare function findPathJPS(grid: Grid, startX: number, startY: number, endX: number, endY: number, options?: JpsOptions): PathResult | null;
61
- //#endregion
62
- //#region src/navmesh.d.ts
55
+ export declare function findPathJPS(grid: Grid, startX: number, startY: number, endX: number, endY: number, options?: JpsOptions): PathResult | null;
63
56
  interface NavMeshPolygon {
64
57
  readonly id: number;
65
58
  /** Convex polygon vertices in winding order. */
@@ -84,9 +77,8 @@ interface NavMeshPathResult {
84
77
  /** Polygon ids traversed. */
85
78
  corridor: number[];
86
79
  }
87
- declare function createNavMesh(polygons: NavMeshPolygon[]): NavMesh;
88
- declare function findPolygonAt(mesh: NavMesh, x: number, y: number): number;
89
- declare function findNavMeshPath(mesh: NavMesh, start: Vec2, end: Vec2): NavMeshPathResult | null;
90
- //#endregion
91
- export { type Grid, type GridConfig, type JpsOptions, type NavMesh, type NavMeshPathResult, type NavMeshPolygon, type PathOptions, type PathResult, type Portal, chebyshevDistance, createGrid, createNavMesh, euclideanDistance, findNavMeshPath, findPath, findPathJPS, findPolygonAt, getCost, inBounds, isWalkable, manhattanDistance, octileDistance, setCost, setWalkable };
80
+ export declare function createNavMesh(polygons: NavMeshPolygon[]): NavMesh;
81
+ export declare function findPolygonAt(mesh: NavMesh, x: number, y: number): number;
82
+ export declare function findNavMeshPath(mesh: NavMesh, start: Vec2, end: Vec2): NavMeshPathResult | null;
83
+ export type { Grid, GridConfig, JpsOptions, NavMesh, NavMeshPathResult, NavMeshPolygon, PathOptions, PathResult, Portal };
92
84
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/grid.ts","../src/astar.ts","../src/jps.ts","../src/navmesh.ts"],"mappings":";;;;;;UAKiB;WACN;WACA;WACA,MAAM;;UAGA;EACf;EACA;;EAEA,OAAO;;EAEP;;iBAGc,WAAW,QAAQ,aAAa;iBAsBhC,SAAS,MAAM,MAAM,WAAW;iBAIhC,WAAW,MAAM,MAAM,WAAW;iBAKlC,QAAQ,MAAM,MAAM,WAAW;iBAK/B,YAAY,MAAM,MAAM,WAAW,WAAW;iBAK9C,QAAQ,MAAM,MAAM,WAAW,WAAW;;;UCrDzC;;EAEf;IAAQ;IAAW;;;EAEnB;;EAEA;;UAGe;;EAEf;;EAEA,aAAa,YAAY,YAAY,YAAY;;EAEjD;;iBAOc,kBAAkB,YAAY,YAAY,YAAY;iBAItD,eAAe,YAAY,YAAY,YAAY;iBAMnD,kBAAkB,YAAY,YAAY,YAAY;iBAItD,kBAAkB,YAAY,YAAY,YAAY;iBAwGtD,SACd,MAAM,MACN,gBACA,gBACA,cACA,cACA,UAAU,cACT;;;UC/Cc;;EAEf;;EAEA,aAAa,YAAY,YAAY,YAAY;;iBAGnC,YACd,MAAM,MACN,gBACA,gBACA,cACA,cACA,UAAU,aACT;;;UChHc;WACN;;WAEA,mBAAmB;;WAEnB,kBAAkB;;UAGZ;;EAEf;;EAEA,GAAG;;EAEH,GAAG;;UAGY;WACN,mBAAmB;;UAGb;;EAEf,MAAM;;EAEN;;iBAKc,cAAc,UAAU,mBAAmB;iBAuB3C,cAAc,MAAM,SAAS,WAAW;iBAkCxC,gBAAgB,MAAM,SAAS,OAAO,MAAM,KAAK,OAAO"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/grid.ts","../src/astar.ts","../src/jps.ts","../src/navmesh.ts"],"mappings":";;;;;UAKiB;WACN;WACA;WACA,MAAM;;UAGA;EACf;EACA;;EAEA,OAAO;;EAEP;;wBAGc,WAAW,QAAQ,aAAa;wBAsBhC,SAAS,MAAM,MAAM,WAAW;wBAIhC,WAAW,MAAM,MAAM,WAAW;wBAKlC,QAAQ,MAAM,MAAM,WAAW;wBAK/B,YAAY,MAAM,MAAM,WAAW,WAAW;wBAK9C,QAAQ,MAAM,MAAM,WAAW,WAAW;UCrDzC;;EAEf;IAAQ;IAAW;;;EAEnB;;EAEA;;UAGe;;EAEf;;EAEA,aAAa,YAAY,YAAY,YAAY;;EAEjD;;wBAOc,kBAAkB,YAAY,YAAY,YAAY;wBAItD,eAAe,YAAY,YAAY,YAAY;wBAMnD,kBAAkB,YAAY,YAAY,YAAY;wBAItD,kBAAkB,YAAY,YAAY,YAAY;wBAwGtD,SACd,MAAM,MACN,gBACA,gBACA,cACA,cACA,UAAU,cACT;UC/Cc;;EAEf;;EAEA,aAAa,YAAY,YAAY,YAAY;;wBAGnC,YACd,MAAM,MACN,gBACA,gBACA,cACA,cACA,UAAU,aACT;UChHc;WACN;;WAEA,mBAAmB;;WAEnB,kBAAkB;;UAGZ;;EAEf;;EAEA,GAAG;;EAEH,GAAG;;UAGY;WACN,mBAAmB;;UAGb;;EAEf,MAAM;;EAEN;;wBAKc,cAAc,UAAU,mBAAmB;wBAuB3C,cAAc,MAAM,SAAS,WAAW;wBAkCxC,gBAAgB,MAAM,SAAS,OAAO,MAAM,KAAK,OAAO"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region src/grid.ts
2
+ // src/grid.ts
3
3
  function createGrid(config) {
4
4
  const { width, height, defaultCost = 1 } = config;
5
5
  if (width <= 0 || height <= 0) throw new RangeError("Grid dimensions must be positive");
@@ -38,8 +38,7 @@ function setCost(grid, x, y, cost) {
38
38
  if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;
39
39
  grid.data[(y | 0) * grid.width + (x | 0)] = cost > 255 ? 255 : cost < 0 ? 0 : cost | 0;
40
40
  }
41
- //#endregion
42
- //#region src/astar.ts
41
+ // src/astar.ts
43
42
  const SQRT2$1 = Math.SQRT2;
44
43
  function manhattanDistance(ax, ay, bx, by) {
45
44
  return Math.abs(ax - bx) + Math.abs(ay - by);
@@ -250,8 +249,7 @@ function reconstructPath(cameFrom, w, endIdx, cost, explored) {
250
249
  explored
251
250
  };
252
251
  }
253
- //#endregion
254
- //#region src/jps.ts
252
+ // src/jps.ts
255
253
  function heapCreate(capacity) {
256
254
  return {
257
255
  f: new Float64Array(capacity),
@@ -509,8 +507,7 @@ function buildPath(cameFrom, w, endIdx, cost, explored) {
509
507
  explored
510
508
  };
511
509
  }
512
- //#endregion
513
- //#region src/navmesh.ts
510
+ // src/navmesh.ts
514
511
  function createNavMesh(polygons) {
515
512
  return { polygons };
516
513
  }
@@ -695,32 +692,36 @@ function funnelSmooth(_mesh, byId, corridor, start, end) {
695
692
  for (let i = 1; i < n; i++) {
696
693
  const pL = portalsLeft[i];
697
694
  const pR = portalsRight[i];
698
- if (triArea2(apexPt, rightPt, pR) <= 0) if (vEqual(apexPt, rightPt) || triArea2(apexPt, leftPt, pR) > 0) {
699
- rightPt = pR;
700
- rightIdx = i;
701
- } else {
702
- addUnique(path, leftPt);
703
- apexPt = leftPt;
704
- apexIdx = leftIdx;
705
- leftPt = apexPt;
706
- rightPt = apexPt;
707
- leftIdx = apexIdx;
708
- rightIdx = apexIdx;
709
- i = apexIdx;
710
- continue;
695
+ if (triArea2(apexPt, rightPt, pR) <= 0) {
696
+ if (vEqual(apexPt, rightPt) || triArea2(apexPt, leftPt, pR) > 0) {
697
+ rightPt = pR;
698
+ rightIdx = i;
699
+ } else {
700
+ addUnique(path, leftPt);
701
+ apexPt = leftPt;
702
+ apexIdx = leftIdx;
703
+ leftPt = apexPt;
704
+ rightPt = apexPt;
705
+ leftIdx = apexIdx;
706
+ rightIdx = apexIdx;
707
+ i = apexIdx;
708
+ continue;
709
+ }
711
710
  }
712
- if (triArea2(apexPt, leftPt, pL) >= 0) if (vEqual(apexPt, leftPt) || triArea2(apexPt, rightPt, pL) < 0) {
713
- leftPt = pL;
714
- leftIdx = i;
715
- } else {
716
- addUnique(path, rightPt);
717
- apexPt = rightPt;
718
- apexIdx = rightIdx;
719
- leftPt = apexPt;
720
- rightPt = apexPt;
721
- leftIdx = apexIdx;
722
- rightIdx = apexIdx;
723
- i = apexIdx;
711
+ if (triArea2(apexPt, leftPt, pL) >= 0) {
712
+ if (vEqual(apexPt, leftPt) || triArea2(apexPt, rightPt, pL) < 0) {
713
+ leftPt = pL;
714
+ leftIdx = i;
715
+ } else {
716
+ addUnique(path, rightPt);
717
+ apexPt = rightPt;
718
+ apexIdx = rightIdx;
719
+ leftPt = apexPt;
720
+ rightPt = apexPt;
721
+ leftIdx = apexIdx;
722
+ rightIdx = apexIdx;
723
+ i = apexIdx;
724
+ }
724
725
  }
725
726
  }
726
727
  addUnique(path, end);
@@ -740,7 +741,6 @@ function triArea2(a, b, c) {
740
741
  function vEqual(a, b) {
741
742
  return a.x === b.x && a.y === b.y;
742
743
  }
743
- //#endregion
744
744
  exports.chebyshevDistance = chebyshevDistance;
745
745
  exports.createGrid = createGrid;
746
746
  exports.createNavMesh = createNavMesh;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["SQRT2","heapCreate","heapGrow","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\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\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 * JPS pruning is only correct when every walkable tile costs 1, so a grid with\n * any tile cost above 1 is delegated to weighted A* (`findPath`, diagonal moves)\n * after one linear scan of `grid.data`.\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 { findPath, 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\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\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\n// One pass per call, never per node: JPS pruning assumes every walkable tile costs 1.\nfunction hasWeightedCost(grid: Grid): boolean {\n const data = grid.data;\n for (let i = 0; i < data.length; i++) {\n if (data[i]! > 1) return true;\n }\n return false;\n}\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 if (hasWeightedCost(grid)) {\n return findPath(grid, sx, sy, ex, ey, { ...options, diagonal: true });\n }\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 /** One `Portal` per adjacent polygon: the shared edge plus that neighbour's id. */\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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"}
1
+ {"version":3,"file":"index.js","names":["SQRT2","heapCreate","heapGrow","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\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\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 * JPS pruning is only correct when every walkable tile costs 1, so a grid with\n * any tile cost above 1 is delegated to weighted A* (`findPath`, diagonal moves)\n * after one linear scan of `grid.data`.\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 { findPath, 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\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\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\n// One pass per call, never per node: JPS pruning assumes every walkable tile costs 1.\nfunction hasWeightedCost(grid: Grid): boolean {\n const data = grid.data;\n for (let i = 0; i < data.length; i++) {\n if (data[i]! > 1) return true;\n }\n return false;\n}\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 if (hasWeightedCost(grid)) {\n return findPath(grid, sx, sy, ex, ey, { ...options, diagonal: true });\n }\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 /** One `Portal` per adjacent polygon: the shared edge plus that neighbour's id. */\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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"}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/grid.ts
1
+ // src/grid.ts
2
2
  function createGrid(config) {
3
3
  const { width, height, defaultCost = 1 } = config;
4
4
  if (width <= 0 || height <= 0) throw new RangeError("Grid dimensions must be positive");
@@ -37,8 +37,7 @@ function setCost(grid, x, y, cost) {
37
37
  if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;
38
38
  grid.data[(y | 0) * grid.width + (x | 0)] = cost > 255 ? 255 : cost < 0 ? 0 : cost | 0;
39
39
  }
40
- //#endregion
41
- //#region src/astar.ts
40
+ // src/astar.ts
42
41
  const SQRT2$1 = Math.SQRT2;
43
42
  function manhattanDistance(ax, ay, bx, by) {
44
43
  return Math.abs(ax - bx) + Math.abs(ay - by);
@@ -249,8 +248,7 @@ function reconstructPath(cameFrom, w, endIdx, cost, explored) {
249
248
  explored
250
249
  };
251
250
  }
252
- //#endregion
253
- //#region src/jps.ts
251
+ // src/jps.ts
254
252
  function heapCreate(capacity) {
255
253
  return {
256
254
  f: new Float64Array(capacity),
@@ -508,8 +506,7 @@ function buildPath(cameFrom, w, endIdx, cost, explored) {
508
506
  explored
509
507
  };
510
508
  }
511
- //#endregion
512
- //#region src/navmesh.ts
509
+ // src/navmesh.ts
513
510
  function createNavMesh(polygons) {
514
511
  return { polygons };
515
512
  }
@@ -694,32 +691,36 @@ function funnelSmooth(_mesh, byId, corridor, start, end) {
694
691
  for (let i = 1; i < n; i++) {
695
692
  const pL = portalsLeft[i];
696
693
  const pR = portalsRight[i];
697
- if (triArea2(apexPt, rightPt, pR) <= 0) if (vEqual(apexPt, rightPt) || triArea2(apexPt, leftPt, pR) > 0) {
698
- rightPt = pR;
699
- rightIdx = i;
700
- } else {
701
- addUnique(path, leftPt);
702
- apexPt = leftPt;
703
- apexIdx = leftIdx;
704
- leftPt = apexPt;
705
- rightPt = apexPt;
706
- leftIdx = apexIdx;
707
- rightIdx = apexIdx;
708
- i = apexIdx;
709
- continue;
694
+ if (triArea2(apexPt, rightPt, pR) <= 0) {
695
+ if (vEqual(apexPt, rightPt) || triArea2(apexPt, leftPt, pR) > 0) {
696
+ rightPt = pR;
697
+ rightIdx = i;
698
+ } else {
699
+ addUnique(path, leftPt);
700
+ apexPt = leftPt;
701
+ apexIdx = leftIdx;
702
+ leftPt = apexPt;
703
+ rightPt = apexPt;
704
+ leftIdx = apexIdx;
705
+ rightIdx = apexIdx;
706
+ i = apexIdx;
707
+ continue;
708
+ }
710
709
  }
711
- if (triArea2(apexPt, leftPt, pL) >= 0) if (vEqual(apexPt, leftPt) || triArea2(apexPt, rightPt, pL) < 0) {
712
- leftPt = pL;
713
- leftIdx = i;
714
- } else {
715
- addUnique(path, rightPt);
716
- apexPt = rightPt;
717
- apexIdx = rightIdx;
718
- leftPt = apexPt;
719
- rightPt = apexPt;
720
- leftIdx = apexIdx;
721
- rightIdx = apexIdx;
722
- i = apexIdx;
710
+ if (triArea2(apexPt, leftPt, pL) >= 0) {
711
+ if (vEqual(apexPt, leftPt) || triArea2(apexPt, rightPt, pL) < 0) {
712
+ leftPt = pL;
713
+ leftIdx = i;
714
+ } else {
715
+ addUnique(path, rightPt);
716
+ apexPt = rightPt;
717
+ apexIdx = rightIdx;
718
+ leftPt = apexPt;
719
+ rightPt = apexPt;
720
+ leftIdx = apexIdx;
721
+ rightIdx = apexIdx;
722
+ i = apexIdx;
723
+ }
723
724
  }
724
725
  }
725
726
  addUnique(path, end);
@@ -739,7 +740,6 @@ function triArea2(a, b, c) {
739
740
  function vEqual(a, b) {
740
741
  return a.x === b.x && a.y === b.y;
741
742
  }
742
- //#endregion
743
743
  export { chebyshevDistance, createGrid, createNavMesh, euclideanDistance, findNavMeshPath, findPath, findPathJPS, findPolygonAt, getCost, inBounds, isWalkable, manhattanDistance, octileDistance, setCost, setWalkable };
744
744
 
745
745
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["SQRT2","heapCreate","heapGrow","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\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\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 * JPS pruning is only correct when every walkable tile costs 1, so a grid with\n * any tile cost above 1 is delegated to weighted A* (`findPath`, diagonal moves)\n * after one linear scan of `grid.data`.\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 { findPath, 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\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\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\n// One pass per call, never per node: JPS pruning assumes every walkable tile costs 1.\nfunction hasWeightedCost(grid: Grid): boolean {\n const data = grid.data;\n for (let i = 0; i < data.length; i++) {\n if (data[i]! > 1) return true;\n }\n return false;\n}\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 if (hasWeightedCost(grid)) {\n return findPath(grid, sx, sy, ex, ey, { ...options, diagonal: true });\n }\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 /** One `Portal` per adjacent polygon: the shared edge plus that neighbour's id. */\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":";AAoBA,SAAgB,WAAW,QAA0B;CACnD,MAAM,EAAE,OAAO,QAAQ,cAAc,MAAM;CAC3C,IAAI,SAAS,KAAK,UAAU,GAC1B,MAAM,IAAI,WAAW,kCAAkC;CAEzD,MAAM,IAAI,QAAQ;CAClB,MAAM,IAAI,SAAS;CACnB,IAAI;CACJ,IAAI,OAAO,MAAM;EACf,IAAI,OAAO,KAAK,WAAW,IAAI,GAC7B,MAAM,IAAI,WAAW,oBAAoB,OAAO,KAAK,OAAO,kBAAkB,EAAE,GAAG,GAAG;EAExF,OAAO,OAAO;CAChB,OAAO;EACL,OAAO,IAAI,WAAW,IAAI,CAAC;EAC3B,IAAI,cAAc,GAChB,KAAK,KAAK,WAAW;CAEzB;CACA,OAAO;EAAE,OAAO;EAAG,QAAQ;EAAG;CAAK;AACrC;AAEA,SAAgB,SAAS,MAAY,GAAW,GAAoB;CAClE,OAAO,KAAK,KAAK,KAAK,KAAK,IAAI,KAAK,SAAS,IAAI,KAAK;AACxD;AAEA,SAAgB,WAAW,MAAY,GAAW,GAAoB;CACpE,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ,OAAO;CAClE,OAAO,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,MAAO;AACtD;AAEA,SAAgB,QAAQ,MAAY,GAAW,GAAmB;CAChE,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ,OAAO;CAClE,OAAO,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI;AAC/C;AAEA,SAAgB,YAAY,MAAY,GAAW,GAAW,UAAyB;CACrF,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ;CAC3D,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,WAAW,IAAI;AAC7D;AAEA,SAAgB,QAAQ,MAAY,GAAW,GAAW,MAAoB;CAC5E,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ;CAC3D,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,OAAO,MAAM,MAAM,OAAO,IAAI,IAAI,OAAO;AACvF;;;ACpCA,MAAMA,UAAQ,KAAK;AAEnB,SAAgB,kBAAkB,IAAY,IAAY,IAAY,IAAoB;CACxF,OAAO,KAAK,IAAI,KAAK,EAAE,IAAI,KAAK,IAAI,KAAK,EAAE;AAC7C;AAEA,SAAgB,eAAe,IAAY,IAAY,IAAY,IAAoB;CACrF,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;CAC3B,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;CAC3B,OAAO,KAAK,KAAK,MAAMA,UAAQ,KAAK,KAAK,MAAMA,UAAQ,KAAK;AAC9D;AAEA,SAAgB,kBAAkB,IAAY,IAAY,IAAY,IAAoB;CACxF,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC;AACtD;AAEA,SAAgB,kBAAkB,IAAY,IAAY,IAAY,IAAoB;CACxF,MAAM,KAAK,KAAK;CAChB,MAAM,KAAK,KAAK;CAChB,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACpC;AAYA,SAASC,aAAW,UAAwB;CAC1C,OAAO;EACL,GAAG,IAAI,aAAa,QAAQ;EAC5B,KAAK,IAAI,WAAW,QAAQ;EAC5B,MAAM;CACR;AACF;;;;;;;;;;;AAYA,SAASC,WAAS,GAAe;CAC/B,MAAM,OAAO,EAAE,EAAE,WAAW,IAAI,KAAK,EAAE,EAAE,SAAS;CAClD,MAAM,IAAI,IAAI,aAAa,IAAI;CAC/B,EAAE,IAAI,EAAE,CAAC;CACT,MAAM,MAAM,IAAI,WAAW,IAAI;CAC/B,IAAI,IAAI,EAAE,GAAG;CACb,EAAE,IAAI;CACN,EAAE,MAAM;AACV;AAEA,SAASC,WAAS,GAAS,GAAW,SAAuB;CAC3D,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,WAAS,CAAC;CACrC,IAAI,IAAI,EAAE;CACV,EAAE,EAAE,KAAK;CACT,EAAE,IAAI,KAAK;CAEX,OAAO,IAAI,GAAG;EACZ,MAAM,SAAU,IAAI,KAAM;EAC1B,IAAI,EAAE,EAAE,WAAY,EAAE,EAAE,IAAK;EAE7B,MAAM,KAAK,EAAE,EAAE;EACf,MAAM,KAAK,EAAE,IAAI;EACjB,EAAE,EAAE,UAAU,EAAE,EAAE;EAClB,EAAE,IAAI,UAAU,EAAE,IAAI;EACtB,EAAE,EAAE,KAAK;EACT,EAAE,IAAI,KAAK;EACX,IAAI;CACN;AACF;AAEA,SAASC,UAAQ,GAAiB;CAChC,MAAM,SAAS,EAAE,IAAI;CACrB,EAAE;CACF,IAAI,EAAE,OAAO,GAAG;EACd,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;EACf,EAAE,IAAI,KAAK,EAAE,IAAI,EAAE;EAEnB,IAAI,IAAI;EACR,SAAS;GACP,IAAI,WAAW;GACf,MAAM,OAAO,IAAI,IAAI;GACrB,MAAM,QAAQ,IAAI,IAAI;GACtB,IAAI,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAS,EAAE,EAAE,WAAY,WAAW;GAC7D,IAAI,QAAQ,EAAE,QAAQ,EAAE,EAAE,SAAU,EAAE,EAAE,WAAY,WAAW;GAC/D,IAAI,aAAa,GAAG;GACpB,MAAM,KAAK,EAAE,EAAE;GACf,MAAM,KAAK,EAAE,IAAI;GACjB,EAAE,EAAE,KAAK,EAAE,EAAE;GACb,EAAE,IAAI,KAAK,EAAE,IAAI;GACjB,EAAE,EAAE,YAAY;GAChB,EAAE,IAAI,YAAY;GAClB,IAAI;EACN;CACF;CACA,OAAO;AACT;AAKA,MAAM,SAAS;CAAC;CAAG;CAAG;CAAG;AAAE;AAC3B,MAAM,SAAS;CAAC;CAAI;CAAG;CAAG;AAAC;AAG3B,MAAM,SAAS;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAI;CAAI;AAAE;AACzC,MAAM,SAAS;CAAC;CAAI;CAAI;CAAG;CAAG;CAAG;CAAG;CAAG;AAAE;AACzC,MAAM,YAAY;CAAC;CAAGJ;CAAO;CAAGA;CAAO;CAAGA;CAAO;CAAGA;AAAK;AAIzD,SAAgB,SACd,MACA,QACA,QACA,MACA,MACA,SACmB;CACnB,MAAM,KAAK,SAAS;CACpB,MAAM,KAAK,SAAS;CACpB,MAAM,KAAK,OAAO;CAClB,MAAM,KAAK,OAAO;CAGlB,IAAI,CAAC,WAAW,MAAM,IAAI,EAAE,KAAK,CAAC,WAAW,MAAM,IAAI,EAAE,GAAG,OAAO;CACnE,IAAI,OAAO,MAAM,OAAO,IAAI,OAAO;EAAE,MAAM,CAAC;GAAE,GAAG;GAAI,GAAG;EAAG,CAAC;EAAG,MAAM;EAAG,UAAU;CAAE;CAEpF,MAAM,WAAW,SAAS,aAAa;CACvC,MAAM,UAAU,SAAS,iBAAiB,KAAK,QAAQ,KAAK;CAC5D,MAAM,YAAY,SAAS,cAAc,WAAW,iBAAiB;CAErE,MAAM,IAAI,KAAK;CACf,MAAM,QAAQ,IAAI,KAAK;CAGvB,MAAM,IAAI,IAAI,aAAa,KAAK;CAChC,EAAE,KAAK,OAAO,iBAAiB;CAC/B,MAAM,SAAS,IAAI,WAAW,KAAK;CACnC,MAAM,WAAW,IAAI,WAAW,KAAK;CACrC,SAAS,KAAK,EAAE;CAEhB,MAAM,WAAW,KAAK,IAAI;CAC1B,MAAM,SAAS,KAAK,IAAI;CACxB,EAAE,YAAY;CAEd,MAAM,OAAOC,aAAW,KAAK,IAAI,OAAO,IAAI,CAAC;CAC7C,WAAS,MAAM,UAAU,IAAI,IAAI,IAAI,EAAE,GAAG,QAAQ;CAElD,MAAM,OAAO,WAAW,SAAS;CACjC,MAAM,OAAO,WAAW,SAAS;CACjC,MAAM,UAAU,WAAW,YAAY;CACvC,MAAM,WAAW,KAAK;CAEtB,IAAI,WAAW;CAEf,OAAO,KAAK,OAAO,KAAK,WAAW,SAAS;EAC1C,MAAM,aAAaG,UAAQ,IAAI;EAC/B,IAAI,eAAe,QACjB,OAAO,gBAAgB,UAAU,GAAG,YAAY,EAAE,aAAc,QAAQ;EAE1E,IAAI,OAAO,aAAa;EACxB,OAAO,cAAc;EACrB;EAEA,MAAM,KAAK,aAAa;EACxB,MAAM,KAAM,aAAa,IAAK;EAC9B,MAAM,WAAW,EAAE;EAEnB,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,KAAK;GACjC,MAAM,KAAK,KAAK,KAAK;GACrB,MAAM,KAAK,KAAK,KAAK;GACrB,IAAI,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,QAAQ;GAEtD,MAAM,OAAO,KAAK,IAAI;GACtB,IAAI,OAAO,OAAO;GAElB,MAAM,WAAW,KAAK,KAAK;GAC3B,IAAI,aAAa,GAAG;GAGpB,IAAI,YAAY,IAAI,GAAG;IACrB,MAAM,KAAK,KAAK;IAChB,MAAM,KAAK,KAAK;IAChB,IAAI,CAAC,WAAW,MAAM,KAAK,IAAI,EAAE,KAAK,CAAC,WAAW,MAAM,IAAI,KAAK,EAAE,GAAG;GACxE;GAGA,MAAM,aAAa,YADF,UAAU,QAAQ,KAAM,WAAW;GAGpD,IAAI,aAAa,EAAE,OAAQ;IACzB,EAAE,QAAQ;IACV,SAAS,QAAQ;IAEjB,WAAS,MADC,aAAa,UAAU,IAAI,IAAI,IAAI,EAAE,GAC7B,IAAI;GACxB;EACF;CACF;CAEA,OAAO;AACT;AAEA,SAAS,gBACP,UACA,GACA,QACA,MACA,UACY;CACZ,MAAM,OAAmC,CAAC;CAC1C,IAAI,MAAM;CACV,OAAO,QAAQ,IAAI;EACjB,KAAK,KAAK;GAAE,GAAG,MAAM;GAAG,GAAI,MAAM,IAAK;EAAE,CAAC;EAC1C,MAAM,SAAS;CACjB;CACA,KAAK,QAAQ;CACb,OAAO;EAAE;EAAM;EAAM;CAAS;AAChC;;;ACvOA,SAAS,WAAW,UAAwB;CAC1C,OAAO;EACL,GAAG,IAAI,aAAa,QAAQ;EAC5B,KAAK,IAAI,WAAW,QAAQ;EAC5B,MAAM;CACR;AACF;;;;;;;;;;;AAYA,SAAS,SAAS,GAAe;CAC/B,MAAM,OAAO,EAAE,EAAE,WAAW,IAAI,KAAK,EAAE,EAAE,SAAS;CAClD,MAAM,IAAI,IAAI,aAAa,IAAI;CAC/B,EAAE,IAAI,EAAE,CAAC;CACT,MAAM,MAAM,IAAI,WAAW,IAAI;CAC/B,IAAI,IAAI,EAAE,GAAG;CACb,EAAE,IAAI;CACN,EAAE,MAAM;AACV;AAEA,SAAS,SAAS,GAAS,GAAW,SAAuB;CAC3D,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,SAAS,CAAC;CACrC,IAAI,IAAI,EAAE;CACV,EAAE,EAAE,KAAK;CACT,EAAE,IAAI,KAAK;CACX,OAAO,IAAI,GAAG;EACZ,MAAM,SAAU,IAAI,KAAM;EAC1B,IAAI,EAAE,EAAE,WAAY,EAAE,EAAE,IAAK;EAC7B,MAAM,KAAK,EAAE,EAAE;EACf,MAAM,KAAK,EAAE,IAAI;EACjB,EAAE,EAAE,UAAU,EAAE,EAAE;EAClB,EAAE,IAAI,UAAU,EAAE,IAAI;EACtB,EAAE,EAAE,KAAK;EACT,EAAE,IAAI,KAAK;EACX,IAAI;CACN;AACF;AAEA,SAAS,QAAQ,GAAiB;CAChC,MAAM,SAAS,EAAE,IAAI;CACrB,EAAE;CACF,IAAI,EAAE,OAAO,GAAG;EACd,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;EACf,EAAE,IAAI,KAAK,EAAE,IAAI,EAAE;EACnB,IAAI,IAAI;EACR,SAAS;GACP,IAAI,WAAW;GACf,MAAM,OAAO,IAAI,IAAI;GACrB,MAAM,QAAQ,IAAI,IAAI;GACtB,IAAI,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAS,EAAE,EAAE,WAAY,WAAW;GAC7D,IAAI,QAAQ,EAAE,QAAQ,EAAE,EAAE,SAAU,EAAE,EAAE,WAAY,WAAW;GAC/D,IAAI,aAAa,GAAG;GACpB,MAAM,KAAK,EAAE,EAAE;GACf,MAAM,KAAK,EAAE,IAAI;GACjB,EAAE,EAAE,KAAK,EAAE,EAAE;GACb,EAAE,IAAI,KAAK,EAAE,IAAI;GACjB,EAAE,EAAE,YAAY;GAChB,EAAE,IAAI,YAAY;GAClB,IAAI;EACN;CACF;CACA,OAAO;AACT;AAIA,MAAM,QAAQ,KAAK;AAGnB,SAAS,gBAAgB,MAAqB;CAC5C,MAAM,OAAO,KAAK;CAClB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAC/B,IAAI,KAAK,KAAM,GAAG,OAAO;CAE3B,OAAO;AACT;AASA,SAAgB,YACd,MACA,QACA,QACA,MACA,MACA,SACmB;CACnB,MAAM,KAAK,SAAS;CACpB,MAAM,KAAK,SAAS;CACpB,MAAM,KAAK,OAAO;CAClB,MAAM,KAAK,OAAO;CAElB,IAAI,CAAC,WAAW,MAAM,IAAI,EAAE,KAAK,CAAC,WAAW,MAAM,IAAI,EAAE,GAAG,OAAO;CACnE,IAAI,OAAO,MAAM,OAAO,IAAI,OAAO;EAAE,MAAM,CAAC;GAAE,GAAG;GAAI,GAAG;EAAG,CAAC;EAAG,MAAM;EAAG,UAAU;CAAE;CACpF,IAAI,gBAAgB,IAAI,GACtB,OAAO,SAAS,MAAM,IAAI,IAAI,IAAI,IAAI;EAAE,GAAG;EAAS,UAAU;CAAK,CAAC;CAGtE,MAAM,IAAI,KAAK;CACf,MAAM,IAAI,KAAK;CACf,MAAM,QAAQ,IAAI;CAClB,MAAM,UAAU,SAAS,iBAAiB;CAC1C,MAAM,YAAY,SAAS,aAAa;CAExC,MAAM,IAAI,IAAI,aAAa,KAAK;CAChC,EAAE,KAAK,OAAO,iBAAiB;CAC/B,MAAM,SAAS,IAAI,WAAW,KAAK;CACnC,MAAM,WAAW,IAAI,WAAW,KAAK;CACrC,SAAS,KAAK,EAAE;CAEhB,MAAM,WAAW,KAAK,IAAI;CAC1B,MAAM,SAAS,KAAK,IAAI;CACxB,EAAE,YAAY;CAEd,MAAM,OAAO,WAAW,KAAK,IAAI,OAAO,IAAI,CAAC;CAC7C,SAAS,MAAM,UAAU,IAAI,IAAI,IAAI,EAAE,GAAG,QAAQ;CAElD,IAAI,WAAW;CAEf,OAAO,KAAK,OAAO,KAAK,WAAW,SAAS;EAC1C,MAAM,aAAa,QAAQ,IAAI;EAC/B,IAAI,eAAe,QACjB,OAAO,UAAU,UAAU,GAAG,YAAY,EAAE,aAAc,QAAQ;EAEpE,IAAI,OAAO,aAAa;EACxB,OAAO,cAAc;EACrB;EAEA,MAAM,KAAK,aAAa;EACxB,MAAM,KAAM,aAAa,IAAK;EAE9B,MAAM,YAAY,mBAAmB,MAAM,IAAI,IAAI,UAAU,GAAG,GAAG,IAAI,EAAE;EACzE,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,GAAG;GAC5C,MAAM,KAAK,UAAU;GACrB,MAAM,KAAK,UAAU,IAAI;GACzB,MAAM,OAAO,KAAK,IAAI;GACtB,IAAI,OAAO,OAAO;GAElB,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;GAC3B,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;GAC3B,MAAM,OAAO,KAAK,IAAI,IAAI,EAAE;GAC5B,MAAM,WAAW,KAAK,IAAI,KAAK,EAAE;GACjC,MAAM,OAAO,OAAO,QAAQ;GAC5B,MAAM,aAAa,EAAE,cAAe;GACpC,IAAI,aAAa,EAAE,OAAQ;IACzB,EAAE,QAAQ;IACV,SAAS,QAAQ;IACjB,SAAS,MAAM,aAAa,UAAU,IAAI,IAAI,IAAI,EAAE,GAAG,IAAI;GAC7D;EACF;CACF;CAEA,OAAO;AACT;AAEA,SAAS,mBACP,MACA,IACA,IACA,UACA,GACA,GACA,IACA,IACU;CACV,MAAM,UAAoB,CAAC;CAC3B,MAAM,YAAY,SAAS,KAAK,IAAI;CAEpC,IAAI,cAAc,IAEhB,KAAK,IAAI,KAAK,IAAI,MAAM,GAAG,MACzB,KAAK,IAAI,KAAK,IAAI,MAAM,GAAG,MAAM;EAC/B,IAAI,OAAO,KAAK,OAAO,GAAG;EAC1B,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;EAClD,IAAI,OAAO,IACT,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;CAErC;MAEG;EACL,MAAM,KAAK,YAAY;EACvB,MAAM,KAAM,YAAY,IAAK;EAC7B,MAAM,KAAK,SAAS,KAAK,EAAE;EAC3B,MAAM,KAAK,SAAS,KAAK,EAAE;EAE3B,IAAI,OAAO,KAAK,OAAO,GAAG;GAExB,IAAI,WAAW,MAAM,IAAI,KAAK,EAAE,GAAG;IACjC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,WAAW,MAAM,KAAK,IAAI,EAAE,GAAG;IACjC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,GAAG;IACtC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;IAClD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GAEA,IAAI,CAAC,WAAW,MAAM,KAAK,IAAI,EAAE,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,GAAG;IACxE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;IACnD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,IAAI,KAAK,EAAE,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,GAAG;IACxE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,EAAE;IACnD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;EACF,OAAO,IAAI,OAAO,GAAG;GAEnB,IAAI,WAAW,MAAM,KAAK,IAAI,EAAE,GAAG;IACjC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,IAAI,KAAK,CAAC,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG;IACtE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,IAAI,KAAK,CAAC,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG;IACtE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;IAClD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;EACF,OAAO;GAEL,IAAI,WAAW,MAAM,IAAI,KAAK,EAAE,GAAG;IACjC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,WAAW,MAAM,KAAK,GAAG,KAAK,EAAE,GAAG;IACtE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,WAAW,MAAM,KAAK,GAAG,KAAK,EAAE,GAAG;IACtE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;IAClD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;EACF;CACF;CAEA,OAAO;AACT;AAEA,SAAS,KACP,MACA,IACA,IACA,IACA,IACA,GACA,GACA,IACA,IACQ;CACR,MAAM,KAAK,KAAK;CAChB,MAAM,KAAK,KAAK;CAEhB,IAAI,CAAC,WAAW,MAAM,IAAI,EAAE,GAAG,OAAO;CACtC,IAAI,OAAO,MAAM,OAAO,IAAI,OAAO,KAAK,IAAI;CAG5C,IAAI,OAAO,KAAK,OAAO,GAAG;EAExB,IACG,CAAC,WAAW,MAAM,KAAK,IAAI,EAAE,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,KACnE,CAAC,WAAW,MAAM,IAAI,KAAK,EAAE,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,GAEpE,OAAO,KAAK,IAAI;EAGlB,IAAI,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE,MAAM,IAAI,OAAO,KAAK,IAAI;EACpE,IAAI,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE,MAAM,IAAI,OAAO,KAAK,IAAI;CACtE,OAAO,IAAI,OAAO;MAGb,CAAC,WAAW,MAAM,IAAI,KAAK,CAAC,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,CAAC,KACjE,CAAC,WAAW,MAAM,IAAI,KAAK,CAAC,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,CAAC,GAElE,OAAO,KAAK,IAAI;CAAA,OAIlB,IACG,CAAC,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,WAAW,MAAM,KAAK,GAAG,KAAK,EAAE,KACjE,CAAC,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,WAAW,MAAM,KAAK,GAAG,KAAK,EAAE,GAElE,OAAO,KAAK,IAAI;CAKpB,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;AAChD;AAEA,SAAS,SAAS,GAAmB;CACnC,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK;AAClC;AAEA,SAAS,UACP,UACA,GACA,QACA,MACA,UACY;CAEZ,MAAM,aAAuB,CAAC;CAC9B,IAAI,MAAM;CACV,OAAO,QAAQ,IAAI;EACjB,WAAW,KAAK,GAAG;EACnB,MAAM,SAAS;CACjB;CACA,WAAW,QAAQ;CAEnB,MAAM,OAAmC,CAAC;CAC1C,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;EAC1C,MAAM,QAAQ,WAAW;EACzB,MAAM,KAAK,QAAQ;EACnB,MAAM,KAAM,QAAQ,IAAK;EACzB,IAAI,MAAM,GACR,KAAK,KAAK;GAAE,GAAG;GAAI,GAAG;EAAG,CAAC;OACrB;GACL,MAAM,OAAO,KAAK,KAAK,SAAS;GAEhC,IAAI,KAAK,KAAK;GACd,IAAI,KAAK,KAAK;GACd,OAAO,OAAO,MAAM,OAAO,IAAI;IAC7B,IAAI,KAAK,IAAI;SACR,IAAI,KAAK,IAAI;IAClB,IAAI,KAAK,IAAI;SACR,IAAI,KAAK,IAAI;IAClB,KAAK,KAAK;KAAE,GAAG;KAAI,GAAG;IAAG,CAAC;GAC5B;EACF;CACF;CAEA,OAAO;EAAE;EAAM;EAAM;CAAS;AAChC;;;AC5UA,SAAgB,cAAc,UAAqC;CACjE,OAAO,EAAE,SAAS;AACpB;AAIA,SAAS,qBAAqB,OAAwB,IAAY,IAAqB;CACrF,MAAM,IAAI,MAAM;CAChB,IAAI,IAAI,GAAG,OAAO;CAClB,IAAI,OAAO;CACX,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,IAAI,MAAM;EAChB,MAAM,IAAI,OAAO,IAAI,KAAK;EAC1B,MAAM,SAAS,EAAE,IAAI,EAAE,MAAM,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,EAAE;EAC/D,IAAI,UAAU,GAAG;GACf,MAAM,IAAI,QAAQ,IAAI,IAAI;GAC1B,IAAI,SAAS,GAAG,OAAO;QAClB,IAAI,SAAS,GAAG,OAAO;EAC9B;CACF;CACA,OAAO;AACT;AAEA,SAAgB,cAAc,MAAe,GAAW,GAAmB;CACzE,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KACxC,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAE,UAAU,GAAG,CAAC,GACvD,OAAO,KAAK,SAAS,EAAE,CAAE;CAG7B,OAAO;AACT;AAIA,SAAS,SAAS,OAA8B;CAC9C,IAAI,KAAK;CACT,IAAI,KAAK;CACT,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,MAAM,EAAE,CAAE;EAChB,MAAM,MAAM,EAAE,CAAE;CAClB;CACA,MAAM,IAAI,MAAM;CAChB,OAAO;EAAE,GAAG,KAAK;EAAG,GAAG,KAAK;CAAE;AAChC;AAIA,SAAS,OAAO,IAAY,IAAY,IAAY,IAAoB;CACtE,MAAM,KAAK,KAAK;CAChB,MAAM,KAAK,KAAK;CAChB,OAAO,KAAK,KAAK,KAAK;AACxB;AAEA,SAAS,KAAK,IAAY,IAAY,IAAY,IAAoB;CACpE,OAAO,KAAK,KAAK,OAAO,IAAI,IAAI,IAAI,EAAE,CAAC;AACzC;AAEA,SAAgB,gBAAgB,MAAe,OAAa,KAAqC;CAC/F,MAAM,cAAc,cAAc,MAAM,MAAM,GAAG,MAAM,CAAC;CACxD,MAAM,YAAY,cAAc,MAAM,IAAI,GAAG,IAAI,CAAC;CAClD,IAAI,gBAAgB,MAAM,cAAc,IAAI,OAAO;CACnD,IAAI,gBAAgB,WAClB,OAAO;EACL,MAAM,CACJ;GAAE,GAAG,MAAM;GAAG,GAAG,MAAM;EAAE,GACzB;GAAE,GAAG,IAAI;GAAG,GAAG,IAAI;EAAE,CACvB;EACA,UAAU,CAAC,WAAW;CACxB;CAIF,MAAM,uBAAO,IAAI,IAA4B;CAC7C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;EAC7C,MAAM,IAAI,KAAK,SAAS;EACxB,KAAK,IAAI,EAAE,IAAI,CAAC;CAClB;CAGA,MAAM,yBAAS,IAAI,IAAoB;CACvC,MAAM,yBAAS,IAAI,IAAoB;CACvC,MAAM,2BAAW,IAAI,IAAoB;CAEzC,OAAO,IAAI,aAAa,CAAC;CAGzB,MAAM,YAAY,SADF,KAAK,IAAI,SACQ,CAAC,CAAC,QAAQ;CAE3C,MAAM,cAAc,SADF,KAAK,IAAI,WACU,CAAC,CAAC,QAAQ;CAE/C,OAAO,IAAI,aAAa,KAAK,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC,CAAC;CAGpF,MAAM,OAAiB,CAAC,WAAW;CACnC,MAAM,yBAAS,IAAI,IAAY,CAAC,WAAW,CAAC;CAC5C,MAAM,yBAAS,IAAI,IAAY;CAE/B,OAAO,KAAK,SAAS,GAAG;EAEtB,IAAI,QAAQ;EACZ,IAAI,QAAQ,OAAO,IAAI,KAAK,EAAG,KAAK,OAAO;EAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;GACpC,MAAM,IAAI,OAAO,IAAI,KAAK,EAAG,KAAK,OAAO;GACzC,IAAI,IAAI,OAAO;IACb,QAAQ;IACR,QAAQ;GACV;EACF;EACA,MAAM,YAAY,KAAK;EAEvB,IAAI,cAAc,WAAW;GAE3B,MAAM,WAAqB,CAAC;GAC5B,IAAI,KAAyB;GAC7B,OAAO,OAAO,KAAA,GAAW;IACvB,SAAS,KAAK,EAAE;IAChB,KAAK,SAAS,IAAI,EAAE;GACtB;GACA,SAAS,QAAQ;GAEjB,OAAO;IAAE,MADI,aAAa,MAAM,MAAM,UAAU,OAAO,GAC3C;IAAG;GAAS;EAC1B;EAGA,KAAK,SAAS,KAAK,KAAK,SAAS;EACjC,KAAK;EACL,OAAO,OAAO,SAAS;EACvB,OAAO,IAAI,SAAS;EAEpB,MAAM,UAAU,KAAK,IAAI,SAAS;EAClC,MAAM,gBAAgB,SAAS,QAAQ,QAAQ;EAC/C,MAAM,WAAW,OAAO,IAAI,SAAS;EAErC,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,QAAQ,KAAK;GAC/C,MAAM,SAAS,QAAQ,QAAQ;GAC/B,MAAM,aAAa,OAAO;GAC1B,IAAI,OAAO,IAAI,UAAU,GAAG;GAE5B,MAAM,WAAW,KAAK,IAAI,UAAU;GACpC,IAAI,CAAC,UAAU;GAEf,MAAM,cAAc,OAAO,EAAE,IAAI,OAAO,EAAE,KAAK;GAC/C,MAAM,cAAc,OAAO,EAAE,IAAI,OAAO,EAAE,KAAK;GAC/C,MAAM,aAAa,WAAW,KAAK,cAAc,GAAG,cAAc,GAAG,YAAY,UAAU;GAE3F,MAAM,QAAQ,OAAO,IAAI,UAAU;GACnC,IAAI,UAAU,KAAA,KAAa,cAAc,OAAO;GAEhD,OAAO,IAAI,YAAY,UAAU;GACjC,SAAS,IAAI,YAAY,SAAS;GAElC,MAAM,iBAAiB,SAAS,SAAS,QAAQ;GACjD,OAAO,IACL,YACA,aAAa,KAAK,eAAe,GAAG,eAAe,GAAG,UAAU,GAAG,UAAU,CAAC,CAChF;GAEA,IAAI,CAAC,OAAO,IAAI,UAAU,GAAG;IAC3B,KAAK,KAAK,UAAU;IACpB,OAAO,IAAI,UAAU;GACvB;EACF;CACF;CAEA,OAAO;AACT;AAIA,SAAS,aACP,OACA,MACA,UACA,OACA,KACQ;CACR,IAAI,SAAS,UAAU,GACrB,OAAO,CACL;EAAE,GAAG,MAAM;EAAG,GAAG,MAAM;CAAE,GACzB;EAAE,GAAG,IAAI;EAAG,GAAG,IAAI;CAAE,CACvB;CAIF,MAAM,cAAsB,CAAC;CAC7B,MAAM,eAAuB,CAAC;CAE9B,YAAY,KAAK;EAAE,GAAG,MAAM;EAAG,GAAG,MAAM;CAAE,CAAC;CAC3C,aAAa,KAAK;EAAE,GAAG,MAAM;EAAG,GAAG,MAAM;CAAE,CAAC;CAE5C,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,SAAS,GAAG,KAAK;EAC5C,MAAM,OAAO,KAAK,IAAI,SAAS,EAAG;EAClC,MAAM,SAAS,SAAS,IAAI;EAE5B,IAAI,QAAQ;EACZ,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KACvC,IAAI,KAAK,QAAQ,EAAE,CAAE,eAAe,QAAQ;GAC1C,YAAY,KAAK,KAAK,QAAQ,EAAE,CAAE,CAAC;GACnC,aAAa,KAAK,KAAK,QAAQ,EAAE,CAAE,CAAC;GACpC,QAAQ;GACR;EACF;EAEF,IAAI,CAAC,OAAO;GAEV,MAAM,IAAI,SAAS,KAAK,QAAQ;GAChC,YAAY,KAAK,CAAC;GAClB,aAAa,KAAK,CAAC;EACrB;CACF;CAEA,YAAY,KAAK;EAAE,GAAG,IAAI;EAAG,GAAG,IAAI;CAAE,CAAC;CACvC,aAAa,KAAK;EAAE,GAAG,IAAI;EAAG,GAAG,IAAI;CAAE,CAAC;CAIxC,MAAM,OAAe,CAAC;CAEtB,IAAI,SAAS,YAAY;CACzB,IAAI,SAAS,YAAY;CACzB,IAAI,UAAU,aAAa;CAC3B,IAAI,UAAU;CACd,IAAI,UAAU;CACd,IAAI,WAAW;CAEf,KAAK,KAAK;EAAE,GAAG,OAAO;EAAG,GAAG,OAAO;CAAE,CAAC;CAEtC,MAAM,IAAI,YAAY;CAEtB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,KAAK,YAAY;EACvB,MAAM,KAAK,aAAa;EAGxB,IAAI,SAAS,QAAQ,SAAS,EAAE,KAAK,GACnC,IAAI,OAAO,QAAQ,OAAO,KAAK,SAAS,QAAQ,QAAQ,EAAE,IAAI,GAAG;GAE/D,UAAU;GACV,WAAW;EACb,OAAO;GAEL,UAAU,MAAM,MAAM;GACtB,SAAS;GACT,UAAU;GAEV,SAAS;GACT,UAAU;GACV,UAAU;GACV,WAAW;GAEX,IAAI;GACJ;EACF;EAIF,IAAI,SAAS,QAAQ,QAAQ,EAAE,KAAK,GAClC,IAAI,OAAO,QAAQ,MAAM,KAAK,SAAS,QAAQ,SAAS,EAAE,IAAI,GAAG;GAE/D,SAAS;GACT,UAAU;EACZ,OAAO;GAEL,UAAU,MAAM,OAAO;GACvB,SAAS;GACT,UAAU;GAEV,SAAS;GACT,UAAU;GACV,UAAU;GACV,WAAW;GAEX,IAAI;EACN;CAEJ;CAEA,UAAU,MAAM,GAAG;CAEnB,OAAO;AACT;AAEA,SAAS,UAAU,MAAc,GAAe;CAC9C,MAAM,OAAO,KAAK,KAAK,SAAS;CAChC,IAAI,CAAC,QAAQ,KAAK,MAAM,EAAE,KAAK,KAAK,MAAM,EAAE,GAC1C,KAAK,KAAK;EAAE,GAAG,EAAE;EAAG,GAAG,EAAE;CAAE,CAAC;AAEhC;;AAGA,SAAS,SAAS,GAAS,GAAS,GAAiB;CACnD,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;AAC5D;AAEA,SAAS,OAAO,GAAS,GAAkB;CACzC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;AAClC"}
1
+ {"version":3,"file":"index.mjs","names":["SQRT2","heapCreate","heapGrow","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\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\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 * JPS pruning is only correct when every walkable tile costs 1, so a grid with\n * any tile cost above 1 is delegated to weighted A* (`findPath`, diagonal moves)\n * after one linear scan of `grid.data`.\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 { findPath, 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\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\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\n// One pass per call, never per node: JPS pruning assumes every walkable tile costs 1.\nfunction hasWeightedCost(grid: Grid): boolean {\n const data = grid.data;\n for (let i = 0; i < data.length; i++) {\n if (data[i]! > 1) return true;\n }\n return false;\n}\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 if (hasWeightedCost(grid)) {\n return findPath(grid, sx, sy, ex, ey, { ...options, diagonal: true });\n }\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 /** One `Portal` per adjacent polygon: the shared edge plus that neighbour's id. */\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":";AAoBA,SAAgB,WAAW,QAA0B;CACnD,MAAM,EAAE,OAAO,QAAQ,cAAc,MAAM;CAC3C,IAAI,SAAS,KAAK,UAAU,GAC1B,MAAM,IAAI,WAAW,kCAAkC;CAEzD,MAAM,IAAI,QAAQ;CAClB,MAAM,IAAI,SAAS;CACnB,IAAI;CACJ,IAAI,OAAO,MAAM;EACf,IAAI,OAAO,KAAK,WAAW,IAAI,GAC7B,MAAM,IAAI,WAAW,oBAAoB,OAAO,KAAK,OAAO,kBAAkB,EAAE,GAAG,GAAG;EAExF,OAAO,OAAO;CAChB,OAAO;EACL,OAAO,IAAI,WAAW,IAAI,CAAC;EAC3B,IAAI,cAAc,GAChB,KAAK,KAAK,WAAW;CAEzB;CACA,OAAO;EAAE,OAAO;EAAG,QAAQ;EAAG;CAAK;AACrC;AAEA,SAAgB,SAAS,MAAY,GAAW,GAAoB;CAClE,OAAO,KAAK,KAAK,KAAK,KAAK,IAAI,KAAK,SAAS,IAAI,KAAK;AACxD;AAEA,SAAgB,WAAW,MAAY,GAAW,GAAoB;CACpE,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ,OAAO;CAClE,OAAO,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,MAAO;AACtD;AAEA,SAAgB,QAAQ,MAAY,GAAW,GAAmB;CAChE,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ,OAAO;CAClE,OAAO,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI;AAC/C;AAEA,SAAgB,YAAY,MAAY,GAAW,GAAW,UAAyB;CACrF,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ;CAC3D,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,WAAW,IAAI;AAC7D;AAEA,SAAgB,QAAQ,MAAY,GAAW,GAAW,MAAoB;CAC5E,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS,KAAK,KAAK,QAAQ;CAC3D,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,OAAO,MAAM,MAAM,OAAO,IAAI,IAAI,OAAO;AACvF;;ACpCA,MAAMA,UAAQ,KAAK;AAEnB,SAAgB,kBAAkB,IAAY,IAAY,IAAY,IAAoB;CACxF,OAAO,KAAK,IAAI,KAAK,EAAE,IAAI,KAAK,IAAI,KAAK,EAAE;AAC7C;AAEA,SAAgB,eAAe,IAAY,IAAY,IAAY,IAAoB;CACrF,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;CAC3B,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;CAC3B,OAAO,KAAK,KAAK,MAAMA,UAAQ,KAAK,KAAK,MAAMA,UAAQ,KAAK;AAC9D;AAEA,SAAgB,kBAAkB,IAAY,IAAY,IAAY,IAAoB;CACxF,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC;AACtD;AAEA,SAAgB,kBAAkB,IAAY,IAAY,IAAY,IAAoB;CACxF,MAAM,KAAK,KAAK;CAChB,MAAM,KAAK,KAAK;CAChB,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACpC;AAYA,SAASC,aAAW,UAAwB;CAC1C,OAAO;EACL,GAAG,IAAI,aAAa,QAAQ;EAC5B,KAAK,IAAI,WAAW,QAAQ;EAC5B,MAAM;CACR;AACF;;;;;;;;;;;AAYA,SAASC,WAAS,GAAe;CAC/B,MAAM,OAAO,EAAE,EAAE,WAAW,IAAI,KAAK,EAAE,EAAE,SAAS;CAClD,MAAM,IAAI,IAAI,aAAa,IAAI;CAC/B,EAAE,IAAI,EAAE,CAAC;CACT,MAAM,MAAM,IAAI,WAAW,IAAI;CAC/B,IAAI,IAAI,EAAE,GAAG;CACb,EAAE,IAAI;CACN,EAAE,MAAM;AACV;AAEA,SAASC,WAAS,GAAS,GAAW,SAAuB;CAC3D,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,WAAS,CAAC;CACrC,IAAI,IAAI,EAAE;CACV,EAAE,EAAE,KAAK;CACT,EAAE,IAAI,KAAK;CAEX,OAAO,IAAI,GAAG;EACZ,MAAM,SAAU,IAAI,KAAM;EAC1B,IAAI,EAAE,EAAE,WAAY,EAAE,EAAE,IAAK;EAE7B,MAAM,KAAK,EAAE,EAAE;EACf,MAAM,KAAK,EAAE,IAAI;EACjB,EAAE,EAAE,UAAU,EAAE,EAAE;EAClB,EAAE,IAAI,UAAU,EAAE,IAAI;EACtB,EAAE,EAAE,KAAK;EACT,EAAE,IAAI,KAAK;EACX,IAAI;CACN;AACF;AAEA,SAASC,UAAQ,GAAiB;CAChC,MAAM,SAAS,EAAE,IAAI;CACrB,EAAE;CACF,IAAI,EAAE,OAAO,GAAG;EACd,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;EACf,EAAE,IAAI,KAAK,EAAE,IAAI,EAAE;EAEnB,IAAI,IAAI;EACR,SAAS;GACP,IAAI,WAAW;GACf,MAAM,OAAO,IAAI,IAAI;GACrB,MAAM,QAAQ,IAAI,IAAI;GACtB,IAAI,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAS,EAAE,EAAE,WAAY,WAAW;GAC7D,IAAI,QAAQ,EAAE,QAAQ,EAAE,EAAE,SAAU,EAAE,EAAE,WAAY,WAAW;GAC/D,IAAI,aAAa,GAAG;GACpB,MAAM,KAAK,EAAE,EAAE;GACf,MAAM,KAAK,EAAE,IAAI;GACjB,EAAE,EAAE,KAAK,EAAE,EAAE;GACb,EAAE,IAAI,KAAK,EAAE,IAAI;GACjB,EAAE,EAAE,YAAY;GAChB,EAAE,IAAI,YAAY;GAClB,IAAI;EACN;CACF;CACA,OAAO;AACT;AAKA,MAAM,SAAS;CAAC;CAAG;CAAG;CAAG;AAAE;AAC3B,MAAM,SAAS;CAAC;CAAI;CAAG;CAAG;AAAC;AAG3B,MAAM,SAAS;CAAC;CAAG;CAAG;CAAG;CAAG;CAAG;CAAI;CAAI;AAAE;AACzC,MAAM,SAAS;CAAC;CAAI;CAAI;CAAG;CAAG;CAAG;CAAG;CAAG;AAAE;AACzC,MAAM,YAAY;CAAC;CAAGJ;CAAO;CAAGA;CAAO;CAAGA;CAAO;CAAGA;AAAK;AAIzD,SAAgB,SACd,MACA,QACA,QACA,MACA,MACA,SACmB;CACnB,MAAM,KAAK,SAAS;CACpB,MAAM,KAAK,SAAS;CACpB,MAAM,KAAK,OAAO;CAClB,MAAM,KAAK,OAAO;CAGlB,IAAI,CAAC,WAAW,MAAM,IAAI,EAAE,KAAK,CAAC,WAAW,MAAM,IAAI,EAAE,GAAG,OAAO;CACnE,IAAI,OAAO,MAAM,OAAO,IAAI,OAAO;EAAE,MAAM,CAAC;GAAE,GAAG;GAAI,GAAG;EAAG,CAAC;EAAG,MAAM;EAAG,UAAU;CAAE;CAEpF,MAAM,WAAW,SAAS,aAAa;CACvC,MAAM,UAAU,SAAS,iBAAiB,KAAK,QAAQ,KAAK;CAC5D,MAAM,YAAY,SAAS,cAAc,WAAW,iBAAiB;CAErE,MAAM,IAAI,KAAK;CACf,MAAM,QAAQ,IAAI,KAAK;CAGvB,MAAM,IAAI,IAAI,aAAa,KAAK;CAChC,EAAE,KAAK,OAAO,iBAAiB;CAC/B,MAAM,SAAS,IAAI,WAAW,KAAK;CACnC,MAAM,WAAW,IAAI,WAAW,KAAK;CACrC,SAAS,KAAK,EAAE;CAEhB,MAAM,WAAW,KAAK,IAAI;CAC1B,MAAM,SAAS,KAAK,IAAI;CACxB,EAAE,YAAY;CAEd,MAAM,OAAOC,aAAW,KAAK,IAAI,OAAO,IAAI,CAAC;CAC7C,WAAS,MAAM,UAAU,IAAI,IAAI,IAAI,EAAE,GAAG,QAAQ;CAElD,MAAM,OAAO,WAAW,SAAS;CACjC,MAAM,OAAO,WAAW,SAAS;CACjC,MAAM,UAAU,WAAW,YAAY;CACvC,MAAM,WAAW,KAAK;CAEtB,IAAI,WAAW;CAEf,OAAO,KAAK,OAAO,KAAK,WAAW,SAAS;EAC1C,MAAM,aAAaG,UAAQ,IAAI;EAC/B,IAAI,eAAe,QACjB,OAAO,gBAAgB,UAAU,GAAG,YAAY,EAAE,aAAc,QAAQ;EAE1E,IAAI,OAAO,aAAa;EACxB,OAAO,cAAc;EACrB;EAEA,MAAM,KAAK,aAAa;EACxB,MAAM,KAAM,aAAa,IAAK;EAC9B,MAAM,WAAW,EAAE;EAEnB,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,KAAK;GACjC,MAAM,KAAK,KAAK,KAAK;GACrB,MAAM,KAAK,KAAK,KAAK;GACrB,IAAI,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,QAAQ;GAEtD,MAAM,OAAO,KAAK,IAAI;GACtB,IAAI,OAAO,OAAO;GAElB,MAAM,WAAW,KAAK,KAAK;GAC3B,IAAI,aAAa,GAAG;GAGpB,IAAI,YAAY,IAAI,GAAG;IACrB,MAAM,KAAK,KAAK;IAChB,MAAM,KAAK,KAAK;IAChB,IAAI,CAAC,WAAW,MAAM,KAAK,IAAI,EAAE,KAAK,CAAC,WAAW,MAAM,IAAI,KAAK,EAAE,GAAG;GACxE;GAGA,MAAM,aAAa,YADF,UAAU,QAAQ,KAAM,WAAW;GAGpD,IAAI,aAAa,EAAE,OAAQ;IACzB,EAAE,QAAQ;IACV,SAAS,QAAQ;IAEjB,WAAS,MADC,aAAa,UAAU,IAAI,IAAI,IAAI,EAAE,GAC7B,IAAI;GACxB;EACF;CACF;CAEA,OAAO;AACT;AAEA,SAAS,gBACP,UACA,GACA,QACA,MACA,UACY;CACZ,MAAM,OAAmC,CAAC;CAC1C,IAAI,MAAM;CACV,OAAO,QAAQ,IAAI;EACjB,KAAK,KAAK;GAAE,GAAG,MAAM;GAAG,GAAI,MAAM,IAAK;EAAE,CAAC;EAC1C,MAAM,SAAS;CACjB;CACA,KAAK,QAAQ;CACb,OAAO;EAAE;EAAM;EAAM;CAAS;AAChC;;ACvOA,SAAS,WAAW,UAAwB;CAC1C,OAAO;EACL,GAAG,IAAI,aAAa,QAAQ;EAC5B,KAAK,IAAI,WAAW,QAAQ;EAC5B,MAAM;CACR;AACF;;;;;;;;;;;AAYA,SAAS,SAAS,GAAe;CAC/B,MAAM,OAAO,EAAE,EAAE,WAAW,IAAI,KAAK,EAAE,EAAE,SAAS;CAClD,MAAM,IAAI,IAAI,aAAa,IAAI;CAC/B,EAAE,IAAI,EAAE,CAAC;CACT,MAAM,MAAM,IAAI,WAAW,IAAI;CAC/B,IAAI,IAAI,EAAE,GAAG;CACb,EAAE,IAAI;CACN,EAAE,MAAM;AACV;AAEA,SAAS,SAAS,GAAS,GAAW,SAAuB;CAC3D,IAAI,EAAE,SAAS,EAAE,EAAE,QAAQ,SAAS,CAAC;CACrC,IAAI,IAAI,EAAE;CACV,EAAE,EAAE,KAAK;CACT,EAAE,IAAI,KAAK;CACX,OAAO,IAAI,GAAG;EACZ,MAAM,SAAU,IAAI,KAAM;EAC1B,IAAI,EAAE,EAAE,WAAY,EAAE,EAAE,IAAK;EAC7B,MAAM,KAAK,EAAE,EAAE;EACf,MAAM,KAAK,EAAE,IAAI;EACjB,EAAE,EAAE,UAAU,EAAE,EAAE;EAClB,EAAE,IAAI,UAAU,EAAE,IAAI;EACtB,EAAE,EAAE,KAAK;EACT,EAAE,IAAI,KAAK;EACX,IAAI;CACN;AACF;AAEA,SAAS,QAAQ,GAAiB;CAChC,MAAM,SAAS,EAAE,IAAI;CACrB,EAAE;CACF,IAAI,EAAE,OAAO,GAAG;EACd,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;EACf,EAAE,IAAI,KAAK,EAAE,IAAI,EAAE;EACnB,IAAI,IAAI;EACR,SAAS;GACP,IAAI,WAAW;GACf,MAAM,OAAO,IAAI,IAAI;GACrB,MAAM,QAAQ,IAAI,IAAI;GACtB,IAAI,OAAO,EAAE,QAAQ,EAAE,EAAE,QAAS,EAAE,EAAE,WAAY,WAAW;GAC7D,IAAI,QAAQ,EAAE,QAAQ,EAAE,EAAE,SAAU,EAAE,EAAE,WAAY,WAAW;GAC/D,IAAI,aAAa,GAAG;GACpB,MAAM,KAAK,EAAE,EAAE;GACf,MAAM,KAAK,EAAE,IAAI;GACjB,EAAE,EAAE,KAAK,EAAE,EAAE;GACb,EAAE,IAAI,KAAK,EAAE,IAAI;GACjB,EAAE,EAAE,YAAY;GAChB,EAAE,IAAI,YAAY;GAClB,IAAI;EACN;CACF;CACA,OAAO;AACT;AAIA,MAAM,QAAQ,KAAK;AAGnB,SAAS,gBAAgB,MAAqB;CAC5C,MAAM,OAAO,KAAK;CAClB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAC/B,IAAI,KAAK,KAAM,GAAG,OAAO;CAE3B,OAAO;AACT;AASA,SAAgB,YACd,MACA,QACA,QACA,MACA,MACA,SACmB;CACnB,MAAM,KAAK,SAAS;CACpB,MAAM,KAAK,SAAS;CACpB,MAAM,KAAK,OAAO;CAClB,MAAM,KAAK,OAAO;CAElB,IAAI,CAAC,WAAW,MAAM,IAAI,EAAE,KAAK,CAAC,WAAW,MAAM,IAAI,EAAE,GAAG,OAAO;CACnE,IAAI,OAAO,MAAM,OAAO,IAAI,OAAO;EAAE,MAAM,CAAC;GAAE,GAAG;GAAI,GAAG;EAAG,CAAC;EAAG,MAAM;EAAG,UAAU;CAAE;CACpF,IAAI,gBAAgB,IAAI,GACtB,OAAO,SAAS,MAAM,IAAI,IAAI,IAAI,IAAI;EAAE,GAAG;EAAS,UAAU;CAAK,CAAC;CAGtE,MAAM,IAAI,KAAK;CACf,MAAM,IAAI,KAAK;CACf,MAAM,QAAQ,IAAI;CAClB,MAAM,UAAU,SAAS,iBAAiB;CAC1C,MAAM,YAAY,SAAS,aAAa;CAExC,MAAM,IAAI,IAAI,aAAa,KAAK;CAChC,EAAE,KAAK,OAAO,iBAAiB;CAC/B,MAAM,SAAS,IAAI,WAAW,KAAK;CACnC,MAAM,WAAW,IAAI,WAAW,KAAK;CACrC,SAAS,KAAK,EAAE;CAEhB,MAAM,WAAW,KAAK,IAAI;CAC1B,MAAM,SAAS,KAAK,IAAI;CACxB,EAAE,YAAY;CAEd,MAAM,OAAO,WAAW,KAAK,IAAI,OAAO,IAAI,CAAC;CAC7C,SAAS,MAAM,UAAU,IAAI,IAAI,IAAI,EAAE,GAAG,QAAQ;CAElD,IAAI,WAAW;CAEf,OAAO,KAAK,OAAO,KAAK,WAAW,SAAS;EAC1C,MAAM,aAAa,QAAQ,IAAI;EAC/B,IAAI,eAAe,QACjB,OAAO,UAAU,UAAU,GAAG,YAAY,EAAE,aAAc,QAAQ;EAEpE,IAAI,OAAO,aAAa;EACxB,OAAO,cAAc;EACrB;EAEA,MAAM,KAAK,aAAa;EACxB,MAAM,KAAM,aAAa,IAAK;EAE9B,MAAM,YAAY,mBAAmB,MAAM,IAAI,IAAI,UAAU,GAAG,GAAG,IAAI,EAAE;EACzE,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,GAAG;GAC5C,MAAM,KAAK,UAAU;GACrB,MAAM,KAAK,UAAU,IAAI;GACzB,MAAM,OAAO,KAAK,IAAI;GACtB,IAAI,OAAO,OAAO;GAElB,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;GAC3B,MAAM,KAAK,KAAK,IAAI,KAAK,EAAE;GAC3B,MAAM,OAAO,KAAK,IAAI,IAAI,EAAE;GAC5B,MAAM,WAAW,KAAK,IAAI,KAAK,EAAE;GACjC,MAAM,OAAO,OAAO,QAAQ;GAC5B,MAAM,aAAa,EAAE,cAAe;GACpC,IAAI,aAAa,EAAE,OAAQ;IACzB,EAAE,QAAQ;IACV,SAAS,QAAQ;IACjB,SAAS,MAAM,aAAa,UAAU,IAAI,IAAI,IAAI,EAAE,GAAG,IAAI;GAC7D;EACF;CACF;CAEA,OAAO;AACT;AAEA,SAAS,mBACP,MACA,IACA,IACA,UACA,GACA,GACA,IACA,IACU;CACV,MAAM,UAAoB,CAAC;CAC3B,MAAM,YAAY,SAAS,KAAK,IAAI;CAEpC,IAAI,cAAc,IAEhB,KAAK,IAAI,KAAK,IAAI,MAAM,GAAG,MACzB,KAAK,IAAI,KAAK,IAAI,MAAM,GAAG,MAAM;EAC/B,IAAI,OAAO,KAAK,OAAO,GAAG;EAC1B,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;EAClD,IAAI,OAAO,IACT,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;CAErC;MAEG;EACL,MAAM,KAAK,YAAY;EACvB,MAAM,KAAM,YAAY,IAAK;EAC7B,MAAM,KAAK,SAAS,KAAK,EAAE;EAC3B,MAAM,KAAK,SAAS,KAAK,EAAE;EAE3B,IAAI,OAAO,KAAK,OAAO,GAAG;GAExB,IAAI,WAAW,MAAM,IAAI,KAAK,EAAE,GAAG;IACjC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,WAAW,MAAM,KAAK,IAAI,EAAE,GAAG;IACjC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,GAAG;IACtC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;IAClD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GAEA,IAAI,CAAC,WAAW,MAAM,KAAK,IAAI,EAAE,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,GAAG;IACxE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;IACnD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,IAAI,KAAK,EAAE,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,GAAG;IACxE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,EAAE;IACnD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;EACF,OAAO,IAAI,OAAO,GAAG;GAEnB,IAAI,WAAW,MAAM,KAAK,IAAI,EAAE,GAAG;IACjC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,IAAI,KAAK,CAAC,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG;IACtE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,IAAI,KAAK,CAAC,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,CAAC,GAAG;IACtE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;IAClD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;EACF,OAAO;GAEL,IAAI,WAAW,MAAM,IAAI,KAAK,EAAE,GAAG;IACjC,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,WAAW,MAAM,KAAK,GAAG,KAAK,EAAE,GAAG;IACtE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE;IACjD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;GACA,IAAI,CAAC,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,WAAW,MAAM,KAAK,GAAG,KAAK,EAAE,GAAG;IACtE,MAAM,KAAK,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;IAClD,IAAI,OAAO,IAAI,QAAQ,KAAK,KAAK,GAAI,KAAK,IAAK,CAAC;GAClD;EACF;CACF;CAEA,OAAO;AACT;AAEA,SAAS,KACP,MACA,IACA,IACA,IACA,IACA,GACA,GACA,IACA,IACQ;CACR,MAAM,KAAK,KAAK;CAChB,MAAM,KAAK,KAAK;CAEhB,IAAI,CAAC,WAAW,MAAM,IAAI,EAAE,GAAG,OAAO;CACtC,IAAI,OAAO,MAAM,OAAO,IAAI,OAAO,KAAK,IAAI;CAG5C,IAAI,OAAO,KAAK,OAAO,GAAG;EAExB,IACG,CAAC,WAAW,MAAM,KAAK,IAAI,EAAE,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,KACnE,CAAC,WAAW,MAAM,IAAI,KAAK,EAAE,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,EAAE,GAEpE,OAAO,KAAK,IAAI;EAGlB,IAAI,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,GAAG,GAAG,IAAI,EAAE,MAAM,IAAI,OAAO,KAAK,IAAI;EACpE,IAAI,KAAK,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,EAAE,MAAM,IAAI,OAAO,KAAK,IAAI;CACtE,OAAO,IAAI,OAAO,GAGb;MAAA,CAAC,WAAW,MAAM,IAAI,KAAK,CAAC,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,CAAC,KACjE,CAAC,WAAW,MAAM,IAAI,KAAK,CAAC,KAAK,WAAW,MAAM,KAAK,IAAI,KAAK,CAAC,GAElE,OAAO,KAAK,IAAI;CAAA,OAIlB,IACG,CAAC,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,WAAW,MAAM,KAAK,GAAG,KAAK,EAAE,KACjE,CAAC,WAAW,MAAM,KAAK,GAAG,EAAE,KAAK,WAAW,MAAM,KAAK,GAAG,KAAK,EAAE,GAElE,OAAO,KAAK,IAAI;CAKpB,OAAO,KAAK,MAAM,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,IAAI,EAAE;AAChD;AAEA,SAAS,SAAS,GAAmB;CACnC,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,KAAK;AAClC;AAEA,SAAS,UACP,UACA,GACA,QACA,MACA,UACY;CAEZ,MAAM,aAAuB,CAAC;CAC9B,IAAI,MAAM;CACV,OAAO,QAAQ,IAAI;EACjB,WAAW,KAAK,GAAG;EACnB,MAAM,SAAS;CACjB;CACA,WAAW,QAAQ;CAEnB,MAAM,OAAmC,CAAC;CAC1C,KAAK,IAAI,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;EAC1C,MAAM,QAAQ,WAAW;EACzB,MAAM,KAAK,QAAQ;EACnB,MAAM,KAAM,QAAQ,IAAK;EACzB,IAAI,MAAM,GACR,KAAK,KAAK;GAAE,GAAG;GAAI,GAAG;EAAG,CAAC;OACrB;GACL,MAAM,OAAO,KAAK,KAAK,SAAS;GAEhC,IAAI,KAAK,KAAK;GACd,IAAI,KAAK,KAAK;GACd,OAAO,OAAO,MAAM,OAAO,IAAI;IAC7B,IAAI,KAAK,IAAI;SACR,IAAI,KAAK,IAAI;IAClB,IAAI,KAAK,IAAI;SACR,IAAI,KAAK,IAAI;IAClB,KAAK,KAAK;KAAE,GAAG;KAAI,GAAG;IAAG,CAAC;GAC5B;EACF;CACF;CAEA,OAAO;EAAE;EAAM;EAAM;CAAS;AAChC;;AC5UA,SAAgB,cAAc,UAAqC;CACjE,OAAO,EAAE,SAAS;AACpB;AAIA,SAAS,qBAAqB,OAAwB,IAAY,IAAqB;CACrF,MAAM,IAAI,MAAM;CAChB,IAAI,IAAI,GAAG,OAAO;CAClB,IAAI,OAAO;CACX,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,IAAI,MAAM;EAChB,MAAM,IAAI,OAAO,IAAI,KAAK;EAC1B,MAAM,SAAS,EAAE,IAAI,EAAE,MAAM,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,EAAE;EAC/D,IAAI,UAAU,GAAG;GACf,MAAM,IAAI,QAAQ,IAAI,IAAI;GAC1B,IAAI,SAAS,GAAG,OAAO;QAClB,IAAI,SAAS,GAAG,OAAO;EAC9B;CACF;CACA,OAAO;AACT;AAEA,SAAgB,cAAc,MAAe,GAAW,GAAmB;CACzE,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KACxC,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAE,UAAU,GAAG,CAAC,GACvD,OAAO,KAAK,SAAS,EAAE,CAAE;CAG7B,OAAO;AACT;AAIA,SAAS,SAAS,OAA8B;CAC9C,IAAI,KAAK;CACT,IAAI,KAAK;CACT,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,MAAM,MAAM,EAAE,CAAE;EAChB,MAAM,MAAM,EAAE,CAAE;CAClB;CACA,MAAM,IAAI,MAAM;CAChB,OAAO;EAAE,GAAG,KAAK;EAAG,GAAG,KAAK;CAAE;AAChC;AAIA,SAAS,OAAO,IAAY,IAAY,IAAY,IAAoB;CACtE,MAAM,KAAK,KAAK;CAChB,MAAM,KAAK,KAAK;CAChB,OAAO,KAAK,KAAK,KAAK;AACxB;AAEA,SAAS,KAAK,IAAY,IAAY,IAAY,IAAoB;CACpE,OAAO,KAAK,KAAK,OAAO,IAAI,IAAI,IAAI,EAAE,CAAC;AACzC;AAEA,SAAgB,gBAAgB,MAAe,OAAa,KAAqC;CAC/F,MAAM,cAAc,cAAc,MAAM,MAAM,GAAG,MAAM,CAAC;CACxD,MAAM,YAAY,cAAc,MAAM,IAAI,GAAG,IAAI,CAAC;CAClD,IAAI,gBAAgB,MAAM,cAAc,IAAI,OAAO;CACnD,IAAI,gBAAgB,WAClB,OAAO;EACL,MAAM,CACJ;GAAE,GAAG,MAAM;GAAG,GAAG,MAAM;EAAE,GACzB;GAAE,GAAG,IAAI;GAAG,GAAG,IAAI;EAAE,CACvB;EACA,UAAU,CAAC,WAAW;CACxB;CAIF,MAAM,uBAAO,IAAI,IAA4B;CAC7C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;EAC7C,MAAM,IAAI,KAAK,SAAS;EACxB,KAAK,IAAI,EAAE,IAAI,CAAC;CAClB;CAGA,MAAM,yBAAS,IAAI,IAAoB;CACvC,MAAM,yBAAS,IAAI,IAAoB;CACvC,MAAM,2BAAW,IAAI,IAAoB;CAEzC,OAAO,IAAI,aAAa,CAAC;CAGzB,MAAM,YAAY,SADF,KAAK,IAAI,SACQ,CAAC,CAAC,QAAQ;CAE3C,MAAM,cAAc,SADF,KAAK,IAAI,WACU,CAAC,CAAC,QAAQ;CAE/C,OAAO,IAAI,aAAa,KAAK,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,UAAU,CAAC,CAAC;CAGpF,MAAM,OAAiB,CAAC,WAAW;CACnC,MAAM,yBAAS,IAAI,IAAY,CAAC,WAAW,CAAC;CAC5C,MAAM,yBAAS,IAAI,IAAY;CAE/B,OAAO,KAAK,SAAS,GAAG;EAEtB,IAAI,QAAQ;EACZ,IAAI,QAAQ,OAAO,IAAI,KAAK,EAAG,KAAK,OAAO;EAC3C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;GACpC,MAAM,IAAI,OAAO,IAAI,KAAK,EAAG,KAAK,OAAO;GACzC,IAAI,IAAI,OAAO;IACb,QAAQ;IACR,QAAQ;GACV;EACF;EACA,MAAM,YAAY,KAAK;EAEvB,IAAI,cAAc,WAAW;GAE3B,MAAM,WAAqB,CAAC;GAC5B,IAAI,KAAyB;GAC7B,OAAO,OAAO,KAAA,GAAW;IACvB,SAAS,KAAK,EAAE;IAChB,KAAK,SAAS,IAAI,EAAE;GACtB;GACA,SAAS,QAAQ;GAEjB,OAAO;IAAE,MADI,aAAa,MAAM,MAAM,UAAU,OAAO,GAC3C;IAAG;GAAS;EAC1B;EAGA,KAAK,SAAS,KAAK,KAAK,SAAS;EACjC,KAAK;EACL,OAAO,OAAO,SAAS;EACvB,OAAO,IAAI,SAAS;EAEpB,MAAM,UAAU,KAAK,IAAI,SAAS;EAClC,MAAM,gBAAgB,SAAS,QAAQ,QAAQ;EAC/C,MAAM,WAAW,OAAO,IAAI,SAAS;EAErC,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,QAAQ,KAAK;GAC/C,MAAM,SAAS,QAAQ,QAAQ;GAC/B,MAAM,aAAa,OAAO;GAC1B,IAAI,OAAO,IAAI,UAAU,GAAG;GAE5B,MAAM,WAAW,KAAK,IAAI,UAAU;GACpC,IAAI,CAAC,UAAU;GAEf,MAAM,cAAc,OAAO,EAAE,IAAI,OAAO,EAAE,KAAK;GAC/C,MAAM,cAAc,OAAO,EAAE,IAAI,OAAO,EAAE,KAAK;GAC/C,MAAM,aAAa,WAAW,KAAK,cAAc,GAAG,cAAc,GAAG,YAAY,UAAU;GAE3F,MAAM,QAAQ,OAAO,IAAI,UAAU;GACnC,IAAI,UAAU,KAAA,KAAa,cAAc,OAAO;GAEhD,OAAO,IAAI,YAAY,UAAU;GACjC,SAAS,IAAI,YAAY,SAAS;GAElC,MAAM,iBAAiB,SAAS,SAAS,QAAQ;GACjD,OAAO,IACL,YACA,aAAa,KAAK,eAAe,GAAG,eAAe,GAAG,UAAU,GAAG,UAAU,CAAC,CAChF;GAEA,IAAI,CAAC,OAAO,IAAI,UAAU,GAAG;IAC3B,KAAK,KAAK,UAAU;IACpB,OAAO,IAAI,UAAU;GACvB;EACF;CACF;CAEA,OAAO;AACT;AAIA,SAAS,aACP,OACA,MACA,UACA,OACA,KACQ;CACR,IAAI,SAAS,UAAU,GACrB,OAAO,CACL;EAAE,GAAG,MAAM;EAAG,GAAG,MAAM;CAAE,GACzB;EAAE,GAAG,IAAI;EAAG,GAAG,IAAI;CAAE,CACvB;CAIF,MAAM,cAAsB,CAAC;CAC7B,MAAM,eAAuB,CAAC;CAE9B,YAAY,KAAK;EAAE,GAAG,MAAM;EAAG,GAAG,MAAM;CAAE,CAAC;CAC3C,aAAa,KAAK;EAAE,GAAG,MAAM;EAAG,GAAG,MAAM;CAAE,CAAC;CAE5C,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,SAAS,GAAG,KAAK;EAC5C,MAAM,OAAO,KAAK,IAAI,SAAS,EAAG;EAClC,MAAM,SAAS,SAAS,IAAI;EAE5B,IAAI,QAAQ;EACZ,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KACvC,IAAI,KAAK,QAAQ,EAAE,CAAE,eAAe,QAAQ;GAC1C,YAAY,KAAK,KAAK,QAAQ,EAAE,CAAE,CAAC;GACnC,aAAa,KAAK,KAAK,QAAQ,EAAE,CAAE,CAAC;GACpC,QAAQ;GACR;EACF;EAEF,IAAI,CAAC,OAAO;GAEV,MAAM,IAAI,SAAS,KAAK,QAAQ;GAChC,YAAY,KAAK,CAAC;GAClB,aAAa,KAAK,CAAC;EACrB;CACF;CAEA,YAAY,KAAK;EAAE,GAAG,IAAI;EAAG,GAAG,IAAI;CAAE,CAAC;CACvC,aAAa,KAAK;EAAE,GAAG,IAAI;EAAG,GAAG,IAAI;CAAE,CAAC;CAIxC,MAAM,OAAe,CAAC;CAEtB,IAAI,SAAS,YAAY;CACzB,IAAI,SAAS,YAAY;CACzB,IAAI,UAAU,aAAa;CAC3B,IAAI,UAAU;CACd,IAAI,UAAU;CACd,IAAI,WAAW;CAEf,KAAK,KAAK;EAAE,GAAG,OAAO;EAAG,GAAG,OAAO;CAAE,CAAC;CAEtC,MAAM,IAAI,YAAY;CAEtB,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK;EAC1B,MAAM,KAAK,YAAY;EACvB,MAAM,KAAK,aAAa;EAGxB,IAAI,SAAS,QAAQ,SAAS,EAAE,KAAK,GAAG;GACtC,IAAI,OAAO,QAAQ,OAAO,KAAK,SAAS,QAAQ,QAAQ,EAAE,IAAI,GAAG;IAE/D,UAAU;IACV,WAAW;GACb,OAAO;IAEL,UAAU,MAAM,MAAM;IACtB,SAAS;IACT,UAAU;IAEV,SAAS;IACT,UAAU;IACV,UAAU;IACV,WAAW;IAEX,IAAI;IACJ;GACF;EACF;EAGA,IAAI,SAAS,QAAQ,QAAQ,EAAE,KAAK,GAAG;GACrC,IAAI,OAAO,QAAQ,MAAM,KAAK,SAAS,QAAQ,SAAS,EAAE,IAAI,GAAG;IAE/D,SAAS;IACT,UAAU;GACZ,OAAO;IAEL,UAAU,MAAM,OAAO;IACvB,SAAS;IACT,UAAU;IAEV,SAAS;IACT,UAAU;IACV,UAAU;IACV,WAAW;IAEX,IAAI;GACN;EACF;CACF;CAEA,UAAU,MAAM,GAAG;CAEnB,OAAO;AACT;AAEA,SAAS,UAAU,MAAc,GAAe;CAC9C,MAAM,OAAO,KAAK,KAAK,SAAS;CAChC,IAAI,CAAC,QAAQ,KAAK,MAAM,EAAE,KAAK,KAAK,MAAM,EAAE,GAC1C,KAAK,KAAK;EAAE,GAAG,EAAE;EAAG,GAAG,EAAE;CAAE,CAAC;AAEhC;;AAGA,SAAS,SAAS,GAAS,GAAS,GAAiB;CACnD,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;AAC5D;AAEA,SAAS,OAAO,GAAS,GAAkB;CACzC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;AAClC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flare-engine/pathfinding",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "description": "A* grid pathfinding, Jump Point Search, and navmesh for 2D scenes and apps",
5
5
  "keywords": ["flare-engine", "pathfinding", "astar", "jps", "navmesh", "grid"],
6
6
  "license": "Apache-2.0",
@@ -37,7 +37,7 @@
37
37
  "typecheck": "tsc --noEmit"
38
38
  },
39
39
  "dependencies": {
40
- "@flare-engine/math": "^0.4.6"
40
+ "@flare-engine/math": "^0.4.7"
41
41
  },
42
42
  "engines": {
43
43
  "node": ">=20"