@screeps/engine
Version:
This is a module for Screeps standalone server. See [main repository](https://github.com/screeps/screeps) for more info.
424 lines (360 loc) • 16.3 kB
JavaScript
;
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var utils = require('../utils'),
driver = utils.getRuntimeDriver(),
C = driver.constants,
_ = require('lodash'),
pathUtils = require('./path-utils'),
Heap = pathUtils.Heap,
OpenClosed = pathUtils.OpenClosed;
const kRouteGrid = 30;
exports.makeMap = function (runtimeData, register, globals) {
var heap, openClosed, parents;
var originX, originY;
var toX, toY;
let _visual;
const accessibleRooms = JSON.parse(runtimeData.accessibleRooms);
function describeExits(roomName) {
if (!/^(W|E)\d+(N|S)\d+$/.test(roomName)) {
return null;
}
var _utils$roomNameToXY = utils.roomNameToXY(roomName),
_utils$roomNameToXY2 = _slicedToArray(_utils$roomNameToXY, 2),
x = _utils$roomNameToXY2[0],
y = _utils$roomNameToXY2[1];
var gridItem = runtimeData.mapGrid.gridData[`${x},${y}`];
if (!gridItem) {
return null;
}
var exits = {};
if (gridItem.t) {
exits[C.TOP] = utils.getRoomNameFromXY(x, y - 1);
}
if (gridItem.b) {
exits[C.BOTTOM] = utils.getRoomNameFromXY(x, y + 1);
}
if (gridItem.l) {
exits[C.LEFT] = utils.getRoomNameFromXY(x - 1, y);
}
if (gridItem.r) {
exits[C.RIGHT] = utils.getRoomNameFromXY(x + 1, y);
}
return exits;
}
function xyToIndex(xx, yy) {
let ox = originX - xx;
let oy = originY - yy;
if (ox < 0 || ox >= kRouteGrid * 2 || oy < 0 || oy >= kRouteGrid * 2) {
return;
}
return ox * kRouteGrid * 2 + oy;
}
function indexToXY(index) {
return [originX - Math.floor(index / (kRouteGrid * 2)), originY - index % (kRouteGrid * 2)];
}
function heuristic(xx, yy) {
return Math.abs(xx - toX) + Math.abs(yy - toY);
}
const map = {
findRoute(fromRoom, toRoom, opts) {
if (_.isObject(fromRoom)) {
fromRoom = fromRoom.name;
}
if (_.isObject(toRoom)) {
toRoom = toRoom.name;
}
if (fromRoom == toRoom) {
return [];
}
if (!/(W|E)\d+(N|S)\d+$/.test(fromRoom) || !/(W|E)\d+(N|S)\d+$/.test(toRoom)) {
return C.ERR_NO_PATH;
}
var _utils$roomNameToXY3 = utils.roomNameToXY(fromRoom),
_utils$roomNameToXY4 = _slicedToArray(_utils$roomNameToXY3, 2),
fromX = _utils$roomNameToXY4[0],
fromY = _utils$roomNameToXY4[1];
var _utils$roomNameToXY5 = utils.roomNameToXY(toRoom);
var _utils$roomNameToXY6 = _slicedToArray(_utils$roomNameToXY5, 2);
toX = _utils$roomNameToXY6[0];
toY = _utils$roomNameToXY6[1];
if (fromX == toX && fromY == toY) {
return [];
}
originX = fromX + kRouteGrid;
originY = fromY + kRouteGrid;
// Init path finding structures
if (heap) {
heap.clear();
openClosed.clear();
} else {
heap = new Heap(Math.pow(kRouteGrid * 2, 2), Float64Array);
openClosed = new OpenClosed(Math.pow(kRouteGrid * 2, 2));
}
if (!parents) {
parents = new Uint16Array(Math.pow(kRouteGrid * 2, 2));
}
var fromIndex = xyToIndex(fromX, fromY);
heap.push(fromIndex, heuristic(fromX, fromY));
var routeCallback = opts && opts.routeCallback || function () {
return 1;
};
// Astar
while (heap.size()) {
// Pull node off heap
let index = heap.min();
let fcost = heap.minPriority();
// Close this node
heap.pop();
openClosed.close(index);
// Calculate costs
var _indexToXY = indexToXY(index),
_indexToXY2 = _slicedToArray(_indexToXY, 2);
let xx = _indexToXY2[0],
yy = _indexToXY2[1];
let hcost = heuristic(xx, yy);
let gcost = fcost - hcost;
// Reached destination?
if (hcost === 0) {
let route = [];
while (index !== fromIndex) {
var _indexToXY3 = indexToXY(index),
_indexToXY4 = _slicedToArray(_indexToXY3, 2);
let xx = _indexToXY4[0],
yy = _indexToXY4[1];
index = parents[index];
var _indexToXY5 = indexToXY(index),
_indexToXY6 = _slicedToArray(_indexToXY5, 2);
let nx = _indexToXY6[0],
ny = _indexToXY6[1];
let dir;
if (nx < xx) {
dir = C.FIND_EXIT_RIGHT;
} else if (nx > xx) {
dir = C.FIND_EXIT_LEFT;
} else if (ny < yy) {
dir = C.FIND_EXIT_BOTTOM;
} else {
dir = C.FIND_EXIT_TOP;
}
route.push({
exit: dir,
room: utils.getRoomNameFromXY(xx, yy)
});
}
route.reverse();
return route;
}
// Add neighbors
let fromRoomName = utils.getRoomNameFromXY(xx, yy);
let exits = describeExits(fromRoomName);
for (let dir in exits) {
// Calculate costs and check if this node was already visited
let roomName = exits[dir];
let graphKey = fromRoomName + ':' + roomName;
var _utils$roomNameToXY7 = utils.roomNameToXY(roomName),
_utils$roomNameToXY8 = _slicedToArray(_utils$roomNameToXY7, 2);
let xx = _utils$roomNameToXY8[0],
yy = _utils$roomNameToXY8[1];
let neighborIndex = xyToIndex(xx, yy);
if (neighborIndex === undefined || openClosed.isClosed(neighborIndex)) {
continue;
}
let cost = Number(routeCallback(roomName, fromRoomName)) || 1;
if (cost === Infinity) {
continue;
}
let fcost = gcost + heuristic(xx, yy) + cost;
// Add to or update heap
if (openClosed.isOpen(neighborIndex)) {
if (heap.priority(neighborIndex) > fcost) {
heap.update(neighborIndex, fcost);
parents[neighborIndex] = index;
}
} else {
heap.push(neighborIndex, fcost);
openClosed.open(neighborIndex);
parents[neighborIndex] = index;
}
}
}
return C.ERR_NO_PATH;
},
findExit(fromRoom, toRoom, opts) {
var route = this.findRoute(fromRoom, toRoom, opts);
if (!_.isArray(route)) {
return route;
}
if (!route.length) {
return C.ERR_INVALID_ARGS;
}
return route[0].exit;
},
describeExits,
isRoomAvailable(roomName) {
register.deprecated('Method `Game.map.isRoomAvailable` is deprecated and will be removed. Please use `Game.map.getRoomStatus` instead.');
if (!/^(W|E)\d+(N|S)\d+$/.test(roomName)) {
return false;
}
return _.contains(accessibleRooms, roomName);
},
getRoomStatus(roomName) {
if (!/^(W|E)\d+(N|S)\d+$/.test(roomName)) {
return undefined;
}
if (!runtimeData.roomStatusData) {
throw new Error('No runtime status data');
}
if (!_.isUndefined(runtimeData.roomStatusData.closed[roomName])) {
return { status: 'closed', timestamp: runtimeData.roomStatusData.closed[roomName] };
}
if (!_.isUndefined(runtimeData.roomStatusData.novice[roomName])) {
return { status: 'novice', timestamp: runtimeData.roomStatusData.novice[roomName] };
}
if (!_.isUndefined(runtimeData.roomStatusData.respawn[roomName])) {
return { status: 'respawn', timestamp: runtimeData.roomStatusData.respawn[roomName] };
}
if (_.contains(accessibleRooms, roomName)) {
return { status: 'normal', timestamp: null };
}
return { status: 'closed', timestamp: null };
},
getTerrainAt(x, y, roomName) {
register.deprecated('Method `Game.map.getTerrainAt` is deprecated and will be removed. Please use a faster method `Game.map.getRoomTerrain` instead.');
if (_.isObject(x)) {
y = x.y;
roomName = x.roomName;
x = x.x;
}
// check if coordinates are out of bounds
if (x < 0 || x > 49 || y < 0 || y > 49) {
return undefined;
}
if (!runtimeData.staticTerrainData || !runtimeData.staticTerrainData[roomName]) {
return undefined;
}
var terrain = runtimeData.staticTerrainData[roomName][y * 50 + x];
if (terrain & C.TERRAIN_MASK_WALL) {
return 'wall';
}
if (terrain & C.TERRAIN_MASK_SWAMP) {
return 'swamp';
}
return 'plain';
},
getRoomTerrain(roomName) {
return new globals.Room.Terrain(roomName);
},
getRoomLinearDistance(roomName1, roomName2, continuous) {
return utils.calcRoomsDistance(roomName1, roomName2, continuous);
},
getWorldSize() {
return driver.getWorldSize();
}
};
Object.defineProperties(map, {
visual: {
enumerable: true,
get() {
if (!_visual) {
_visual = {};
Object.defineProperties(_visual, {
circle: {
value: function (pos, style) {
if (!(pos instanceof globals.RoomPosition)) {
throw new Error('Invalid pos, RoomPosition expected');
}
globals.console.addVisual("map", {
t: 'c',
x: pos.x, y: pos.y, n: pos.roomName,
s: style || {} });
return this;
}
},
line: {
value: function (pos1, pos2, style) {
if (!(pos1 instanceof globals.RoomPosition)) {
throw new Error('Invalid pos1, RoomPosition expected');
}
if (!(pos2 instanceof globals.RoomPosition)) {
throw new Error('Invalid pos2, RoomPosition expected');
}
globals.console.addVisual("map", {
t: 'l',
x1: pos1.x, y1: pos1.y, n1: pos1.roomName,
x2: pos2.x, y2: pos2.y, n2: pos2.roomName,
s: style || {} });
return this;
}
},
rect: {
value: function (pos, w, h, style) {
if (!(pos instanceof globals.RoomPosition)) {
throw new Error('Invalid pos, RoomPosition expected');
}
globals.console.addVisual("map", {
t: 'r',
x: pos.x, y: pos.y, n: pos.roomName,
w, h,
s: style || {} });
return this;
}
},
poly: {
value: function (points, style) {
if (_.isArray(points) && _.some(points)) {
points = points.map(i => {
const p = i.pos || i;
return { x: p.x, y: p.y, n: p.roomName };
});
globals.console.addVisual("map", {
t: 'p',
points,
s: style || {} });
}
return this;
}
},
text: {
value: function (text, pos, style) {
if (!(pos instanceof globals.RoomPosition)) {
throw new Error('Invalid pos , RoomPosition expected');
}
globals.console.addVisual("map", {
t: 't',
text,
x: pos.x, y: pos.y, n: pos.roomName,
s: style || {} });
return this;
}
},
clear: {
value: function () {
globals.console.clearVisual("map");
return this;
}
},
getSize: {
value: function () {
return globals.console.getVisualSize("map");
}
},
export: {
value: function () {
return globals.console.getVisual("map");
}
},
import: {
value: function (data) {
globals.console.addVisual("map", "" + data);
return this;
}
}
});
}
return _visual;
}
}
});
return map;
};
//# sourceMappingURL=../sourcemaps/game/map.js.map