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

View File

@ -1,22 +1,21 @@
import { randomIntInRange } from '../utils/Random'; import { randomValueFromArray } from '../utils/Random';
export interface SourceNumber { export function selectSource(creep: Creep): Id<Source> {
sourceNum: number | undefined;
}
function selectSource(memory: SourceNumber) {
if (memory.sourceNum === undefined) {
const sources = creep.room.find(FIND_SOURCES);
memory.sourceNum = randomIntInRange(0, sources.length);
}
}
function moveToSource(creep: Creep) {
const memory = creep.memory as SourceNumber;
const sources = creep.room.find(FIND_SOURCES); const sources = creep.room.find(FIND_SOURCES);
const sourceNum = memory.sourceNum; const choices: Array<String> = [];
if (creep.harvest(sources[sourceNum]) == ERR_NOT_IN_RANGE) { for (let source of sources) {
creep.say('🔄 harvest ' + sourceNum); const weight = getSourceWeight(source);
creep.moveTo(sources[sourceNum], { visualizePathStyle: { stroke: '#ffaa00' } }); for (let i = 0; i < weight; ++i) {
choices.push(source.id);
}
} }
console.log('Sources', choices);
return randomValueFromArray(choices) as Id<Source>;
}
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 { interface HarvesterMemory extends CreepMemory {
sourceNum: number | undefined; sourceId: Id<Source> | undefined;
} }
export function runAsHarvester(creep: Creep) { export function runAsHarvester(creep: Creep) {
const memory = creep.memory as HarvesterMemory; const memory = creep.memory as HarvesterMemory;
if (memory.sourceNum === undefined) { if (memory.sourceId === undefined) {
const sources = creep.room.find(FIND_SOURCES); memory.sourceId = selectSource(creep);
memory.sourceNum = randomIntInRange(0, sources.length);
} }
if (creep.store.getFreeCapacity() > 0) { if (creep.store.getFreeCapacity() > 0) {
let sources = creep.room.find(FIND_SOURCES); const source = Game.getObjectById(memory.sourceId);
const sourceNum = memory.sourceNum; if (source && creep.harvest(source) === ERR_NOT_IN_RANGE) {
if (creep.harvest(sources[sourceNum]) === ERR_NOT_IN_RANGE) { creep.say('🔄 harvest');
creep.say('🔄 harvest ' + sourceNum); creep.moveTo(source, { visualizePathStyle: { stroke: '#ffaa00' } });
creep.moveTo(sources[sourceNum], { visualizePathStyle: { stroke: '#ffaa00' } });
} }
} else { } else {
let targets = creep.room.find(FIND_STRUCTURES, { 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 { interface UpgraderMemory extends CreepMemory {
upgrading: boolean | undefined; upgrading: boolean | undefined;
sourceNum: number | undefined; sourceId: Id<Source> | undefined;
} }
export function runAsUpgrader(creep: Creep) { export function runAsUpgrader(creep: Creep) {
@ -16,9 +16,8 @@ export function runAsUpgrader(creep: Creep) {
memory.upgrading = true; memory.upgrading = true;
} }
if (memory.sourceNum === undefined) { if (memory.sourceId === undefined) {
const sources = creep.room.find(FIND_SOURCES); memory.sourceId = selectSource(creep);
memory.sourceNum = randomIntInRange(0, sources.length);
} }
if (memory.upgrading) { if (memory.upgrading) {
@ -27,11 +26,10 @@ export function runAsUpgrader(creep: Creep) {
creep.moveTo(creep.room.controller, { visualizePathStyle: { stroke: '#ffffff' } }); creep.moveTo(creep.room.controller, { visualizePathStyle: { stroke: '#ffffff' } });
} }
} else { } else {
const sources = creep.room.find(FIND_SOURCES); const source = Game.getObjectById(memory.sourceId);
const sourceNum = memory.sourceNum; if (source && creep.harvest(source) == ERR_NOT_IN_RANGE) {
if (creep.harvest(sources[sourceNum]) == ERR_NOT_IN_RANGE) { creep.say('🔄 harvest');
creep.say('🔄 harvest ' + sourceNum); creep.moveTo(source, { visualizePathStyle: { stroke: '#ffaa00' } });
creep.moveTo(sources[sourceNum], { visualizePathStyle: { stroke: '#ffaa00' } });
} }
} }
} }

View File

@ -4,8 +4,8 @@ import { runAsBuilder } from './creep/builder';
import { runAsUpgrader } from './creep/upgrader'; import { runAsUpgrader } from './creep/upgrader';
import { uniqId } from './utils/Identity'; import { uniqId } from './utils/Identity';
function makeName(role: string): string { function makeName(): string {
return uniqId(role + '_'); return uniqId();
} }
enum CreepRole { enum CreepRole {
@ -19,17 +19,35 @@ function makeCreep(role: CreepRole, count: number) {
console.log(`Make creep "${role}"`, 'need', count, 'has', creeps.length); console.log(`Make creep "${role}"`, 'need', count, 'has', creeps.length);
if (creeps.length < count) { if (creeps.length < count) {
const firstSpawn = _.first(Object.values(Game.spawns)); const firstSpawn = _.first(Object.values(Game.spawns));
const name = makeName(role); const name = makeName();
const memory = { role: role } as CreepMemory; const memory = { role: role } as CreepMemory;
const err = firstSpawn.spawnCreep([WORK, CARRY, MOVE], name, { memory }); const err = firstSpawn.spawnCreep([WORK, CARRY, MOVE], name, { memory });
console.log(`Make creep "${role}"`, 'err', err); 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 // 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 // This utility uses source maps to get the line numbers and file names of the original, TS source code
export const loop = ErrorMapper.wrapLoop(() => { 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 // Automatically delete memory of missing creeps
for (const name in Memory.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.UPGRADER, 6);
makeCreep(CreepRole.BUILDER, 6); makeCreep(CreepRole.BUILDER, 6);
callHarvestersFromOthers(minHarvCount);
// Process current creeps // Process current creeps
for (let name in Game.creeps) { for (let name in Game.creeps) {
const creep = Game.creeps[name]; const creep = Game.creeps[name];

View File

@ -2,3 +2,9 @@ export function randomIntInRange(min: number, max: number): number {
const delta = max - min; const delta = max - min;
return Math.floor(Math.random() * delta) + 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];
}