diff --git a/types/screeps/index.d.ts b/types/screeps/index.d.ts index 42b7d8a696..27ca10960d 100644 --- a/types/screeps/index.d.ts +++ b/types/screeps/index.d.ts @@ -1744,6 +1744,11 @@ type STRUCTURE_CONTAINER = "container"; type STRUCTURE_NUKER = "nuker"; type STRUCTURE_PORTAL = "portal"; +// Terrain mask constants +type TERRAIN_MASK_WALL = 1; +type TERRAIN_MASK_SWAMP = 2; +type TERRAIN_MASK_LAVA = 4; + // Resource Constants type ResourceConstant = @@ -2809,7 +2814,15 @@ interface RoomTerrain { * @param y Y position in the room. * @return number Number of terrain mask like: TERRAIN_MASK_SWAMP | TERRAIN_MASK_WALL */ - get(x: number, y: number): number; + get(x: number, y: number): 0 | TERRAIN_MASK_WALL | TERRAIN_MASK_SWAMP; +} + +interface RoomTerrainConstructor extends _Constructor { + /** + * Get room terrain for the specified room. This method works for any room in the world even if you have no access to it. + * @param roomName String name of the room. + */ + new (roomName: string): RoomTerrain; } declare class RoomVisual { /** @@ -3182,6 +3195,11 @@ interface Room { * @returns A RoomPosition object or null if it cannot be obtained. */ getPositionAt(x: number, y: number): RoomPosition | null; + /** + * Get a Room.Terrain object which provides fast access to static terrain data. + * This method works for any room in the world even if you have no access to it. + */ + getTerrain(): RoomTerrain; /** * Get the list of objects at the specified room position. * @param x The X position. @@ -3282,6 +3300,9 @@ interface Room { interface RoomConstructor extends _Constructor { new (id: string): Room; + + Terrain: RoomTerrainConstructor; + /** * Serialize a path array into a short string representation, which is suitable to store in memory. * @param path A path array retrieved from `Room.findPath`. diff --git a/types/screeps/screeps-tests.ts b/types/screeps/screeps-tests.ts index 4b7a3722a4..d7befaf3bd 100644 --- a/types/screeps/screeps-tests.ts +++ b/types/screeps/screeps-tests.ts @@ -121,7 +121,7 @@ function keys(o: T): Array { if (Game.spawns["Spawn1"].energy === 0) { Game.notify( "Spawn1 is out of energy", - 180 // group these notifications for 3 hours + 180, // group these notifications for 3 hours ); } } @@ -130,13 +130,13 @@ function keys(o: T): Array { { const exits = Game.map.describeExits("W8N3"); - keys(exits) - .map((exitKey) => { - const nextRoom = exits[exitKey]; - const exitDir = +exitKey as ExitConstant; - const exitPos = creep.pos.findClosestByRange(exitDir); - return {nextRoom, exitPos}; - }); + // tslint:disable-next-line:newline-per-chained-call + keys(exits).map(exitKey => { + const nextRoom = exits[exitKey]; + const exitDir = +exitKey as ExitConstant; + const exitPos = creep.pos.findClosestByRange(exitDir); + return { nextRoom, exitPos }; + }); } // Game.map.findExit() @@ -180,7 +180,7 @@ function keys(o: T): Array { return Infinity; } return 1; - } + }, }); } @@ -195,11 +195,8 @@ function keys(o: T): Array { routeCallback(roomName) { const parsed = /^[WE]([0-9]+)[NS]([0-9]+)$/.exec(roomName); if (parsed !== null) { - const isHighway = (parseInt(parsed[1], 10) % 10 === 0) || - (parseInt(parsed[2], 10) % 10 === 0); - const isMyRoom = Game.rooms[roomName] && - Game.rooms[roomName].controller && - Game.rooms[roomName].controller!.my; + const isHighway = parseInt(parsed[1], 10) % 10 === 0 || parseInt(parsed[2], 10) % 10 === 0; + const isMyRoom = Game.rooms[roomName] && Game.rooms[roomName].controller && Game.rooms[roomName].controller!.my; if (isHighway || isMyRoom) { return 1; } else { @@ -208,24 +205,24 @@ function keys(o: T): Array { } else { return 2.5; } - } + }, }); if (route !== ERR_NO_PATH) { - route.forEach((info) => { + route.forEach(info => { allowedRooms[info.room] = true; }); } // Invoke PathFinder, allowing access only to rooms from `findRoute` const ret = PathFinder.search(from, [to], { - roomCallback: (roomName) => { + roomCallback: roomName => { if (allowedRooms[roomName] === undefined) { return false; } else { return true; } - } + }, }); } @@ -299,9 +296,12 @@ function keys(o: T): Array { Game.market.getAllOrders({ type: ORDER_SELL, resourceType: RESOURCE_GHODIUM }); const targetRoom = "W1N1"; - Game.market.getAllOrders((currentOrder) => currentOrder.resourceType === RESOURCE_GHODIUM && - currentOrder.type === ORDER_SELL && - Game.market.calcTransactionCost(1000, targetRoom, currentOrder.roomName!) < 500); + Game.market.getAllOrders( + currentOrder => + currentOrder.resourceType === RESOURCE_GHODIUM && + currentOrder.type === ORDER_SELL && + Game.market.calcTransactionCost(1000, targetRoom, currentOrder.roomName!) < 500, + ); // Game.market.getOrderById(id) const order = Game.market.getOrderById("55c34a6b5be41a0a6e80c123"); @@ -316,54 +316,52 @@ function keys(o: T): Array { { const pfCreep = Game.creeps.John; - const goals = pfCreep.room.find(FIND_SOURCES) - .map((source) => { - // We can't actually walk on sources-- set `range` to 1 - // so we path next to it. - return { pos: source.pos, range: 1 }; - }); + // tslint:disable-next-line:newline-per-chained-call + const goals = pfCreep.room.find(FIND_SOURCES).map(source => { + // We can't actually walk on sources-- set `range` to 1 + // so we path next to it. + return { pos: source.pos, range: 1 }; + }); - const ret = PathFinder.search( - pfCreep.pos, goals, - { - // We need to set the defaults costs higher so that we - // can set the road cost lower in `roomCallback` - plainCost: 2, - swampCost: 10, + const ret = PathFinder.search(pfCreep.pos, goals, { + // We need to set the defaults costs higher so that we + // can set the road cost lower in `roomCallback` + plainCost: 2, + swampCost: 10, - roomCallback(roomName) { - const curRoom = Game.rooms[roomName]; - // In this example `room` will always exist, but since - // PathFinder supports searches which span multiple rooms - // you should be careful! - if (!curRoom) { - return false; + roomCallback(roomName) { + const curRoom = Game.rooms[roomName]; + // In this example `room` will always exist, but since + // PathFinder supports searches which span multiple rooms + // you should be careful! + if (!curRoom) { + return false; + } + const costs = new PathFinder.CostMatrix(); + + // tslint:disable-next-line:newline-per-chained-call + curRoom.find(FIND_STRUCTURES).forEach(struct => { + if (struct.structureType === STRUCTURE_ROAD) { + // Favor roads over plain tiles + costs.set(struct.pos.x, struct.pos.y, 1); + } else if ( + struct.structureType !== STRUCTURE_CONTAINER && + (struct.structureType !== STRUCTURE_RAMPART || !(struct as OwnedStructure).my) + ) { + // Can't walk through non-walkable buildings + costs.set(struct.pos.x, struct.pos.y, 0xff); } - const costs = new PathFinder.CostMatrix(); + }); - curRoom.find(FIND_STRUCTURES) - .forEach((struct) => { - if (struct.structureType === STRUCTURE_ROAD) { - // Favor roads over plain tiles - costs.set(struct.pos.x, struct.pos.y, 1); - } else if (struct.structureType !== STRUCTURE_CONTAINER && - (struct.structureType !== STRUCTURE_RAMPART || - !(struct as OwnedStructure).my)) { - // Can't walk through non-walkable buildings - costs.set(struct.pos.x, struct.pos.y, 0xff); - } - }); + // Avoid creeps in the room + // tslint:disable-next-line:newline-per-chained-call + curRoom.find(FIND_CREEPS).forEach(thisCreep => { + costs.set(thisCreep.pos.x, thisCreep.pos.y, 0xff); + }); - // Avoid creeps in the room - curRoom.find(FIND_CREEPS) - .forEach((thisCreep) => { - costs.set(thisCreep.pos.x, thisCreep.pos.y, 0xff); - }); - - return costs; - }, - } - ); + return costs; + }, + }); const pos = ret.path[0]; pfCreep.move(pfCreep.pos.getDirectionTo(pos)); @@ -390,8 +388,8 @@ function keys(o: T): Array { RawMemory.interShardSegment = JSON.stringify({ creeps: { - Bob: {role: "claimer"} - } + Bob: { role: "claimer" }, + }, }); // on another shard @@ -454,9 +452,9 @@ function keys(o: T): Array { creepsHere[0].getActiveBodyparts(ATTACK); const towers = room.find(FIND_MY_STRUCTURES, { - filter: (structure) => { - return (structure.structureType === STRUCTURE_TOWER); - } + filter: structure => { + return structure.structureType === STRUCTURE_TOWER; + }, }); towers[0].attack(creeps[0]); } @@ -471,18 +469,18 @@ function keys(o: T): Array { } const tower = creep.pos.findClosestByPath(FIND_HOSTILE_STRUCTURES, { - filter: (structure) => { + filter: structure => { return structure.structureType === STRUCTURE_TOWER; - } + }, }); if (tower !== null) { tower.attack(creep); } const rampart = creep.pos.findClosestByRange(FIND_HOSTILE_STRUCTURES, { - filter: (structure) => { + filter: structure => { return structure.structureType === STRUCTURE_RAMPART; - } + }, }); if (rampart !== null) { rampart.isPublic; @@ -493,9 +491,9 @@ function keys(o: T): Array { hostileCreeps[0].saying; const labs = creep.pos.findInRange(FIND_MY_STRUCTURES, 4, { - filter: (structure) => { + filter: structure => { return structure.structureType === STRUCTURE_LAB; - } + }, }); labs[0].boostCreep(creep); @@ -511,7 +509,7 @@ function keys(o: T): Array { const pos = new RoomPosition(+x, +y, room.name); const objects = row[x]; if (objects.length > 0) { - objects.map((o) => o.type); + objects.map(o => o.type); } } } @@ -556,34 +554,31 @@ function keys(o: T): Array { switch (unowned.structureType) { case STRUCTURE_TOWER: unowned.heal(Game.creeps.myCreep); - break; + break; case STRUCTURE_CONTAINER: case STRUCTURE_STORAGE: case STRUCTURE_TERMINAL: const energyPercent = unowned.store.energy / unowned.storeCapacity; - break; + break; case STRUCTURE_WALL: case STRUCTURE_RAMPART: const wallHp = unowned.hits / unowned.hitsMax; - break; + break; } // test discriminated union using filter functions on find const from = Game.rooms.myRoom.find(FIND_STRUCTURES, { - filter: (s) => ((s.structureType === STRUCTURE_CONTAINER - || s.structureType === STRUCTURE_STORAGE) - && s.store.energy > 0) + filter: s => (s.structureType === STRUCTURE_CONTAINER || s.structureType === STRUCTURE_STORAGE) && s.store.energy > 0, })[0]; const to = from.pos.findClosestByPath(FIND_MY_STRUCTURES, { - filter: (s) => ((s.structureType === STRUCTURE_SPAWN - || s.structureType === STRUCTURE_EXTENSION) - && s.energy < s.energyCapacity) + filter: s => (s.structureType === STRUCTURE_SPAWN || s.structureType === STRUCTURE_EXTENSION) && s.energy < s.energyCapacity, }); - Game.rooms.myRoom.find(FIND_MY_STRUCTURES, { - filter: (s) => s.structureType === STRUCTURE_RAMPART - }) - .forEach((r) => r.notifyWhenAttacked(false)); + Game.rooms.myRoom + .find(FIND_MY_STRUCTURES, { + filter: s => s.structureType === STRUCTURE_RAMPART, + }) + .forEach(r => r.notifyWhenAttacked(false)); } { @@ -604,12 +599,12 @@ function keys(o: T): Array { tombstone.id; - const creep = Game.creeps['dave']; + const creep = Game.creeps["dave"]; creep.withdraw(tombstone, RESOURCE_ENERGY); } { - if (Game.cpu.hasOwnProperty('getHeapStatistics')) { + if (Game.cpu.hasOwnProperty("getHeapStatistics")) { const heap = Game.cpu.getHeapStatistics!(); heap.total_heap_size; } @@ -618,9 +613,9 @@ function keys(o: T): Array { // StructurePortal { - const portals = room.find(FIND_STRUCTURES, {filter: (s) => s.structureType === STRUCTURE_PORTAL}); + const portals = room.find(FIND_STRUCTURES, { filter: s => s.structureType === STRUCTURE_PORTAL }); portals.forEach((p: StructurePortal) => { - const state = p.ticksToDecay === undefined ? 'stable' : 'unstable'; + const state = p.ticksToDecay === undefined ? "stable" : "unstable"; if (p.destination instanceof RoomPosition) { Game.notify(`Found ${state} inter-room portal to ${p.destination}`); } else { @@ -649,8 +644,7 @@ function keys(o: T): Array { const lab1 = Game.getObjectById("lab1"); const lab2 = Game.getObjectById("lab2"); if (lab0 !== null && lab1 !== null && lab2 !== null) { - if (lab1.mineralAmount >= LAB_REACTION_AMOUNT && lab2.mineralAmount >= LAB_REACTION_AMOUNT && - lab0.mineralType === null) { + if (lab1.mineralAmount >= LAB_REACTION_AMOUNT && lab2.mineralAmount >= LAB_REACTION_AMOUNT && lab0.mineralType === null) { lab0.runReaction(lab1, lab2); } } @@ -662,3 +656,24 @@ function keys(o: T): Array { room.getEventLog(); room.getEventLog(true); } + +// Room.Terrain + +{ + const room = Game.rooms[""]; + + const myTerrain = room.getTerrain(); + + const ret = myTerrain.get(5, 5); + if (ret === 0) { + /*plain*/ + } + if (ret === TERRAIN_MASK_SWAMP) { + /*swamp*/ + } + if (ret === TERRAIN_MASK_WALL) { + /*wall*/ + } + + const enemyTerrain = new Room.Terrain("W2N5"); +}