UNPKG

@amarillion/helixgraph

Version:

A collection of graph algorithms for game development

47 lines (46 loc) 1.77 kB
import { PriorityQueue } from "../PriorityQueue.js"; import { toSet } from "./pathFinding.js"; /** * Given a weighted graph, find all paths from one source to one or more destinations * @param {*} source * @param {*} destinations * @param {*} getAdjacent * @param {Object} options containing getHeuristic(node), maxIterations, getWeight(edge) * * @returns Map(to, { edge, from, to, cost }) */ export function astar(source, dest, getAdjacent, // see: https://mariusschulz.com/blog/typing-destructured-object-parameters-in-typescript { maxIterations = 0, getWeight = () => 1, getHeuristic = () => 0 } = {}) { const dist = new Map(); const prev = new Map(); const priority = new Map(); const open = new PriorityQueue((a, b) => priority.get(b) - priority.get(a)); open.push(source); dist.set(source, 0); const remain = toSet(dest); let i = maxIterations; while (open.size() > 0) { i--; // 0 -> -1 means Infinite. if (i === 0) break; const current = open.pop(); if (remain.has(current)) { remain.delete(current); if (remain.size === 0) break; // reached all destiniations! } for (const [edge, sibling] of getAdjacent(current)) { const cost = dist.get(current) + getWeight(edge, current); const oldCost = dist.has(sibling) ? dist.get(sibling) : Infinity; if (cost < oldCost) { dist.set(sibling, cost); priority.set(sibling, cost + getHeuristic(sibling)); open.push(sibling); // build back-tracking map prev.set(sibling, { edge, from: current, to: sibling, cost }); } } } return prev; }