UNPKG

@screeps/engine

Version:

This is a module for Screeps standalone server. See [main repository](https://github.com/screeps/screeps) for more info.

278 lines (231 loc) 10.1 kB
'use strict'; 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.getDriver(), C = driver.constants, _ = require('lodash'), util = require('util'), pathUtils = require('./path-utils'), Heap = pathUtils.Heap, OpenClosed = pathUtils.OpenClosed; var kRouteGrid = 30; exports.makeMap = function (runtimeData, register) { var heap, openClosed, parents; var originX, originY; var toX, toY; 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) { var ox = originX - xx; var 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); } return { findRoute: function 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 var index = heap.min(); var fcost = heap.minPriority(); // Close this node heap.pop(); openClosed.close(index); // Calculate costs var _indexToXY = indexToXY(index), _indexToXY2 = _slicedToArray(_indexToXY, 2), xx = _indexToXY2[0], yy = _indexToXY2[1]; var hcost = heuristic(xx, yy); var gcost = fcost - hcost; // Reached destination? if (hcost === 0) { var route = []; while (index !== fromIndex) { var _indexToXY3 = indexToXY(index), _indexToXY4 = _slicedToArray(_indexToXY3, 2), _xx = _indexToXY4[0], _yy = _indexToXY4[1]; index = parents[index]; var _indexToXY5 = indexToXY(index), _indexToXY6 = _slicedToArray(_indexToXY5, 2), nx = _indexToXY6[0], ny = _indexToXY6[1]; var dir = void 0; 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 var fromRoomName = utils.getRoomNameFromXY(xx, yy); var exits = describeExits(fromRoomName); for (var _dir in exits) { // Calculate costs and check if this node was already visited var roomName = exits[_dir]; var graphKey = fromRoomName + ':' + roomName; var _utils$roomNameToXY7 = utils.roomNameToXY(roomName), _utils$roomNameToXY8 = _slicedToArray(_utils$roomNameToXY7, 2), _xx2 = _utils$roomNameToXY8[0], _yy2 = _utils$roomNameToXY8[1]; var neighborIndex = xyToIndex(_xx2, _yy2); if (neighborIndex === undefined || openClosed.isClosed(neighborIndex)) { continue; } var cost = Number(routeCallback(roomName, fromRoomName)) || 1; if (cost === Infinity) { continue; } var _fcost = gcost + heuristic(_xx2, _yy2) + 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: function 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: describeExits, isRoomProtected: function isRoomProtected(roomName) { register.deprecated('Method `Game.map.isRoomProtected` is deprecated and will be removed. Please use `Game.map.isRoomAvailable` instead.'); if (!/^(W|E)\d+(N|S)\d+$/.test(roomName)) { return null; } return !_.contains(runtimeData.accessibleRooms, roomName); }, isRoomAvailable: function isRoomAvailable(roomName) { if (!/^(W|E)\d+(N|S)\d+$/.test(roomName)) { return false; } return _.contains(runtimeData.accessibleRooms, roomName); }, getTerrainAt: function getTerrainAt(x, y, roomName) { if (_.isObject(x)) { y = x.y; roomName = x.roomName; x = x.x; } 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'; }, getRoomLinearDistance: function getRoomLinearDistance(roomName1, roomName2, continuous) { return utils.calcRoomsDistance(roomName1, roomName2, continuous); }, getWorldSize: function getWorldSize() { return driver.getWorldSize(); } }; }; //# sourceMappingURL=../sourcemaps/game/map.js.map