UNPKG

roguelike-pumpkin-patch

Version:
145 lines 7.26 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; /** Pathfinder to determine how to travel from one point to another */ var PathFinder = /** @class */ (function () { function PathFinder(parameters) { var canPass = parameters.canPass, metric = parameters.metric, maxIterations = parameters.maxIterations, weight = parameters.weight, rest = __rest(parameters, ["canPass", "metric", "maxIterations", "weight"]); this.canPass = canPass; if (!metric) { // Default metric is Manhattan metric, if none provided metric = function (position1, position2) { return Math.abs(position2[1] - position1[1]) + Math.abs(position2[0] - position1[0]); }; } if (!weight) { // Default to everything being length of 1 weight = function (position) { return 1; }; } this.maxIterations = maxIterations; this.metric = metric; this.weight = weight; } /** Find route from startPosition to endPosition, via A* */ PathFinder.prototype.findPath = function (startPosition, endPosition, orthogonalOnly) { var _this = this; if (orthogonalOnly === void 0) { orthogonalOnly = false; } var route = []; // Limit the loop so it doesn't break things var maxIterations = (this.maxIterations) ? this.maxIterations : 40 * this.metric(startPosition, endPosition); var iterations = 0; // Initialize the list, and add the start to it var closedList = [ { position: __spreadArrays(startPosition), steps: 0, distanceFromGoal: this.metric(startPosition, endPosition), previousLocation: null } ]; var openList = []; // Handle diagonals var stepSizeArr = [0, 1, 1.2]; // Find a path while (iterations < maxIterations && !this.contains(closedList, endPosition)) { iterations++; // Expand the open list closedList.forEach(function (location) { for (var i = -1; i < 2; i++) { for (var j = -1; j < 2; j++) { if (orthogonalOnly && i !== 0 && j !== 0) { continue; } var newPosition = [location.position[0] + i, location.position[1] + j]; // Determine the cost / size of step into the square var stepSize = stepSizeArr[Math.abs(i) + Math.abs(j)] * _this.weight(newPosition); if (!_this.canPass(newPosition)) { continue; } var inClosedListAlready = _this.getLocation(closedList, newPosition); var inOpenListAlready = _this.getLocation(openList, newPosition); // New position is in neither list if (!inClosedListAlready && !inOpenListAlready) { openList.push({ position: newPosition, steps: location.steps + stepSize, distanceFromGoal: _this.metric(newPosition, endPosition), previousLocation: location }); } else { // if the position is already in the list, adjust to be whichever version is shorter if (inClosedListAlready && inClosedListAlready.steps > location.steps + stepSize) { inClosedListAlready.steps = location.steps + stepSize; inClosedListAlready.previousLocation = location; } if (inOpenListAlready && inOpenListAlready.steps > location.steps + stepSize) { inOpenListAlready.steps = location.steps + stepSize; inOpenListAlready.previousLocation = location; } } } } }); // Sort the open list (highest --> lowest) openList.sort(function (a, b) { return (b.steps + b.distanceFromGoal) - (a.steps + a.distanceFromGoal); }); // Pop off the lowest openList item and add it to the closed list closedList.push(openList.pop()); } // Found a route! Put the pieces together by working backwards var location = this.getLocation(closedList, endPosition); if (this.contains(closedList, endPosition)) { iterations = 0; while ((location.position[0] !== startPosition[0] || location.position[1] !== startPosition[1]) && iterations < maxIterations) { iterations++; route.push(location.position); location = location.previousLocation; } } return route.reverse(); }; PathFinder.prototype.isEqual = function (position1, position2) { return (position1.position[0] === position2.position[0] && position1.position[1] === position2.position[1]); }; PathFinder.prototype.contains = function (locationList, testLocation) { var _this = this; if (Array.isArray(testLocation)) { return locationList.some(function (location) { return (location.position[0] === testLocation[0] && location.position[1] === testLocation[1]); }); } else { return locationList.some(function (location) { return _this.isEqual(location, testLocation); }); } }; PathFinder.prototype.getLocation = function (locationList, testPosition) { for (var _i = 0, locationList_1 = locationList; _i < locationList_1.length; _i++) { var location_1 = locationList_1[_i]; if (location_1.position[0] === testPosition[0] && location_1.position[1] === testPosition[1]) { return location_1; } } return undefined; }; return PathFinder; }()); export default PathFinder; //# sourceMappingURL=PathFinder.js.map