UNPKG

@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
'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.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