Init files

This commit is contained in:
2020-05-31 15:06:55 +03:00
commit 3cd6a07fbf
29 changed files with 947 additions and 0 deletions

93
src/harvester.ts Normal file
View File

@ -0,0 +1,93 @@
/** @param {Creep} creep **/
export function runAsHarvester(creep: Creep) {
if (creep.store.getFreeCapacity() > 0) {
let sources = creep.room.find(FIND_SOURCES);
if (creep.harvest(sources[0]) === ERR_NOT_IN_RANGE) {
creep.moveTo(sources[0], { visualizePathStyle: { stroke: '#ffaa00' } });
}
} else {
let targets = creep.room.find(FIND_STRUCTURES, {
filter: (structure) => {
return (
(structure.structureType === STRUCTURE_EXTENSION ||
structure.structureType === STRUCTURE_SPAWN ||
structure.structureType === STRUCTURE_TOWER) &&
structure.store.getFreeCapacity(RESOURCE_ENERGY) > 0
);
}
});
if (targets.length > 0) {
if (creep.transfer(targets[0], RESOURCE_ENERGY) === ERR_NOT_IN_RANGE) {
creep.moveTo(targets[0], { visualizePathStyle: { stroke: '#ffffff' } });
}
} else {
const spawns = creep.room.find(FIND_MY_SPAWNS);
if (spawns.length > 0) {
creep.say('to spawn');
creep.moveTo(spawns[0]);
}
}
}
}
/** @param {Creep} creep **/
export function runAsBuilder(creep: Creep) {
const memory = creep.memory as CreepMemory & { building: boolean | undefined };
if (memory.building && creep.store[RESOURCE_ENERGY] === 0) {
memory.building = false;
creep.say('🔄 harvest');
}
if (!memory.building && creep.store.getFreeCapacity() === 0) {
memory.building = true;
creep.say('🚧 build');
}
if (memory.building) {
const targets = creep.room.find(FIND_CONSTRUCTION_SITES);
if (targets.length > 0) {
if (creep.build(targets[0]) == ERR_NOT_IN_RANGE) {
creep.moveTo(targets[0], { visualizePathStyle: { stroke: '#ffffff' } });
}
} else {
const spawns = creep.room.find(FIND_MY_SPAWNS);
if (spawns.length > 0) {
creep.say('to spawn');
creep.moveTo(spawns[0]);
}
}
} else {
const sources = creep.room.find(FIND_SOURCES);
if (creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
creep.moveTo(sources[0], { visualizePathStyle: { stroke: '#ffaa00' } });
}
}
}
/** @param {Creep} creep **/
export function runAsUpgrader(creep: Creep) {
const memory = creep.memory as CreepMemory & { upgrading: boolean | undefined };
if (memory.upgrading && creep.store[RESOURCE_ENERGY] === 0) {
memory.upgrading = false;
creep.say('🔄 harvest');
}
if (!memory.upgrading && creep.store.getFreeCapacity() === 0) {
memory.upgrading = true;
creep.say('⚡ upgrade');
}
if (memory.upgrading) {
if (creep.room.controller && creep.upgradeController(creep.room.controller) == ERR_NOT_IN_RANGE) {
creep.moveTo(creep.room.controller, { visualizePathStyle: { stroke: '#ffffff' } });
}
} else {
const sources = creep.room.find(FIND_SOURCES);
if (creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
creep.moveTo(sources[0], { visualizePathStyle: { stroke: '#ffaa00' } });
}
}
}

77
src/main.ts Normal file
View File

