@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
JavaScript
'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) {