malwoden
Version:
   
121 lines • 5.09 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.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