Use weights for source selection

This commit is contained in:
Anton Vakhrushev 2020-07-21 13:33:26 +03:00
parent c51647312f
commit 420cd3f72e
6 changed files with 75 additions and 53 deletions

View File

@ -1,8 +1,8 @@
import { randomIntInRange } from '../utils/Random';
import { selectSource } from './common';
interface BuilderMemory extends CreepMemory {
building: boolean | undefined;
sourceNum: number | undefined;
sourceId: Id<Source> | undefined;
}
export function runAsBuilder(creep: Creep) {
@ -16,9 +16,8 @@ export function runAsBuilder(creep: Creep) {
memory.building = true;
}
if (memory.sourceNum === undefined) {
const sources = creep.room.find(FIND_SOURCES);
memory.sourceNum = randomIntInRange(0, sources.length);
if (memory.sourceId === undefined) {
memory.sourceId = selectSource(creep);
}
if (memory.building) {
@ -34,11 +33,10 @@ export function runAsBuilder(creep: Creep) {
creep.moveTo(spawns[0]);
}
} else {
const sources = creep.room.find(FIND_SOURCES);
const sourceNum = memory.sourceNum;
if (creep.harvest(sources[sourceNum]) == ERR_NOT_IN_RANGE) {
creep.say('🔄 harvest ' + sourceNum);
creep.moveTo(sources[sourceNum], { visualizePathStyle: { stroke: '#ffaa00' } });
const source = Game.getObjectById(memory.sourceId);
if (source && creep.harvest(source) == ERR_NOT_IN_RANGE) {
creep.say('🔄 harvest');
creep.moveTo(source, { visualizePathStyle: { stroke: '#ffaa00' } });
}
}
}

View File

@ -1,22 +1,21 @@
import { randomIntInRange } from '../utils/Random';
import { randomValueFromArray } from '../utils/Random';
export interface SourceNumber {
sourceNum: number | undefined;
}
function selectSource(memory: SourceNumber) {
if (memory.sourceNum === undefined) {
export function selectSource(creep: Creep): Id<Source> {
const sources = creep.room.find(FIND_SOURCES);
memory.sourceNum = randomIntInRange(0, sources.length);
const choices: Array<String> = [];
for (let source of sources) {
const weight = getSourceWeight(source);
for (let i = 0; i < weight; ++i) {
choices.push(source.id);
}
}
console.log('Sources', choices);
return randomValueFromArray(choices) as Id<Source>;
}
function moveToSource(creep: Creep) {
const memory = creep.memory as SourceNumber;
const sources = creep.room.find(FIND_SOURCES);
const sourceNum = memory.sourceNum;
if (creep.harvest(sources[sourceNum]) == ERR_NOT_IN_RANGE) {
creep.say('🔄 harvest ' + sourceNum);
creep.moveTo(sources[sourceNum], { visualizePathStyle: { stroke: '#ffaa00' } });
}
function getSourceWeight(source: Source) {
const pos = source.pos;
const terrains = source.room.lookForAtArea(LOOK_TERRAIN, pos.y - 1, pos.x - 1, pos.y + 1, pos.x + 1, true);
const walked = terrains.filter((t) => t.terrain !== 'wall');
return Math.max(walked.length - 1, 1);
}

View File

@ -1,23 +1,21 @@
import { randomIntInRange } from '../utils/Random';
import { selectSource } from './common';
interface HarvesterMemory extends CreepMemory {
sourceNum: number | undefined;
sourceId: Id<Source> | undefined;
}
export function runAsHarvester(creep: Creep) {
const memory = creep.memory as HarvesterMemory;
if (memory.sourceNum === undefined) {
const sources = creep.room.find(FIND_SOURCES);
memory.sourceNum = randomIntInRange(0, sources.length);
if (memory.sourceId === undefined) {
memory.sourceId = selectSource(creep);
}
if (creep.store.getFreeCapacity() > 0) {
let sources = creep.room.find(FIND_SOURCES);
const sourceNum = memory.sourceNum;
if (creep.harvest(sources[sourceNum]) === ERR_NOT_IN_RANGE) {
creep.say('🔄 harvest ' + sourceNum);
creep.moveTo(sources[sourceNum], { visualizePathStyle: { stroke: '#ffaa00' } });
const source = Game.getObjectById(memory.sourceId);
if (source && creep.harvest(source) === ERR_NOT_IN_RANGE) {
creep.say('🔄 harvest');
creep.moveTo(source, { visualizePathStyle: { stroke: '#ffaa00' } });
}
} else {
let targets = creep.room.find(FIND_STRUCTURES, {

View File

@ -1,8 +1,8 @@
import { randomIntInRange } from '../utils/Random';
import { selectSource } from './common';
interface UpgraderMemory extends CreepMemory {
upgrading: boolean | undefined;
sourceNum: number | undefined;
sourceId: Id<Source> | undefined;
}
export function runAsUpgrader(creep: Creep) {
@ -16,9 +16,8 @@ export function runAsUpgrader(creep: Creep) {
memory.upgrading = true;
}
if (memory.sourceNum === undefined) {
const sources = creep.room.find(FIND_SOURCES);
memory.sourceNum = randomIntInRange(0, sources.length);
if (memory.sourceId === undefined) {
memory.sourceId = selectSource(creep);
}
if (memory.upgrading) {
@ -27,11 +26,10 @@ export function runAsUpgrader(creep: Creep) {
creep.moveTo(creep.room.controller, { visualizePathStyle: { stroke: '#ffffff' } });
}
} else {
const sources = creep.room.find(FIND_SOURCES);
const sourceNum = memory.sourceNum;
if (creep.harvest(sources[sourceNum]) == ERR_NOT_IN_RANGE) {
creep.say('🔄 harvest ' + sourceNum);
creep.moveTo(sources[sourceNum], { visualizePathStyle: { stroke: '#ffaa00' } });
const source = Game.getObjectById(memory.sourceId);
if (source && creep.harvest(source) == ERR_NOT_IN_RANGE) {
creep.say('🔄 harvest');
creep.moveTo(source, { visualizePathStyle: { stroke: '#ffaa00' } });
}
}
}

View File

@ -4,8 +4,8 @@ import { runAsBuilder } from './creep/builder';
import { runAsUpgrader } from './creep/upgrader';
import { uniqId } from './utils/Identity';
function makeName(role: string): string {
return uniqId(role + '_');
function makeName(): string {
return uniqId();
}
enum CreepRole {
@ -19,17 +19,35 @@ function makeCreep(role: CreepRole, count: number) {
console.log(`Make creep "${role}"`, 'need', count, 'has', creeps.length);
if (creeps.length < count) {
const firstSpawn = _.first(Object.values(Game.spawns));
const name = makeName(role);
const name = makeName();
const memory = { role: role } as CreepMemory;
const err = firstSpawn.spawnCreep([WORK, CARRY, MOVE], name, { memory });
console.log(`Make creep "${role}"`, 'err', err);
}
}
function callHarvestersFromOthers(minHarvCount: number) {
const harvesters = Object.values(Game.creeps).filter((c) => c.memory.role === CreepRole.HARVESTER);
if (harvesters.length < minHarvCount) {
const others = Object.values(Game.creeps).filter((c) => c.memory.role !== CreepRole.HARVESTER);
const required = Math.min(minHarvCount, others.length);
console.log('Call harvesters', required);
let count = 0;
for (let creep of others) {
if (count >= required) {
break;
}
count++;
creep.memory.role = CreepRole.HARVESTER;
}
}
}
// 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(`\nCurrent game tick is ${Game.time}`);
console.log('');
console.log(`Current game tick is ${Game.time}`);
// Automatically delete memory of missing creeps
for (const name in Memory.creeps) {
@ -38,10 +56,15 @@ export const loop = ErrorMapper.wrapLoop(() => {
}
}
makeCreep(CreepRole.HARVESTER, 6);
const harvCount = 8;
const minHarvCount = Math.floor(harvCount * 0.6);
makeCreep(CreepRole.HARVESTER, harvCount);
makeCreep(CreepRole.UPGRADER, 6);
makeCreep(CreepRole.BUILDER, 6);
callHarvestersFromOthers(minHarvCount);
// Process current creeps
for (let name in Game.creeps) {
const creep = Game.creeps[name];

View File

@ -2,3 +2,9 @@ export function randomIntInRange(min: number, max: number): number {
const delta = max - min;
return Math.floor(Math.random() * delta) + min;
}
export function randomValueFromArray<T>(items: Array<T>): T {
const len = items.length;
const index = randomIntInRange(0, len);
return items[index];
}