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)

133 lines 5.47 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.AStar = void 0; var get_ring_1 = require("../fov/get-ring"); var Calc = require("../calc"); var struct_1 = require("../struct"); /** * AStar is a path finding algorithm that attempts search tiles closer * the goal. It estimates a tiles score as the known distance to that * tile, plus the distance to goal as the bird flies. It will always * first evaluate the tile it knows to currently have the score, * and continue from there. */ var AStar = /** @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 AStar(config) { this._getTerrainCallback = function () { return 1; }; this._isBlocked = config.isBlockedCallback; this.topology = config.topology; if (config.getTerrainCallback) { this._getTerrainCallback = config.getTerrainCallback; } } AStar.prototype.getDistance = function (from, to) { if (this._isBlocked && this._isBlocked(to)) return Infinity; return this._getTerrainCallback(from, to); }; /** * Get all neightbors of a point. Returns orthogonal * directions first, then diagonal if topology is 8. * Results in more natural looking paths. * @param pos - Vector2 */ AStar.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; }; AStar.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. */ AStar.prototype.compute = function (start, end) { // visited tracks the cheapest known distance to a spot // estimate tracks visited score + heuristic var visited = new Map(); visited.set(start.x + ":" + start.y, 0); // Nodes where we still need to check neighbors, prioritized by fscore // The RangeVector here will be partly redundant with the value // tracked by visited var horizon = new struct_1.ArrayPriorityQueue(function (_a) { var _ = _a[0], fscore = _a[1]; return fscore; }); horizon.insert([ __assign(__assign({}, start), { r: 0 }), Calc.Vector.getDistance(start, end, "eight"), ]); // Find our way home var breadcrumbs = new Map(); while (horizon.size()) { var _a = horizon.pop(), current = _a[0], _ = _a[1]; // If we're at the end, find our path and return if (Calc.Vector.areEqual(current, end)) { return this.computePathBack(current, breadcrumbs, visited); } for (var _i = 0, _b = this.getNeighbors(current); _i < _b.length; _i++) { var n = _b[_i]; var nr = current.r + this.getDistance(current, n); // If neighbor range is infinity, we can't get there if (nr === Infinity) continue; var interestingNeighbor = !visited.has(n.x + ":" + n.y) || nr < visited.get(n.x + ":" + n.y); if (interestingNeighbor) { breadcrumbs.set(n.x + ":" + n.y, current.x + ":" + current.y); visited.set(n.x + ":" + n.y, nr); var estimate = nr + Calc.Vector.getDistance(n, end, "eight"); horizon.insert([__assign(__assign({}, n), { r: nr }), estimate]); } } } // We never got current == end return undefined; }; return AStar; }()); exports.AStar = AStar; //# sourceMappingURL=astar.js.map