UNPKG

@screeps/engine

Version:

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

1,407 lines (1,156 loc) 52.2 kB
'use strict'; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 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"); } }; }(); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var _ = require('lodash'), utils = require('./../utils'), driver = utils.getDriver(), C = driver.constants, pathfinding = require('@screeps/pathfinding'); var abs = Math.abs, min = Math.min, max = Math.max; var runtimeData, intents, register, globals; var positionsSetCacheCounter, createdFlagNames, createdSpawnNames, privateStore, createdConstructionSites; function getPathfinder(id, opts) { opts = opts || {}; _.defaults(opts, { maxOps: 2000, heuristicWeight: 1 }); var key = opts.maxOps + ',' + opts.heuristicWeight; if (!privateStore[id].pfFinders[key]) { privateStore[id].pfFinders[key] = new pathfinding.AStarFinder({ diagonalMovement: 1, maxOpsLimit: opts.maxOps, heuristic: pathfinding.Heuristic.chebyshev, weight: opts.heuristicWeight }); } return privateStore[id].pfFinders[key]; } function makePathfindingGrid(id, opts, endNodesKey) { opts = opts || {}; var rows = new Array(50), obstacleTypes = _.clone(C.OBSTACLE_OBJECT_TYPES); if (opts.ignoreDestructibleStructures) { obstacleTypes = _.without(obstacleTypes, 'constructedWall', 'spawn', 'extension', 'link', 'storage', 'observer', 'tower', 'powerBank', 'powerSpawn', 'lab', 'terminal'); } if (opts.ignoreCreeps) { obstacleTypes = _.without(obstacleTypes, 'creep'); } for (var y = 0; y < 50; y++) { rows[y] = new Array(50); for (var x = 0; x < 50; x++) { rows[y][x] = x == 0 || y == 0 || x == 49 || y == 49 ? 11 : 2; //var terrainCode = register.terrainByRoom.spatial[id][y][x]; var terrainCode = runtimeData.staticTerrainData[id][y * 50 + x]; if (terrainCode & C.TERRAIN_MASK_WALL) { rows[y][x] = 0; } if (terrainCode & C.TERRAIN_MASK_SWAMP && rows[y][x] == 2) { rows[y][x] = 10; } } } register.objectsByRoomKeys[id].forEach(function (key) { var object = register.objectsByRoom[id][key]; if (_.contains(obstacleTypes, object.type) || !opts.ignoreDestructibleStructures && object.type == 'rampart' && !object.isPublic && object.user != runtimeData.user._id || !opts.ignoreDestructibleStructures && object.type == 'constructionSite' && object.user == runtimeData.user._id && _.contains(C.OBSTACLE_OBJECT_TYPES, object.structureType)) { rows[object.y][object.x] = 0; } if (object.type == 'road' && rows[object.y][object.x] > 0) { rows[object.y][object.x] = 1; } }); if (opts.ignore) { if (!_.isArray(opts.ignore)) { throw new Error('option `ignore` is not an array'); } _.forEach(opts.ignore, function (i, key) { if (!i) { return; } if (i.pos) { rows[i.pos.y][i.pos.x] = rows[i.pos.y][i.pos.x] > 2 ? 2 : rows[i.pos.y][i.pos.x]; } if (_.isObject(i) && !_.isUndefined(i.x) && !(i instanceof globals.RoomPosition)) { opts.ignore[key] = new globals.RoomPosition(i.x, i.y, id); } if (!_.isUndefined(i.x)) { rows[i.y][i.x] = rows[i.y][i.x] > 2 ? 2 : rows[i.y][i.x]; } }); } if (opts.avoid) { if (!_.isArray(opts.avoid)) { throw new Error('option `avoid` is not an array'); } _.forEach(opts.avoid, function (i, key) { if (!i) { return; } if (i.pos) { rows[i.pos.y][i.pos.x] = 0; } if (_.isObject(i) && !_.isUndefined(i.x) && !(i instanceof globals.RoomPosition)) { opts.avoid[key] = new globals.RoomPosition(i.x, i.y, id); } if (!_.isUndefined(i.x)) { rows[i.y][i.x] = 0; } }); } if (endNodesKey) { _.forEach(privateStore[id].pfEndNodes[endNodesKey], function (i) { if (!_.isUndefined(i.x)) { rows[i.y][i.x] = 999; } else if (!_.isUndefined(i.pos)) { rows[i.pos.y][i.pos.x] = 999; } }); } return new pathfinding.Grid(50, 50, rows); } function getPathfindingGrid(id, opts, endNodesKey) { var gridName = 'grid'; opts = opts || {}; if (opts.ignoreCreeps) { gridName += '_ignoreCreeps'; } if (opts.ignoreDestructibleStructures) { gridName += '_ignoreDestructibleStructures'; } if (_.isNumber(endNodesKey)) { gridName += '_endNodes' + endNodesKey; } if (opts.avoid) { gridName += '_avoid' + privateStore[id].positionsSetCache.key(opts.avoid); } if (opts.ignore) { gridName += '_ignore' + privateStore[id].positionsSetCache.key(opts.ignore); } if (!privateStore[id].pfGrid[gridName]) privateStore[id].pfGrid[gridName] = makePathfindingGrid(id, opts, endNodesKey); return privateStore[id].pfGrid[gridName].clone(); } function makePathfindingGrid2(id, opts) { opts = opts || {}; var costs = new globals.PathFinder.CostMatrix(); var obstacleTypes = _.clone(C.OBSTACLE_OBJECT_TYPES); obstacleTypes.push('portal'); if (opts.ignoreDestructibleStructures) { obstacleTypes = _.without(obstacleTypes, 'constructedWall', 'spawn', 'extension', 'link', 'storage', 'observer', 'tower', 'powerBank', 'powerSpawn', 'lab', 'terminal'); } if (opts.ignoreCreeps || register.rooms[id].controller && register.rooms[id].controller.safeMode && register.rooms[id].controller.my) { obstacleTypes = _.without(obstacleTypes, 'creep'); } if (register.objectsByRoomKeys[id]) { register.objectsByRoomKeys[id].forEach(function (key) { var object = register.objectsByRoom[id][key]; if (_.contains(obstacleTypes, object.type) || !opts.ignoreCreeps && register.rooms[id].controller && register.rooms[id].controller.safeMode && register.rooms[id].controller.my && object.type == 'creep' && object.user == runtimeData.user._id || !opts.ignoreDestructibleStructures && object.type == 'rampart' && !object.isPublic && object.user != runtimeData.user._id || !opts.ignoreDestructibleStructures && object.type == 'constructionSite' && object.user == runtimeData.user._id && _.contains(C.OBSTACLE_OBJECT_TYPES, object.structureType)) { costs.set(object.x, object.y, 0xFF); } if (object.type == 'swamp' && costs.get(object.x, object.y) == 0) { costs.set(object.x, object.y, opts.ignoreRoads ? 5 : 10); } if (!opts.ignoreRoads && object.type == 'road' && costs.get(object.x, object.y) < 0xFF) { costs.set(object.x, object.y, 1); } }); } return costs; } function getPathfindingGrid2(id, opts) { if (!privateStore[id]) { return new globals.PathFinder.CostMatrix(); } var gridName = 'grid2'; opts = opts || {}; if (opts.ignoreCreeps) { gridName += '_ignoreCreeps'; } if (opts.ignoreDestructibleStructures) { gridName += '_ignoreDestructibleStructures'; } if (opts.ignoreRoads) { gridName += '_ignoreRoads'; } if (!privateStore[id].pfGrid[gridName]) privateStore[id].pfGrid[gridName] = makePathfindingGrid2(id, opts); return privateStore[id].pfGrid[gridName]; } function _findPath2(id, fromPos, toPos, opts) { opts = opts || {}; if (fromPos.isEqualTo(toPos)) { return opts.serialize ? '' : []; } if (opts.avoid) { register.deprecated('`avoid` option cannot be used when `PathFinder.use()` is enabled. Use `costCallback` instead.'); opts.avoid = undefined; } if (opts.ignore) { register.deprecated('`ignore` option cannot be used when `PathFinder.use()` is enabled. Use `costCallback` instead.'); opts.ignore = undefined; } if (opts.maxOps === undefined && (opts.maxRooms === undefined || opts.maxRooms > 1) && fromPos.roomName != toPos.roomName) { opts.maxOps = 20000; } var searchOpts = { roomCallback: function roomCallback(roomName) { var costMatrix = getPathfindingGrid2(roomName, opts); if (typeof opts.costCallback == 'function') { costMatrix = costMatrix.clone(); var resultMatrix = opts.costCallback(roomName, costMatrix); if (resultMatrix instanceof globals.PathFinder.CostMatrix) { costMatrix = resultMatrix; } } return costMatrix; }, maxOps: opts.maxOps, maxRooms: opts.maxRooms }; if (!opts.ignoreRoads) { searchOpts.plainCost = 2; searchOpts.swampCost = 10; } var ret = globals.PathFinder.search(fromPos, { range: Math.max(1, opts.range || 0), pos: toPos }, searchOpts); if (!opts.range && (ret.path.length && ret.path[ret.path.length - 1].isNearTo(toPos) && !ret.path[ret.path.length - 1].isEqualTo(toPos) || !ret.path.length && fromPos.isNearTo(toPos))) { ret.path.push(toPos); } var curX = fromPos.x, curY = fromPos.y; var resultPath = []; for (var i = 0; i < ret.path.length; i++) { var pos = ret.path[i]; if (pos.roomName != id) { break; } var result = { x: pos.x, y: pos.y, dx: pos.x - curX, dy: pos.y - curY, direction: utils.getDirection(pos.x - curX, pos.y - curY) }; curX = result.x; curY = result.y; resultPath.push(result); } if (opts.serialize) { return utils.serializePath(resultPath); } return resultPath; } function _findClosestByPath2(fromPos, objects, opts) { opts = opts || {}; if (_.isNumber(objects)) { objects = register.rooms[fromPos.roomName].find(objects, { filter: opts.filter }); } else if (opts.filter) { objects = _.filter(objects, opts.filter); } if (!objects.length) { return null; } var objectOnSquare = _.find(objects, function (obj) { return fromPos.isEqualTo(obj); }); if (objectOnSquare) { return objectOnSquare; } var goals = _.map(objects, function (i) { if (i.pos) { i = i.pos; } return { range: 1, pos: i }; }); if (opts.avoid) { register.deprecated('`avoid` option cannot be used when `PathFinder.use()` is enabled. Use `costCallback` instead.'); } if (opts.ignore) { register.deprecated('`ignore` option cannot be used when `PathFinder.use()` is enabled. Use `costCallback` instead.'); } var searchOpts = { roomCallback: function roomCallback(roomName) { if (register.objectsByRoom[roomName]) { var costMatrix = getPathfindingGrid2(roomName, opts); if (typeof opts.costCallback == 'function') { costMatrix = costMatrix.clone(); var resultMatrix = opts.costCallback(roomName, costMatrix); if (resultMatrix instanceof globals.PathFinder.CostMatrix) { costMatrix = resultMatrix; } } return costMatrix; } }, maxOps: opts.maxOps, maxRooms: 1 }; if (!opts.ignoreRoads) { searchOpts.plainCost = 2; searchOpts.swampCost = 10; } var ret = globals.PathFinder.search(fromPos, goals, searchOpts); var result = null; var lastPos = fromPos; if (ret.path.length) { lastPos = ret.path[ret.path.length - 1]; } objects.forEach(function (obj) { if (lastPos.isNearTo(obj)) { result = obj; } }); return result; } exports.make = function (_runtimeData, _intents, _register, _globals) { runtimeData = _runtimeData; intents = _intents; register = _register; globals = _globals; positionsSetCacheCounter = 1; createdFlagNames = []; createdSpawnNames = []; privateStore = {}; createdConstructionSites = 0; if (globals.Room) { return; } var data = function data(id) { if (!runtimeData.rooms[id]) { throw new Error("Could not find a room with name " + id); } return runtimeData.rooms[id]; }; /** * Room * @param id * @returns {number} * @constructor */ var Room = register.wrapFn(function (id) { var objectData = data(id); var gameInfo, gameId = id, match = id.match(/survival_(.*)$/); if (match) { gameId = match[1]; } if (runtimeData.games && gameId in runtimeData.games) { gameInfo = runtimeData.games[gameId]; } this.name = id; this.energyAvailable = 0; this.energyCapacityAvailable = 0; this.survivalInfo = gameInfo; privateStore[id] = { pfGrid: {}, pfFinders: {}, pfEndNodes: {}, pfDijkstraFinder: new pathfinding.DijkstraFinder({ diagonalMovement: 1 }), pathCache: {}, positionsSetCache: { cache: {}, key: function key(array) { if (!_.isArray(array)) { return 0; } var positionsArray = _.map(array, function (i) { if (i && i.pos) { return i.pos; } if (_.isObject(i) && !_.isUndefined(i.x) && !(i instanceof globals.RoomPosition)) { return new globals.RoomPosition(i.x, i.y, id); } return i; }); var key = _.findKey(this.cache, function (objects) { return positionsArray.length == objects.length && _.every(positionsArray, function (j) { return _.any(objects, function (object) { if (!_.isObject(j) || !j.isEqualTo) { throw new Error('Invalid position ' + j + ', check your `opts` property'); } return j.isEqualTo(object); }); }); }); if (key === undefined) { key = positionsSetCacheCounter++; this.cache[key] = _.clone(array); } else { key = parseInt(key); } return key; } }, lookTypeRegisters: { creep: register.byRoom[id].creeps, energy: register.byRoom[id].energy, resource: register.byRoom[id].energy, source: register.byRoom[id].sources, mineral: register.byRoom[id].minerals, structure: register.byRoom[id].structures, flag: register.byRoom[id].flags, constructionSite: register.byRoom[id].constructionSites, nuke: register.byRoom[id].nukes }, lookTypeSpatialRegisters: { creep: register.byRoom[id].spatial.creeps, energy: register.byRoom[id].spatial.energy, resource: register.byRoom[id].spatial.energy, source: register.byRoom[id].spatial.sources, mineral: register.byRoom[id].spatial.minerals, structure: register.byRoom[id].spatial.structures, flag: register.byRoom[id].spatial.flags, constructionSite: register.byRoom[id].spatial.constructionSites, nuke: register.byRoom[id].spatial.nukes } }; this.visual = new globals.RoomVisual(id); }); Room.serializePath = register.wrapFn(function (path) { return utils.serializePath(path); }); Room.deserializePath = register.wrapFn(function (str) { return utils.deserializePath(str); }); Room.prototype.toString = register.wrapFn(function () { return '[room ' + this.name + ']'; }); Room.prototype.toJSON = register.wrapFn(function () { var result = {}; for (var i in this) { if (i[0] == '_' || _.contains(['toJSON', 'toString', 'controller', 'storage', 'terminal'], i)) { continue; } result[i] = this[i]; } return result; }); Object.defineProperty(Room.prototype, 'memory', { get: function get() { if (_.isUndefined(globals.Memory.rooms) || globals.Memory.rooms === 'undefined') { globals.Memory.rooms = {}; } if (!_.isObject(globals.Memory.rooms)) { return undefined; } return globals.Memory.rooms[this.name] = globals.Memory.rooms[this.name] || {}; }, set: function set(value) { if (_.isUndefined(globals.Memory.rooms) || globals.Memory.rooms === 'undefined') { globals.Memory.rooms = {}; } if (!_.isObject(globals.Memory.rooms)) { throw new Error('Could not set room memory'); } globals.Memory.rooms[this.name] = value; } }); Room.prototype.find = register.wrapFn(function (type, opts) { var _this = this; var result = []; opts = opts || {}; if (type === C.FIND_DROPPED_ENERGY) { register.deprecated('FIND_DROPPED_ENERGY constant is considered deprecated and will be removed soon. Please use FIND_DROPPED_RESOURCES instead.'); type = C.FIND_DROPPED_RESOURCES; } if (register.findCache[type] && register.findCache[type][this.name]) { result = register.findCache[type][this.name]; } else { switch (type) { case C.FIND_EXIT: register.findCache[type] = register.findCache[type] || {}; register.findCache[type][this.name] = this.find(C.FIND_EXIT_TOP, opts).concat(this.find(C.FIND_EXIT_BOTTOM, opts)).concat(this.find(C.FIND_EXIT_RIGHT, opts)).concat(this.find(C.FIND_EXIT_LEFT, opts)); return _.clone(register.findCache[type][this.name]); case C.FIND_EXIT_TOP: case C.FIND_EXIT_RIGHT: case C.FIND_EXIT_BOTTOM: case C.FIND_EXIT_LEFT: register.findCache[type] = register.findCache[type] || {}; var exits = []; for (var i = 0; i < 50; i++) { var x = 0, y = 0; if (type == C.FIND_EXIT_LEFT || type == C.FIND_EXIT_RIGHT) { y = i; } else { x = i; } if (type == C.FIND_EXIT_RIGHT) { x = 49; } if (type == C.FIND_EXIT_BOTTOM) { y = 49; } exits.push(!(runtimeData.staticTerrainData[this.name][y * 50 + x] & C.TERRAIN_MASK_WALL)); } result = _.reduce(exits, function (accum, i, key) { if (i) { if (type == C.FIND_EXIT_TOP) { accum.push(_this.getPositionAt(key, 0)); } if (type == C.FIND_EXIT_BOTTOM) { accum.push(_this.getPositionAt(key, 49)); } if (type == C.FIND_EXIT_LEFT) { accum.push(_this.getPositionAt(0, key)); } if (type == C.FIND_EXIT_RIGHT) { accum.push(_this.getPositionAt(49, key)); } } return accum; }, []); register.findCache[type][this.name] = result; break; } } if (opts.filter) { result = _.filter(result, opts.filter); } else { result = _.clone(result); } return result; }); function _lookSpatialRegister(id, typeName, x, y, outArray, withCoords) { var item; if (typeName == 'terrain') { var result = 'plain'; var terrainCode = runtimeData.staticTerrainData[id][y * 50 + x]; if (terrainCode & C.TERRAIN_MASK_SWAMP) { result = 'swamp'; } if (terrainCode & C.TERRAIN_MASK_WALL) { result = 'wall'; } if (outArray) { item = { type: 'terrain', terrain: result }; if (withCoords) { item.x = x; item.y = y; } outArray.push(item); return; } return [result]; } if (x < 0 || y < 0 || x > 49 || y > 49) { throw new Error('look coords are out of bounds'); } var typeResult = privateStore[id].lookTypeSpatialRegisters[typeName][y][x]; if (typeResult) { if (outArray) { typeResult.forEach(function (i) { item = { type: typeName }; item[typeName] = i; if (withCoords) { item.x = x; item.y = y; } outArray.push(item); }); return; } return _.clone(typeResult); } return []; } function _lookAreaMixedRegister(id, type, top, left, bottom, right, withType, asArray, result) { var typeRegister = privateStore[id].lookTypeRegisters[type], keys = typeRegister && Object.keys(typeRegister); if (type != 'terrain' && keys.length < (bottom - top + 1) * (right - left + 1)) { // by objects var checkInside = function checkInside(i) { return (!i.pos && i.roomName == id || i.pos && i.pos.roomName == id) && i.pos && i.pos.y >= top && i.pos.y <= bottom && i.pos.x >= left && i.pos.x <= right || !i.pos && i.y >= top && i.y <= bottom && i.x >= left && i.x <= right; }; var item; keys.forEach(function (key) { var obj = typeRegister[key]; if (checkInside(obj)) { if (withType) { item = { type: type }; item[type] = obj; if (asArray) { result.push(_defineProperty({ x: obj.x || obj.pos.x, y: obj.y || obj.pos.y, type: type }, type, obj)); } else { result[obj.y || obj.pos.y][obj.x || obj.pos.x].push(item); } } else { if (asArray) { result.push(_defineProperty({ x: obj.x || obj.pos.x, y: obj.y || obj.pos.y }, type, obj)); } else { result[obj.y || obj.pos.y][obj.x || obj.pos.x] = result[obj.y || obj.pos.y][obj.x || obj.pos.x] || []; result[obj.y || obj.pos.y][obj.x || obj.pos.x].push(obj); } } } }); } else { // spatial for (var y = top; y <= bottom; y++) { for (var x = left; x <= right; x++) { if (asArray) { _lookSpatialRegister(id, type, x, y, result, true); } else { if (result[y][x]) { _lookSpatialRegister(id, type, x, y, result[y][x]); } else { result[y][x] = _lookSpatialRegister(id, type, x, y, undefined); } } } } } } Room.prototype.lookAt = register.wrapFn(function (firstArg, secondArg) { var _utils$fetchXYArgumen = utils.fetchXYArguments(firstArg, secondArg, globals), _utils$fetchXYArgumen2 = _slicedToArray(_utils$fetchXYArgumen, 2), x = _utils$fetchXYArgumen2[0], y = _utils$fetchXYArgumen2[1], result = []; _lookSpatialRegister(this.name, C.LOOK_CREEPS, x, y, result); _lookSpatialRegister(this.name, C.LOOK_ENERGY, x, y, result); _lookSpatialRegister(this.name, C.LOOK_RESOURCES, x, y, result); _lookSpatialRegister(this.name, C.LOOK_SOURCES, x, y, result); _lookSpatialRegister(this.name, C.LOOK_MINERALS, x, y, result); _lookSpatialRegister(this.name, C.LOOK_STRUCTURES, x, y, result); _lookSpatialRegister(this.name, C.LOOK_FLAGS, x, y, result); _lookSpatialRegister(this.name, C.LOOK_CONSTRUCTION_SITES, x, y, result); _lookSpatialRegister(this.name, C.LOOK_TERRAIN, x, y, result); _lookSpatialRegister(this.name, C.LOOK_NUKES, x, y, result); return result; }); Room.prototype.lookForAt = register.wrapFn(function (type, firstArg, secondArg) { var _utils$fetchXYArgumen3 = utils.fetchXYArguments(firstArg, secondArg, globals), _utils$fetchXYArgumen4 = _slicedToArray(_utils$fetchXYArgumen3, 2), x = _utils$fetchXYArgumen4[0], y = _utils$fetchXYArgumen4[1]; if (type != 'terrain' && !(type in privateStore[this.name].lookTypeSpatialRegisters)) { return C.ERR_INVALID_ARGS; } return _lookSpatialRegister(this.name, type, x, y); }); Room.prototype.lookAtArea = register.wrapFn(function (top, left, bottom, right, asArray) { var result = asArray ? [] : {}; if (!asArray) { for (var y = top; y <= bottom; y++) { result[y] = {}; for (var x = left; x <= right; x++) { result[y][x] = []; } } } _lookAreaMixedRegister(this.name, C.LOOK_CREEPS, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_ENERGY, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_RESOURCES, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_SOURCES, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_MINERALS, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_STRUCTURES, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_FLAGS, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_CONSTRUCTION_SITES, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_TERRAIN, top, left, bottom, right, true, asArray, result); _lookAreaMixedRegister(this.name, C.LOOK_NUKES, top, left, bottom, right, true, asArray, result); return result; }); Room.prototype.lookForAtArea = register.wrapFn(function (type, top, left, bottom, right, asArray) { var result = asArray ? [] : {}; if (!asArray) { for (var y = top; y <= bottom; y++) { result[y] = {}; } } _lookAreaMixedRegister(this.name, type, top, left, bottom, right, false, asArray, result); return result; }); Room.prototype.findPath = register.wrapFn(function (fromPos, toPos, opts) { if (fromPos.roomName != this.name) { return opts.serialize ? '' : []; } if (register._useNewPathFinder) { return _findPath2(this.name, fromPos, toPos, opts); } var fromX = fromPos.x, fromY = fromPos.y, path, cacheKeySuffix = ''; opts = _.clone(opts || {}); if (opts.ignoreCreeps) { cacheKeySuffix += '_ignoreCreeps'; } if (opts.ignoreDestructibleStructures) { cacheKeySuffix += '_ignoreDestructibleStructures'; } if (opts.avoid) { cacheKeySuffix += '_avoid' + privateStore[this.name].positionsSetCache.key(opts.avoid); } if (opts.ignore) { cacheKeySuffix += '_ignore' + privateStore[this.name].positionsSetCache.key(opts.ignore); } if (_.isNumber(toPos)) { if (!privateStore[this.name].pfEndNodes[toPos]) { return opts.serialize ? '' : []; } var grid = getPathfindingGrid(this.name, opts, toPos); path = privateStore[this.name].pfDijkstraFinder.findPath(fromX, fromY, -999, -999, grid); } else { if (toPos.roomName != this.name) { return opts.serialize ? '' : []; } var toX = toPos.x, toY = toPos.y, cacheKey = fromX + ',' + fromY + ',' + toX + ',' + toY + cacheKeySuffix; if (privateStore[this.name].pathCache[cacheKey]) { return opts.serialize ? utils.serializePath(privateStore[this.name].pathCache[cacheKey]) : _.cloneDeep(privateStore[this.name].pathCache[cacheKey]); } if (fromX == toX && fromY == toY) { return opts.serialize ? '' : []; } if (fromX < 0 || fromY < 0 || toX < 0 || toY < 0 || fromX >= 50 || fromY >= 50 || toX >= 50 || toY >= 50) { return opts.serialize ? '' : []; } if (abs(fromX - toX) < 2 && abs(fromY - toY) < 2) { var result = [{ x: toX, y: toY, dx: toX - fromX, dy: toY - fromY, direction: utils.getDirection(toX - fromX, toY - fromY) }]; return opts.serialize ? utils.serializePath(result) : result; } var grid = getPathfindingGrid(this.name, opts), finder = getPathfinder(this.name, opts); grid.setWalkableAt(toX, toY, true); path = finder.findPath(fromX, fromY, toX, toY, grid); } path.splice(0, 1); var curX = fromX, curY = fromY; var resultPath = _.map(path, function (step) { var result = { x: step[0], y: step[1], dx: step[0] - curX, dy: step[1] - curY, direction: utils.getDirection(step[0] - curX, step[1] - curY) }; curX = result.x; curY = result.y; return result; }); if (resultPath.length > 0) { var lastStep = resultPath[resultPath.length - 1], cacheKey = fromX + ',' + fromY + ',' + lastStep.x + ',' + lastStep.y + cacheKeySuffix; privateStore[this.name].pathCache[cacheKey] = _.cloneDeep(resultPath); } if (opts.serialize) { return utils.serializePath(resultPath); } return resultPath; }); Room.prototype.getPositionAt = register.wrapFn(function (x, y) { if (x < 0 || x > 49 || y < 0 || y > 49) { return null; } return new globals.RoomPosition(x, y, this.name); }); Room.prototype.createFlag = register.wrapFn(function (firstArg, secondArg, name, color, secondaryColor) { var _utils$fetchXYArgumen5 = utils.fetchXYArguments(firstArg, secondArg, globals), _utils$fetchXYArgumen6 = _slicedToArray(_utils$fetchXYArgumen5, 2), x = _utils$fetchXYArgumen6[0], y = _utils$fetchXYArgumen6[1]; if (_.isUndefined(x) || _.isUndefined(y) || x < 0 || x > 49 || y < 0 || y > 49) { return C.ERR_INVALID_ARGS; } if (_.size(globals.Game.flags) >= C.FLAGS_LIMIT) { return C.ERR_FULL; } if (_.isObject(firstArg)) { secondaryColor = color; color = name; name = secondArg; } if (!color) { color = C.COLOR_WHITE; } if (!secondaryColor) { secondaryColor = color; } if (!_.contains(C.COLORS_ALL, color)) { return C.ERR_INVALID_ARGS; } if (!_.contains(C.COLORS_ALL, secondaryColor)) { return C.ERR_INVALID_ARGS; } if (!name) { var cnt = 1; do { name = 'Flag' + cnt; cnt++; } while (_.any(register.flags, { name: name }) || createdFlagNames.indexOf(name) != -1); } if (_.any(register.flags, { name: name }) || createdFlagNames.indexOf(name) != -1) { return C.ERR_NAME_EXISTS; } if (name.length > 60) { return C.ERR_INVALID_ARGS; } createdFlagNames.push(name); globals.Game.flags[name] = new globals.Flag(name, color, secondaryColor, this.name, x, y); intents.pushByName('room', 'createFlag', { roomName: this.name, x: x, y: y, name: name, color: color, secondaryColor: secondaryColor }); return name; }); Room.prototype.createConstructionSite = register.wrapFn(function (firstArg, secondArg, structureType) { var _utils$fetchXYArgumen7 = utils.fetchXYArguments(firstArg, secondArg, globals), _utils$fetchXYArgumen8 = _slicedToArray(_utils$fetchXYArgumen7, 2), x = _utils$fetchXYArgumen8[0], y = _utils$fetchXYArgumen8[1]; if (_.isUndefined(x) || _.isUndefined(y) || x < 0 || x > 49 || y < 0 || y > 49) { return C.ERR_INVALID_ARGS; } if (_.isString(secondArg) && _.isUndefined(structureType)) { structureType = secondArg; } if (!C.CONSTRUCTION_COST[structureType]) { return C.ERR_INVALID_ARGS; } if (this.controller && this.controller.level > 0 && !this.controller.my) { return C.ERR_RCL_NOT_ENOUGH; } if (!utils.checkControllerAvailability(structureType, register.objectsByRoom[this.name], this.controller)) { return C.ERR_RCL_NOT_ENOUGH; } if (!utils.checkConstructionSite(register.objectsByRoom[this.name], structureType, x, y) || !utils.checkConstructionSite(runtimeData.staticTerrainData[this.name], structureType, x, y)) { return C.ERR_INVALID_TARGET; } if (_(runtimeData.userObjects).filter({ type: 'constructionSite' }).size() + createdConstructionSites >= C.MAX_CONSTRUCTION_SITES) { return C.ERR_FULL; } var intent = { roomName: this.name, x: x, y: y, structureType: structureType }; if (structureType == 'spawn') { var cnt = 1, name; do { name = "Spawn" + cnt; cnt++; } while (_.any(register.spawns, { name: name }) || _.any(register.constructionSites, { structureType: 'spawn', name: name }) || createdSpawnNames.indexOf(name) != -1); createdSpawnNames.push(name); intent.name = name; } createdConstructionSites++; intents.pushByName('room', 'createConstructionSite', intent); return C.OK; }); Room.prototype.getEndNodes = register.wrapFn(function (type, opts) { var key; opts = opts || {}; if (_.isUndefined(type)) { throw new Error('Find type cannot be undefined'); } if (!opts.filter && _.isNumber(type)) { key = type; } else { if (_.isNumber(type)) { type = this.find(type, opts); } key = privateStore[this.name].positionsSetCache.key(type); privateStore[this.name].pfEndNodes[key] = privateStore[this.name].positionsSetCache.cache[key]; } if (!privateStore[this.name].pfEndNodes[key]) { privateStore[this.name].pfEndNodes[key] = _.clone(type); if (_.isNumber(type)) { privateStore[this.name].pfEndNodes[key] = this.find(type, opts); } } return { key: key, objects: privateStore[this.name].pfEndNodes[key] }; }); Room.prototype.findExitTo = register.wrapFn(function (room) { return register.map.findExit(this.name, room); }); globals.Room = Room; /** * RoomVisual * @param id * @returns {object} * @constructor */ var RoomVisual = register.wrapFn(function (roomName) { this.roomName = roomName; }); RoomVisual.prototype.circle = register.wrapFn(function (x, y, style) { if ((typeof x === 'undefined' ? 'undefined' : _typeof(x)) == 'object') { style = y; y = x.y; x = x.x; } globals.console.addVisual(this.roomName, { t: 'c', x: x, y: y, s: style }); return this; }); RoomVisual.prototype.line = register.wrapFn(function (x1, y1, x2, y2, style) { if ((typeof x1 === 'undefined' ? 'undefined' : _typeof(x1)) == 'object' && (typeof y1 === 'undefined' ? 'undefined' : _typeof(y1)) == 'object') { style = x2; x2 = y1.x; y2 = y1.y; y1 = x1.y; x1 = x1.x; } globals.console.addVisual(this.roomName, { t: 'l', x1: x1, y1: y1, x2: x2, y2: y2, s: style }); return this; }); RoomVisual.prototype.rect = register.wrapFn(function (x, y, w, h, style) { if ((typeof x === 'undefined' ? 'undefined' : _typeof(x)) == 'object') { style = h; h = w; w = y; y = x.y; x = x.x; } globals.console.addVisual(this.roomName, { t: 'r', x: x, y: y, w: w, h: h, s: style }); return this; }); RoomVisual.prototype.poly = register.wrapFn(function (points, style) { points = points.map(function (i) { return i.x !== undefined ? [i.x, i.y] : i; }); globals.console.addVisual(this.roomName, { t: 'p', points: points, s: style }); return this; }); RoomVisual.prototype.text = register.wrapFn(function (text, x, y, style) { if ((typeof x === 'undefined' ? 'undefined' : _typeof(x)) == 'object') { style = y; y = x.y; x = x.x; } globals.console.addVisual(this.roomName, { t: 't', text: text, x: x, y: y, s: style }); return this; }); RoomVisual.prototype.getSize = register.wrapFn(function () { return globals.console.getVisualSize(this.roomName); }); RoomVisual.prototype.clear = register.wrapFn(function () { globals.console.clearVisual(this.roomName); return this; }); globals.RoomVisual = RoomVisual; }; exports.makePos = function (_register) { register = _register; if (globals.RoomPosition) { return; } /** * RoomPosition * @param x * @param y * @param roomName * @constructor */ var RoomPosition = register.wrapFn(function (x, y, roomName) { x = +x; y = +y; if (_.isNaN(x) || _.isNaN(y) || !_.isString(roomName)) { throw new Error('invalid arguments in RoomPosition constructor'); } this.x = x; this.y = y; this.roomName = roomName; }); RoomPosition.prototype.toString = register.wrapFn(function () { return '[room ' + this.roomName + ' pos ' + this.x + ',' + this.y + ']'; }); RoomPosition.prototype.inRangeTo = register.wrapFn(function (firstArg, secondArg, thirdArg) { var x = firstArg, y = secondArg, range = thirdArg, roomName = this.roomName; if (_.isUndefined(thirdArg)) { var pos = firstArg; if (pos.pos) { pos = pos.pos; } x = pos.x; y = pos.y; roomName = pos.roomName; range = secondArg; } return abs(x - this.x) <= range && abs(y - this.y) <= range && roomName == this.roomName; }); RoomPosition.prototype.isNearTo = register.wrapFn(function (firstArg, secondArg) { var _utils$fetchXYArgumen9 = utils.fetchXYArguments(firstArg, secondArg, globals), _utils$fetchXYArgumen10 = _slicedToArray(_utils$fetchXYArgumen9, 3), x = _utils$fetchXYArgumen10[0], y = _utils$fetchXYArgumen10[1], roomName = _utils$fetchXYArgumen10[2]; return abs(x - this.x) <= 1 && abs(y - this.y) <= 1 && (!roomName || roomName == this.roomName); }); RoomPosition.prototype.getDirectionTo = register.wrapFn(function (firstArg, secondArg) { var _utils$fetchXYArgumen11 = utils.fetchXYArguments(firstArg, secondArg, globals), _utils$fetchXYArgumen12 = _slicedToArray(_utils$fetchXYArgumen11, 3), x = _utils$fetchXYArgumen12[0], y = _utils$fetchXYArgumen12[1], roomName = _utils$fetchXYArgumen12[2]; if (!roomName || roomName == this.roomName) { return utils.getDirection(x - this.x, y - this.y); } var _utils$roomNameToXY = utils.roomNameToXY(this.roomName), _utils$roomNameToXY2 = _slicedToArray(_utils$roomNameToXY, 2), thisRoomX = _utils$roomNameToXY2[0], thisRoomY = _utils$roomNameToXY2[1]; var _utils$roomNameToXY3 = utils.roomNameToXY(roomName), _utils$roomNameToXY4 = _slicedToArray(_utils$roomNameToXY3, 2), thatRoomX = _utils$roomNameToXY4[0], thatRoomY = _utils$roomNameToXY4[1]; return utils.getDirection(thatRoomX * 50 + x - thisRoomX * 50 - this.x, thatRoomY * 50 + y - thisRoomY * 50 - this.y); }); RoomPosition.prototype.findPathTo = register.wrapFn(function (firstArg, secondArg, opts) { var _utils$fetchXYArgumen13 = utils.fetchXYArguments(firstArg, secondArg, globals), _utils$fetchXYArgumen14 = _slicedToArray(_utils$fetchXYArgumen13, 3), x = _utils$fetchXYArgumen14[0], y = _utils$fetchXYArgumen14[1], roomName = _utils$fetchXYArgumen14[2], room = register.rooms[this.roomName]; if (_.isObject(secondArg)) { opts = _.clone(secondArg); } opts = opts || {}; roomName = roomName || this.roomName; if (!room) { throw new Error('Could not access room ' + this.roomName); } if (roomName == this.roomName || register._useNewPathFinder) { return room.findPath(this, new globals.RoomPosition(x, y, roomName), opts); } else { var exitDir = room.findExitTo(roomName); if (exitDir < 0) { return []; } var exit = this.findClosestByPath(exitDir, opts); if (!exit) { return []; } return room.findPath(this, exit, opts); } }); RoomPosition.prototype.findClosestByPath = register.wrapFn(function (type, opts) { var _this2 = this; opts = _.clone(opts || {}); var room = register.rooms[this.roomName]; if (!room) { throw new Error('Could not access room ' + this.roomName); } if (_.isUndefined(type)) { return null; } if (register._useNewPathFinder) { return _findClosestByPath2(this, type, opts); } opts.serialize = false; var result = null, isNear, endNodes = room.getEndNodes(type, opts); if (!opts.algorithm) { var minH, sumH = 0; endNodes.objects.forEach(function (i) { var x = i.x, y = i.y, roomName = i.roomName; if (i.pos) { x = i.pos.x; y = i.pos.y; roomName = i.pos.roomName; } var h = max(abs(_this2.x - x), abs(_this2.y - y)); if (_.isUndefined(minH) || minH > h) { minH = h; } sumH += h; }); opts.algorithm = sumH > minH * 10 ? 'dijkstra' : 'astar'; } if (opts.algorithm == 'dijkstra') { isNear = 1; endNodes.objects.forEach(function (i) { var distance = _this2.isEqualTo(i) ? -1 : _this2.isNearTo(i) ? 0 : 1; if (distance < isNear) { result = i; isNear = distance; } }); if (isNear == 1) { var path = room.findPath(this, endNodes.key, opts); if (path.length > 0) { var lastStep = path[path.length - 1], lastStepPos = room.getPositionAt(lastStep.x, lastStep.y); result = _.find(endNodes.objects, function (i) { return lastStepPos.isEqualTo(i); }); } } } if (opts.algorithm == 'astar') { endNodes.objects.forEach(function (i) { var path, distance = _this2.isEqualTo(i) ? -1 : _this2.isNearTo(i) ? 0 : (path = _this2.findPathTo(i, opts)) && path.length > 0 && room.getPositionAt(path[path.length - 1].x, path[path.length - 1].y).isNearTo(i) ? path.length : undefined; if ((_.isUndefined(isNear) || distance <= isNear) && !_.isUndefined(distance)) { isNear = distance; result = i; } }); } return result; }); RoomPosition.prototype.findInRange = register.wrapFn(function (type, range, opts) { var _this3 = this; var room = register.rooms[this.roomName]; if (!room) { throw new Error('Could not access room ' + this.roomName); } opts = _.clone(opts || {}); var objects = [], result = []; if (_.isNumber(type)) { objects = room.find(type, opts); } if (_.isArray(type)) { objects = opts.filter ? _.filter(type, opts.filter) : type; } objects.forEach(function (i) { if (_this3.inRangeTo(i, range)) { result.push(i); } }); return result; }); RoomPosition.prototype.findClosestByRange = register.wrapFn(function (type, opts) { var _this4 = this; var room = register.rooms[this.roomName]; if (!room) { throw new Error('Could not access room ' + this.roomName); } opts = _.clone(opts || {}); var objects = [], result = []; if (_.isNumber(type)) { objects = room.find(type, opts); } if (_.isArray(type)) { objects = opts.filter ? _.filter(type, opts.filter) : type; } var closest = null, minRange = Infinity; objects.forEach(function (i) { var range = _this4.getRangeTo(i); if (range < minRange) { minRange = range; closest = i; } }); return closest; }); RoomPosition.prototype.isEqualTo = register.wrapFn(function (firstArg, secondArg) { var _utils$fetchXYArgumen15 = utils.fetchXYArguments(firstArg, secondArg, globals), _utils$fetchXYArgumen16 = _slicedToArray(_utils$fetchXYArgumen15, 3), x = _utils$fetchXYArgumen16[0], y = _utils$fetchXYArgumen16[1], roomName = _utils$fetchXYArgumen16[2]; return x == this.x && y == this.y && (!roomName || roomName == this.roomName); }); RoomPosition.prototype.getRangeTo = register.wrapFn(function (firstArg, secondArg) {