@ -0,0 +1,77 @@
import { ErrorMapper } from 'utils/ErrorMapper';
import { runAsBuilder, runAsHarvester, runAsUpgrader } from './harvester';
const ALPHABET = 'abcdefghijklmnopqrstuvwxyz1234567890';
const ALPHABET_LENGTH = ALPHABET.length - 1;
function generateId(count: number): string {
let str = '';
for (let i = 0; i < count; ++i) {
let symbolIndex = Math.floor(Math.random() * ALPHABET_LENGTH);
str += ALPHABET[symbolIndex];
}
return str;
}
export function uniqId(prefix: string = 'id'): string {
return prefix + generateId(16);
}
const ROLE_HARVESTER = 'harvester';
const ROLE_UPGRADER = 'upgrader';
const ROLE_BUILDER = 'builder';
// When compiling TS to JS and bundling with rollup, the line numbers and file names in error messages change
// This utility uses source maps to get the line numbers and file names of the original, TS source code
export const loop = ErrorMapper.wrapLoop(() => {
console.log(`Current game tick is ${Game.time}`);
// Automatically delete memory of missing creeps
for (const name in Memory.creeps) {
if (!(name in Game.creeps)) {
delete Memory.creeps[name];
}
}
// Create new creeps
const HARVESTER_CREEP_COUNT = 1;
const harvesterCreeps = Object.values(Game.creeps).filter((c) => c.memory.role === ROLE_HARVESTER);
if (harvesterCreeps.length < HARVESTER_CREEP_COUNT) {
const firstSpawn = _.first(Object.values(Game.spawns));
const name = uniqId(ROLE_HARVESTER);
const err = firstSpawn.spawnCreep([WORK, CARRY, MOVE], name, { memory: { role: ROLE_HARVESTER } as CreepMemory });
console.log('Err', err);
}
const UPGRADER_CREEP_COUNT = 2;
const upgraderCreeps = Object.values(Game.creeps).filter((c) => c.memory.role === ROLE_UPGRADER);
if (upgraderCreeps.length < UPGRADER_CREEP_COUNT) {
const firstSpawn = _.first(Object.values(Game.spawns));
const name = uniqId(ROLE_UPGRADER);
const err = firstSpawn.spawnCreep([WORK, CARRY, MOVE], name, { memory: { role: ROLE_UPGRADER } as CreepMemory });
console.log('Err', err);
}
const BUILDER_CREEP_COUNT = 2;
const builderCreeps = Object.values(Game.creeps).filter((c) => c.memory.role === ROLE_BUILDER);
if (builderCreeps.length < BUILDER_CREEP_COUNT) {
const firstSpawn = _.first(Object.values(Game.spawns));
const name = uniqId(ROLE_BUILDER);
const err = firstSpawn.spawnCreep([WORK, CARRY, MOVE], name, { memory: { role: ROLE_BUILDER } as CreepMemory });
console.log('Err', err);
}
// Process current creeps
for (let name in Game.creeps) {
const creep = Game.creeps[name];
if (creep.memory.role === ROLE_HARVESTER) {
runAsHarvester(creep);
}
if (creep.memory.role === ROLE_UPGRADER) {
runAsUpgrader(creep);
}
if (creep.memory.role === ROLE_BUILDER) {
runAsBuilder(creep);
}
}
});

20
src/types.d.ts vendored Normal file
View File

@ -0,0 +1,20 @@
// example declaration file - remove these and add your own custom typings
// memory extension samples
interface CreepMemory {
role: string;
room: string;
working: boolean;
}
interface Memory {
uuid: number;
log: any;
}
// `global` extension samples
declare namespace NodeJS {
interface Global {
log: any;
}
}

90
src/utils/ErrorMapper.ts Normal file
View File

@ -0,0 +1,90 @@
// tslint:disable:no-conditional-assignment
import { SourceMapConsumer } from 'source-map';
export class ErrorMapper {
// Cache consumer
private static _consumer?: SourceMapConsumer;
public static get consumer(): SourceMapConsumer {
if (this._consumer == null) {
this._consumer = new SourceMapConsumer(require('main.js.map'));
}
return this._consumer;
}
// Cache previously mapped traces to improve performance
public static cache: { [key: string]: string } = {};
/**
* Generates a stack trace using a source map generate original symbol names.
*
* WARNING - EXTREMELY high CPU cost for first call after reset - >30 CPU! Use sparingly!
* (Consecutive calls after a reset are more reasonable, ~0.1 CPU/ea)
*
* @param {Error | string} error The error or original stack trace
* @returns {string} The source-mapped stack trace
*/
public static sourceMappedStackTrace(error: Error | string): string {
const stack: string = error instanceof Error ? (error.stack as string) : error;
if (this.cache.hasOwnProperty(stack)) {
return this.cache[stack];
}
const re = /^\s+at\s+(.+?\s+)?\(?([0-z._\-\\\/]+):(\d+):(\d+)\)?$/gm;
let match: RegExpExecArray | null;
let outStack = error.toString();
while ((match = re.exec(stack))) {
if (match[2] === 'main') {
const pos = this.consumer.originalPositionFor({
column: parseInt(match[4], 10),
line: parseInt(match[3], 10)
});
if (pos.line != null) {
if (pos.name) {
outStack += `\n at ${pos.name} (${pos.source}:${pos.line}:${pos.column})`;
} else {
if (match[1]) {
// no original source file name known - use file name from given trace
outStack += `\n at ${match[1]} (${pos.source}:${pos.line}:${pos.column})`;
} else {
// no original source file name known or in given trace - omit name
outStack += `\n at ${pos.source}:${pos.line}:${pos.column}`;
}
}
} else {
// no known position
break;
}
} else {
// no more parseable lines
break;
}
}
this.cache[stack] = outStack;
return outStack;
}
public static wrapLoop(loop: () => void): () => void {
return () => {
try {
loop();
} catch (e) {
if (e instanceof Error) {
if ('sim' in Game.rooms) {
const message = `Source maps don't work in the simulator - displaying original error`;
console.log(`<span style='color:red'>${message}<br>${_.escape(e.stack)}</span>`);
} else {
console.log(`<span style='color:red'>${_.escape(this.sourceMappedStackTrace(e))}</span>`);
}
} else {
// can't handle it
throw e;
}
}
};
}
}