Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 64 additions & 52 deletions dist/index.d.ts

Large diffs are not rendered by default.

99 changes: 53 additions & 46 deletions dist/screeps-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,22 @@

// Sample inputs

const creep: Creep = Game.creeps.sampleCreep;
const room: Room = Game.rooms.W10S10;
const flag: Flag = Game.flags.Flag1;
const powerCreep: PowerCreep = Game.powerCreeps.samplePowerCreep;
const spawn: StructureSpawn = Game.spawns.Spawn1;
const creepName = "sampleCreep" as Name<Creep>;
const creep: Creep = Game.creeps[creepName];
const roomName = "W11S11" as Name<Room>;
const room: Room = Game.rooms[roomName];
const flagName = "Flag1" as Name<Flag>;
const flag: Flag = Game.flags[flagName];
const powerCreepName = "samplePowerCreep" as Name<PowerCreep>;
const powerCreep: PowerCreep = Game.powerCreeps[powerCreepName];
const spawnName = "Spawn1" as Name<StructureSpawn>;
const spawn: StructureSpawn = Game.spawns[spawnName];
const body: BodyPartConstant[] = [WORK, WORK, CARRY, MOVE];
const shardName = "shard0" as Name<Shard>;

// Sample inputs for Game.map.findRoute testing
const anotherRoomName: Room = Game.rooms.W10S11;
const anotherRoomName = "E22S22" as Name<Room>;
const anotherRoom: Room = Game.rooms[anotherRoomName];

