UNPKG

malwoden

Version:

![alt text](./coverage/badge-lines.svg) ![alt text](./coverage/badge-statements.svg) ![alt text](./coverage/badge-functions.svg) ![alt text](./coverage/badge-branches.svg)

121 lines 5.09 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Dijkstra = void 0; var struct_1 = require("../struct"); var Calc = require("../calc"); var get_ring_1 = require("../fov/get-ring"); /** * Dijkstra's algorithm is a breadth first search to find the goal. * This makes it slower than AStar in most cases, as it doesn't know * how to 'guess' if a tile is closer to the goal or not. However in * most cases the difference in speed is negligible, and this * version of Dijkstra's algorithm can occasionally result in more * 'normal' looking paths. */ var Dijkstra = /** @class */ (function () { /** * @param config - General parameters for the AStar Pathfinder * @param config.isBlockedCallback - Return true if the position is blocked. * @param config.getTerrainCallback - Provide terrain costs for movement (optional) * @param config.topology - four | eight */ function Dijkstra(config) { this._getDistance = function () { return 1; }; this.topology = config.topology; if (config.getTerrainCallback) { this._getDistance = config.getTerrainCallback; } if (config.isBlockedCallback) { this._isBlocked = config.isBlockedCallback; } } Dijkstra.prototype.getDistance = function (from, to) { if (this._isBlocked && this._isBlocked(to)) return Infinity; return this._getDistance(from, to); }; Dijkstra.prototype.getNeighbors = function (pos) { var neighbors = get_ring_1.getRing4(pos.x, pos.y, 1); if (this.topology === "eight") { neighbors.push({ x: pos.x + 1, y: pos.y - 1 }); neighbors.push({ x: pos.x - 1, y: pos.y - 1 }); neighbors.push({ x: pos.x - 1, y: pos.y + 1 }); neighbors.push({ x: pos.x + 1, y: pos.y + 1 }); } return neighbors; }; Dijkstra.prototype.computePathBack = function (current, cameFrom, visited) { var curStr = current.x + ":" + current.y; var totalPath = [current]; while (cameFrom.get(curStr)) { var prevStr = cameFrom.get(curStr); var _a = prevStr.split(":"), x = _a[0], y = _a[1]; var r = visited.get(prevStr); curStr = prevStr; totalPath.unshift({ x: Number.parseInt(x), y: Number.parseInt(y), r: r, }); } return totalPath; }; /** * Computes a given path from a start and end point. If not path is found, * it will return undefined. Both the start + end points will be returned * in the path. * * @param start Vector2 - The starting point * @param end Vector2 - The ending point * * @returns RangeVector2[] | undefined - Returns the path, * including start + end, or undefined if no path is found. */ Dijkstra.prototype.compute = function (start, end) { var breadcrumbs = new Map(); var visited = new Map(); // Horizon are tiles we've visited, but still need to check neighbors var horizon = new struct_1.ArrayPriorityQueue(function (v) { return v.r; }); // Initialize visited.set(start.x + ":" + start.y, 0); horizon.insert(__assign(__assign({}, start), { r: 0 })); while (horizon.size()) { //shift the last node off the array. var current = horizon.pop(); // check to see if the space is where you need to be. If so, exit loop. if (Calc.Vector.areEqual(current, end)) { return this.computePathBack(current, breadcrumbs, visited); } for (var _i = 0, _a = this.getNeighbors(current); _i < _a.length; _i++) { var n = _a[_i]; var stepDistance = this.getDistance(current, n); var totalDistance = current.r + stepDistance; if (stepDistance === Infinity) continue; // Only interesting if we haven't been there, or if we found a shorter path. var interestingNeighbor = !visited.has(n.x + ":" + n.y) || totalDistance < visited.get(n.x + ":" + n.y); if (interestingNeighbor) { horizon.insert(__assign(__assign({}, n), { r: current.r + stepDistance })); visited.set(n.x + ":" + n.y, totalDistance); breadcrumbs.set(n.x + ":" + n.y, current.x + ":" + current.y); } } } return undefined; }; return Dijkstra; }()); exports.Dijkstra = Dijkstra; //# sourceMappingURL=dijkstra.js.map