@screeps/engine
Version:
This is a module for Screeps standalone server. See [main repository](https://github.com/screeps/screeps) for more info.
348 lines (272 loc) • 11.4 kB
JavaScript
'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"); } }; }();
const _ = require('lodash'),
utils = require('../../utils'),
driver = utils.getDriver(),
C = driver.constants;
let terrains = {};
const RoomPosition = 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.isEqualTo = function (p) {
return p.x == this.x && p.y == this.y && p.roomName == this.roomName;
};
RoomPosition.prototype.getRangeTo = function (p) {
return p.roomName == this.roomName ? utils.dist(p, this) : Infinity;
};
RoomPosition.prototype.getDirectionTo = function (p) {
if (p.roomName == this.roomName) {
return utils.getDirection(p.x - this.x, p.y - this.y);
}
var _utils$roomNameToXY = utils.roomNameToXY(this.roomName),
_utils$roomNameToXY2 = _slicedToArray(_utils$roomNameToXY, 2);
const thisRoomX = _utils$roomNameToXY2[0],
thisRoomY = _utils$roomNameToXY2[1];
var _utils$roomNameToXY3 = utils.roomNameToXY(p.roomName),
_utils$roomNameToXY4 = _slicedToArray(_utils$roomNameToXY3, 2);
const thatRoomX = _utils$roomNameToXY4[0],
thatRoomY = _utils$roomNameToXY4[1];
return utils.getDirection(thatRoomX * 50 + p.x - thisRoomX * 50 - this.x, thatRoomY * 50 + p.y - thisRoomY * 50 - this.y);
};
RoomPosition.prototype.lookFor = function (type) {
if (type != C.LOOK_TERRAIN) {
return null;
}
if (!terrains[this.roomName]) {
// disallow movement via unknown terrain
return 'wall';
}
const terrainStrings = ['plain', 'wall', 'swamp', 'wall'];
return [terrainStrings[terrains[this.roomName][50 * this.y + this.x]]];
};
const packLocal = function (x, y) {
let uint32 = 0;
uint32 <<= 6;uint32 |= x;
uint32 <<= 6;uint32 |= y;
return String.fromCharCode(32 + uint32);
};
RoomPosition.prototype.sPackLocal = function () {
return packLocal(this.x, this.y);
};
RoomPosition.sUnpackLocal = function (packed, roomName) {
let uint32 = packed.codePointAt(0);
if (uint32 < 32) {
throw new Error(`Invalid uint value ${uint32}`);
}
uint32 -= 32;
const y = uint32 & 0x3f;uint32 >>>= 6;
const x = uint32 & 0x3f;uint32 >>>= 6;
return new RoomPosition(x, y, roomName);
};
const CostMatrix = function () {
this._bits = new Uint8Array(2500);
};
CostMatrix.prototype.set = function (xx, yy, val) {
xx = xx | 0;
yy = yy | 0;
this._bits[xx * 50 + yy] = Math.min(Math.max(0, val), 255);
};
CostMatrix.prototype.get = function (xx, yy) {
xx = xx | 0;
yy = yy | 0;
return this._bits[xx * 50 + yy];
};
CostMatrix.prototype.clone = function () {
const newMatrix = new CostMatrix();
newMatrix._bits = new Uint8Array(this._bits);
return newMatrix;
};
function packPath(roomPositions) {
return _.reduce(roomPositions, (path, position) => `${path}${position.sPackLocal()}`, '');
}
const defaultCostMatrix = function defaultCostMatrix(roomId, opts, creep, roomObjects) {
if (creep.room != roomId) {
// disallow movement via unknown terrain
return false;
}
const costs = new CostMatrix();
let obstacleTypes = _.clone(C.OBSTACLE_OBJECT_TYPES);
obstacleTypes.push(C.STRUCTURE_PORTAL);
if (opts.ignoreDestructibleStructures) {
obstacleTypes = _.without(obstacleTypes, 'constructedWall', 'rampart', 'spawn', 'extension', 'link', 'storage', 'observer', 'tower', 'powerBank', 'powerSpawn', 'lab', 'terminal');
}
if (opts.ignoreCreeps) {
obstacleTypes = _.without(obstacleTypes, 'creep');
}
_.forEach(roomObjects, function (object) {
if (_.contains(obstacleTypes, object.type) || !opts.ignoreDestructibleStructures && object.type == 'rampart' && !object.isPublic && object.user != creep.user || !opts.ignoreDestructibleStructures && object.type == 'constructionSite' && object.user == creep.user && _.contains(C.OBSTACLE_OBJECT_TYPES, object.structureType)) {
costs.set(object.x, object.y, Infinity);
}
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) < Infinity) {
costs.set(object.x, object.y, 1);
}
});
return costs;
};
const findPath = function findPath(source, target, opts, scope) {
const roomTerrain = scope.roomTerrain,
roomObjects = scope.roomObjects;
terrains = { [source.room]: roomTerrain };
const roomCallback = function (roomName) {
let costMatrix = defaultCostMatrix(roomName, opts, source, roomObjects);
if (typeof opts.costCallback == 'function') {
costMatrix = costMatrix.clone();
const resultMatrix = opts.costCallback(roomName, costMatrix);
if (resultMatrix instanceof CostMatrix) {
costMatrix = resultMatrix;
}
}
return costMatrix;
};
const searchOpts = _.clone(opts);
searchOpts.maxRooms = 1;
searchOpts.roomCallback = roomCallback;
if (!searchOpts.ignoreRoads) {
searchOpts.plainCost = 2;
searchOpts.swampCost = 10;
}
const fromPos = new RoomPosition(source.x, source.y, source.room);
const ret = driver.pathFinder.search(fromPos, target, searchOpts);
if (target instanceof RoomPosition && !opts.range && (ret.path.length && ret.path[ret.path.length - 1].getRangeTo(target) === 1 || !ret.path.length && fromPos.getRangeTo(target) === 1)) {
ret.path.push(target);
}
return ret;
};
const flee = function flee(creep, hostiles, range, opts, scope) {
const danger = hostiles.map(c => {
return {
pos: new RoomPosition(c.x, c.y, c.room),
range: range
};
});
const result = findPath(creep, danger, { flee: true }, scope);
if (!_.some(result.path)) {
return 0;
}
const fleePosition = result.path[0];
return utils.getDirection(fleePosition.x - creep.x, fleePosition.y - creep.y);
};
const moveTo = function moveTo(creep, target, opts, scope) {
const bulk = scope.bulk,
gameTime = scope.gameTime;
opts = opts || {};
if (_.isUndefined(opts.reusePath)) {
opts.reusePath = 5;
}
if (_.isUndefined(opts.range)) {
opts.range = 0;
}
if (utils.dist(creep, target) <= opts.range) {
return 0;
}
const targetPosition = new RoomPosition(target.x, target.y, target.room);
if (!creep['memory_move'] || !creep['memory_move']['dest'] || !creep['memory_move']['time'] || creep['memory_move']['dest'] != targetPosition.sPackLocal() || gameTime > creep['memory_move']['time'] + opts.reusePath) {
const result = findPath(creep, { range: opts.range, pos: new RoomPosition(target.x, target.y, target.room) }, opts, scope);
if (!result.path) {
return 0;
}
const memory_move = {
dest: targetPosition.sPackLocal(),
path: packPath(result.path),
time: gameTime
};
bulk.update(creep, { memory_move });
}
const direction = nextDirectionByPath(creep, creep['memory_move']['path']);
if (direction) {
bulk.update(creep, { memory_move: { lastMove: gameTime } });
}
return direction;
};
const walkTo = function (creep, target, opts, context) {
const scope = context.scope,
intents = context.intents;
const gameTime = scope.gameTime,
bulk = scope.bulk,
roomObjects = scope.roomObjects;
const direction = moveTo(creep, target, opts, scope);
if (!direction) {
return direction;
}
const offsets = utils.getOffsetsByDirection(direction);
const creepAhead = _.find(roomObjects, { type: 'creep', user: creep.user, x: creep.x + offsets[0], y: creep.y + offsets[1] });
if (creepAhead && (!creepAhead['memory_move'] || creepAhead['memory_move']['lastMove'] && creepAhead['memory_move']['lastMove'] + 1 < gameTime)) {
intents.set(creepAhead._id, 'move', { direction: utils.getDirection(creep.x - creepAhead.x, creep.y - creepAhead.y) });
bulk.update(creepAhead, { memory_move: { dest: null, time: null, path: null, lastMove: gameTime } });
}
intents.set(creep._id, 'move', { direction });
};
const findClosestByPath = function findClosestByPath(fromPos, objects, opts, scope) {
if (!_.some(objects)) {
return null;
}
const roomTerrain = scope.roomTerrain;
terrains = { [fromPos.room]: roomTerrain };
opts = opts || {};
if (_.isUndefined(opts.range)) {
opts.range = 0;
}
const objectHere = _.find(objects, obj => utils.dist(fromPos, obj) == 0);
if (objectHere) {
return objectHere;
}
const goals = _.map(objects, i => {
return { range: 1, pos: new RoomPosition(i.x, i.y, i.room) };
});
const ret = findPath(fromPos, goals, opts, scope);
if (!ret.path) {
return null;
}
let result = null;
let lastPos = fromPos;
if (ret.path.length) {
lastPos = ret.path[ret.path.length - 1];
}
objects.forEach(obj => {
if (utils.dist(lastPos, obj) <= 1) {
result = obj;
}
});
return result;
};
const nextDirectionByPath = function (creep, path) {
const currentPositionIndex = path.indexOf(packLocal(creep.x, creep.y));
if (currentPositionIndex == path.length - 1) {
return 0;
}
let nextPosition = undefined;
if (currentPositionIndex < 0) {
const firstPosition = RoomPosition.sUnpackLocal(path[0], creep.room);
if (utils.dist(creep, firstPosition) <= 1) {
nextPosition = firstPosition;
}
} else {
nextPosition = RoomPosition.sUnpackLocal(path[1 + currentPositionIndex], creep.room);
}
if (!nextPosition) {
return 0;
}
return utils.getDirection(nextPosition.x - creep.x, nextPosition.y - creep.y);
};
const hasActiveBodyparts = function hasActiveBodyparts(creep, part) {
return !!creep.body && _.some(creep.body, p => p.hits > 0 && p.type == part);
};
module.exports.findPath = findPath;
module.exports.findClosestByPath = findClosestByPath;
module.exports.moveTo = moveTo;
module.exports.walkTo = walkTo;
module.exports.flee = flee;
module.exports.RoomPosition = RoomPosition;
module.exports.CostMatrix = CostMatrix;
module.exports.hasActiveBodyparts = hasActiveBodyparts;
//# sourceMappingURL=../../sourcemaps/processor/common/fake-runtime.js.map