// Sample memory extensions
interface CreepMemory {
Expand Down Expand Up @@ -74,24 +81,24 @@ function resources(o: GenericStore): ResourceConstant[] {
// Game.creeps

{
for (const creepName of Object.keys(Game.creeps)) {
for (const creepName of Object.keys(Game.creeps) as Array<keyof typeof Game.creeps>) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is ugly and a breaking change 😢

Could be better with

export function iterKeys<K extends string, V>(d: Partial<Record<K, V>> | Record<K, V>) {
  return Object.keys(d) as unknown as readonly K[]
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am constantly re-surprised by typescript's Object.keys() not producing typed keys from a known-typed object.

Game.creeps[creepName].moveTo(flag);
}
}

// Game.flags

{
creep.moveTo(Game.flags.Flag1);
creep.moveTo(Game.flags[flagName]);
}

// Game.powerCreeps

{
PowerCreep.create("steve", POWER_CLASS.OPERATOR) === OK;

for (const i of Object.keys(Game.powerCreeps)) {
const powerCreep = Game.powerCreeps[i];
for (const powerCreepName of Object.keys(Game.powerCreeps) as Array<keyof typeof Game.powerCreeps>) {
const powerCreep = Game.powerCreeps[powerCreepName];

if (powerCreep.ticksToLive === undefined) {
// Not spawned in world; spawn creep
Expand All @@ -104,7 +111,7 @@ function resources(o: GenericStore): ResourceConstant[] {
powerCreep.powers[PWR_GENERATE_OPS].cooldown === 0 &&
(powerCreep.carry.ops || 0) < 10
) {
Game.powerCreeps[i].usePower(PWR_GENERATE_OPS);
Game.powerCreeps[powerCreepName].usePower(PWR_GENERATE_OPS);
} else {
// Boost resource
const targetSource = Game.getObjectById("targetSourceID" as Id<Source>)!;
Expand All @@ -127,7 +134,7 @@ function resources(o: GenericStore): ResourceConstant[] {
powerCreep.upgrade(PWR_GENERATE_OPS);
}

const myPowaCreeps = Game.rooms.sim.find(FIND_MY_POWER_CREEPS);
const myPowaCreeps = Game.rooms["sim" as Name<Room>].find(FIND_MY_POWER_CREEPS);

// Constant type checking
POWER_INFO[PWR_GENERATE_OPS].className === POWER_CLASS.OPERATOR;
Expand All @@ -137,7 +144,7 @@ function resources(o: GenericStore): ResourceConstant[] {
// Game.spawns

{
for (const i of Object.keys(Game.spawns)) {
for (const i of Object.keys(Game.spawns) as Array<keyof typeof Game.spawns>) {
Game.spawns[i].createCreep(body);

// Test StructureSpawn.Spawning
Expand Down Expand Up @@ -188,7 +195,7 @@ function resources(o: GenericStore): ResourceConstant[] {
// Game.cpu.setShardLimits()

{
Game.cpu.setShardLimits({ shard0: 20, shard1: 10 });
Game.cpu.setShardLimits({ [shardName]: 20, ["privateshard" as Name<Shard>]: 10 });
}

// Game.cpu.halt()
Expand Down Expand Up @@ -227,9 +234,9 @@ function resources(o: GenericStore): ResourceConstant[] {
}

{
if (Game.spawns["Spawn1"].energy === 0) {
if (Game.spawns[spawnName].energy === 0) {
Game.notify(
"Spawn1 is out of energy",
`${spawnName} is out of energy`,
180, // group these notifications for 3 hours
);
}
Expand All @@ -238,7 +245,7 @@ function resources(o: GenericStore): ResourceConstant[] {
// Game.map.describeExits()

{
const exits = Game.map.describeExits("W8N3");
const exits = Game.map.describeExits(roomName);
if (exits) {
keys(exits).map((exitKey) => {
const nextRoom = exits[exitKey];
Expand All @@ -252,8 +259,8 @@ function resources(o: GenericStore): ResourceConstant[] {
// Game.map.findExit()

{
if (creep.room.name !== anotherRoomName.name) {
const exitDir = Game.map.findExit(creep.room, anotherRoomName);
if (creep.room.name !== anotherRoom.name) {
const exitDir = Game.map.findExit(creep.room, anotherRoom);
if (exitDir !== ERR_NO_PATH && exitDir !== ERR_INVALID_ARGS) {
const exit = creep.pos.findClosestByRange(exitDir);
if (exit !== null) {
Expand All @@ -266,13 +273,13 @@ function resources(o: GenericStore): ResourceConstant[] {
}

{
creep.moveTo(new RoomPosition(25, 25, anotherRoomName.name));
creep.moveTo(new RoomPosition(25, 25, anotherRoom.name));
}

// Game.map.findRoute()

{
const route = Game.map.findRoute(creep.room, anotherRoomName);
const route = Game.map.findRoute(creep.room, anotherRoom);

if (route !== ERR_NO_PATH && route.length > 0) {
const exit = creep.pos.findClosestByRange(route[0].exit);
Expand All @@ -283,7 +290,7 @@ function resources(o: GenericStore): ResourceConstant[] {
}

{
const route = Game.map.findRoute(creep.room, anotherRoomName, {
const route = Game.map.findRoute(creep.room, anotherRoom, {
routeCallback(roomName, fromRoomName) {
if (roomName === "W10S10") {
// avoid this room
Expand All @@ -295,8 +302,8 @@ function resources(o: GenericStore): ResourceConstant[] {
}

{
const from = new RoomPosition(25, 25, "E1N1");
const to = new RoomPosition(25, 25, "E4N1");
const from = new RoomPosition(25, 25, roomName);
const to = new RoomPosition(25, 25, "W1S1" as Name<Room>);

// Use `findRoute` to calculate a high-level plan for this path,
// prioritizing highways and owned rooms
Expand Down Expand Up @@ -348,11 +355,11 @@ function resources(o: GenericStore): ResourceConstant[] {
// Game.map.getTerrainAt(pos)

{
Game.map.getTerrainAt(25, 20, "W10N10");
Game.map.getTerrainAt(25, 20, roomName);
}

{
Game.map.getTerrainAt(new RoomPosition(25, 20, "W10N10"));
Game.map.getTerrainAt(new RoomPosition(25, 20, roomName));
}

// Game.map.getRoomStatus(roomName)
Expand All @@ -368,7 +375,7 @@ function resources(o: GenericStore): ResourceConstant[] {

{
// Game.market.calcTransactionCost(amount, roomName1, roomName2)
const cost = Game.market.calcTransactionCost(1000, "W0N0", "W10N5");
const cost = Game.market.calcTransactionCost(1000, roomName, anotherRoomName);

// Game.market.cancelOrder(orderId)
for (const id of Object.keys(Game.market.orders)) {
Expand All @@ -379,7 +386,7 @@ function resources(o: GenericStore): ResourceConstant[] {
Game.market.changeOrderPrice("57bec1bf77f4d17c4c011960", 9.95);

// Game.market.createOrder({type, resourceType, price, totalAmount, [roomName]})
Game.market.createOrder({ type: ORDER_SELL, resourceType: RESOURCE_GHODIUM, price: 9.95, totalAmount: 10000, roomName: "W1N1" });
Game.market.createOrder({ type: ORDER_SELL, resourceType: RESOURCE_GHODIUM, price: 9.95, totalAmount: 10000, roomName: roomName });
Game.market.createOrder({ type: ORDER_SELL, resourceType: RESOURCE_GHODIUM, price: 9.95, totalAmount: 10000 });

// Testing the hardcoded string literal value of the `type` field
Expand All @@ -398,18 +405,18 @@ function resources(o: GenericStore): ResourceConstant[] {
}

// Game.market.deal(orderId, amount, [yourRoomName])
Game.market.deal("57cd2b12cda69a004ae223a3", 1000, "W1N1");
Game.market.deal("57cd2b12cda69a004ae223a3", 1000, roomName);

const amountToBuy = 2000;
const maxTransferEnergyCost = 500;
const orders = Game.market.getAllOrders({ type: ORDER_SELL, resourceType: RESOURCE_GHODIUM });

for (const i of orders) {
if (i.roomName) {
const transferEnergyCost = Game.market.calcTransactionCost(amountToBuy, "W1N1", i.roomName);
const transferEnergyCost = Game.market.calcTransactionCost(amountToBuy, roomName, i.roomName);

if (transferEnergyCost < maxTransferEnergyCost) {
Game.market.deal(i.id, amountToBuy, "W1N1");
Game.market.deal(i.id, amountToBuy, roomName);
break;
}
}
Expand All @@ -427,7 +434,7 @@ function resources(o: GenericStore): ResourceConstant[] {
(currentOrder) =>
currentOrder.resourceType === RESOURCE_GHODIUM &&
currentOrder.type === ORDER_SELL &&
Game.market.calcTransactionCost(1000, targetRoom, currentOrder.roomName!) < 500,
Game.market.calcTransactionCost(1000, anotherRoomName, currentOrder.roomName!) < 500,
);

// Game.market.getOrderById(id)
Expand All @@ -451,7 +458,7 @@ function resources(o: GenericStore): ResourceConstant[] {
// PathFinder

{
const pfCreep = Game.creeps.John;
const pfCreep = Game.creeps[creepName];

const goals = pfCreep.room.find(FIND_SOURCES).map((source) => {
// We can't actually walk on sources-- set `range` to 1
Expand Down Expand Up @@ -573,7 +580,7 @@ function resources(o: GenericStore): ResourceConstant[] {
InterShardMemory.setLocal(localShardData);
localShardData = InterShardMemory.getLocal();

const remoteShardData: string = InterShardMemory.getRemote("shard2") || "";
const remoteShardData: string = InterShardMemory.getRemote("shard2" as Name<Shard>) || "";
}

// Find Overloads
Expand Down Expand Up @@ -984,7 +991,7 @@ function resources(o: GenericStore): ResourceConstant[] {
// test discriminated union
switch (unowned.structureType) {
case STRUCTURE_TOWER:
unowned.heal(Game.creeps.myCreep);
unowned.heal(Game.creeps["myCreep" as Name<Creep>]);
break;
case STRUCTURE_CONTAINER:
case STRUCTURE_STORAGE:
Expand All @@ -1000,15 +1007,15 @@ function resources(o: GenericStore): ResourceConstant[] {
// test discriminated union using filter functions on find

// $ExpectType AnyStructure
const from = Game.rooms.myRoom.find(FIND_STRUCTURES, {
const from = Game.rooms["myRoom" as Name<Room>].find(FIND_STRUCTURES, {
filter: (s) => (s.structureType === STRUCTURE_CONTAINER || s.structureType === STRUCTURE_STORAGE) && s.store.energy > 0,
})[0];
// $ExpectType AnyOwnedStructure | null
const to = from.pos.findClosestByPath(FIND_MY_STRUCTURES, {
filter: (s) => (s.structureType === STRUCTURE_SPAWN || s.structureType === STRUCTURE_EXTENSION) && s.energy < s.energyCapacity,
});

Game.rooms.myRoom
Game.rooms["myRoom" as Name<Room>]
.find(FIND_MY_STRUCTURES, {
filter: (s) => s.structureType === STRUCTURE_RAMPART,
})
Expand All @@ -1017,7 +1024,7 @@ function resources(o: GenericStore): ResourceConstant[] {

{
// Test that you can use signatures
EXTENSION_ENERGY_CAPACITY[Game.rooms.myRoom.controller!.level];
EXTENSION_ENERGY_CAPACITY[Game.rooms[roomName].controller!.level];

REACTIONS[Object.keys(creep.carry)[0]];

Expand All @@ -1036,7 +1043,7 @@ function resources(o: GenericStore): ResourceConstant[] {

tombstone.id;

const creep = Game.creeps["dave"];
const creep = Game.creeps["dave" as Name<Creep>];
creep.withdraw(tombstone, RESOURCE_ENERGY);
}

Expand Down Expand Up @@ -1127,13 +1134,13 @@ function resources(o: GenericStore): ResourceConstant[] {
// Room.Terrain

{
const room = Game.rooms[""];
const room = Game.rooms["" as Name<Room>];

const myTerrain = room.getTerrain();

const otherTerrain = new Room.Terrain("E2S7");
const otherTerrain = new Room.Terrain(roomName);

const anotherTerrain = Game.map.getRoomTerrain("W2N5");
const anotherTerrain = Game.map.getRoomTerrain(anotherRoomName);

const ret = myTerrain.get(5, 5);
if (ret === 0) {
Expand Down Expand Up @@ -1267,10 +1274,10 @@ function atackPower(creep: Creep) {
// Game.map.visual
{
const mapVis = Game.map.visual;
const point1 = new RoomPosition(1, 1, "E1N1");
const point2 = new RoomPosition(1, 1, "E1N8");
const point3 = new RoomPosition(1, 1, "E8N8");
const point4 = new RoomPosition(1, 1, "E1N8");
const point1 = new RoomPosition(1, 1, roomName);
const point2 = new RoomPosition(1, 1, anotherRoomName);
const point3 = new RoomPosition(1, 1, "E8N8" as Name<Room>);
const point4 = new RoomPosition(1, 1, "E1N8" as Name<Room>);

mapVis.line(point1, point2).circle(point3, { fill: "#f2f2f2" }).poly([point1, point2, point3, point4]).rect(point3, 50, 50);

Expand Down
2 changes: 1 addition & 1 deletion src/creep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ interface Creep extends RoomObject {
* You can choose the name while creating a new creep, and it cannot be changed later.
* This name is a hash key to access the creep via the {@link Game.creeps} object.
*/
name: string;
name: Name<this>;
/**
* An object with the creep’s owner info.
*/
Expand Down
6 changes: 3 additions & 3 deletions src/flag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface Flag extends RoomObject {
*
* This name is a hash key to access the flag via the {@link Game.flags} object. The maximum name length is 60 characters.
*/
name: string;
name: Name<this>;
/**
* Flag secondary color. One of the {@link ColorConstant COLOR_*} constants.
*/
Expand Down Expand Up @@ -62,8 +62,8 @@ interface Flag extends RoomObject {
}

interface FlagConstructor extends _Constructor<Flag> {
new (name: string, color: ColorConstant, secondaryColor: ColorConstant, roomName: string, x: number, y: number): Flag;
(name: string, color: ColorConstant, secondaryColor: ColorConstant, roomName: string, x: number, y: number): Flag;
new (name: Name<Flag>, color: ColorConstant, secondaryColor: ColorConstant, roomName: Name<Room>, x: number, y: number): Flag;
(name: Name<Flag>, color: ColorConstant, secondaryColor: ColorConstant, roomName: Name<Room>, x: number, y: number): Flag;
}

declare const Flag: FlagConstructor;
10 changes: 5 additions & 5 deletions src/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ interface Game {
/**
* A hash containing all your creeps with creep names as hash keys.
*/
creeps: { [creepName: string]: Creep };
creeps: { [creepName: Name<Creep>]: Creep };
/**
* A hash containing all your flags with flag names as hash keys.
*/
flags: { [flagName: string]: Flag };
flags: { [flagName: Name<Flag>]: Flag };
/**
* Your Global Control Level.
*/
Expand All @@ -35,7 +35,7 @@ interface Game {
*
* Even power creeps not spawned in the world can be accessed here.
*/
powerCreeps: { [creepName: string]: PowerCreep };
powerCreeps: { [creepName: Name<PowerCreep>]: PowerCreep };
/**
* An object with your global resources that are bound to the account, like pixels or cpu unlocks.
*
Expand All @@ -47,11 +47,11 @@ interface Game {
*
* A room is visible if you have a creep or an owned structure in it.
*/
rooms: { [roomName: string]: Room };
rooms: { [roomName: Name<Room>]: Room };
/**
* A hash containing all your spawns with spawn names as hash keys.
*/
spawns: { [spawnName: string]: StructureSpawn };
spawns: { [spawnName: Name<StructureSpawn>]: StructureSpawn };
/**
* A hash containing all your structures with structure id as hash keys.
*/
Expand Down
Loading