malwoden
Version:
   
133 lines • 5.47 kB
JavaScript
;
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