Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Power creep directive #7

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
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
8 changes: 8 additions & 0 deletions src/Colony.ts
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,13 @@ export class Colony {
return allAssets;
}

private runPowerSpawn() {
if (this.powerSpawn && this.assets.energy > 300000 && this.powerSpawn.energy > 50
&& this.powerSpawn.power > 0) {
this.powerSpawn.processPower();
}
}

/**
* Initializes the state of the colony each tick
*/
Expand All @@ -567,6 +574,7 @@ export class Colony {
this.linkNetwork.run(); // Run the link network
this.roadLogistics.run(); // Run the road network
this.roomPlanner.run(); // Run the room planner
this.runPowerSpawn(); // Run power spawn - short term
this.stats(); // Log stats per tick
}

Expand Down
11 changes: 11 additions & 0 deletions src/declarations/prototypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ interface Creep {
inRampart: boolean;
}

interface PowerCreep {
hitsPredicted?: number;
intel?: { [property: string]: number };
memory: CreepMemory;
fatigue: number;
body: BodyPartDefinition[];
boosts: _ResourceConstantSansEnergy[];
boostCounts: { [boostType: string]: number };
inRampart: boolean;
}

interface ConstructionSite {
isWalkable: boolean;
}
Expand Down
8 changes: 8 additions & 0 deletions src/directives/initializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {DirectiveTargetSiege} from './targeting/siegeTarget';
import {DirectiveTerminalEmergencyState} from './terminalState/terminalState_emergency';
import {DirectiveTerminalEvacuateState} from './terminalState/terminalState_evacuate';
import {DirectiveTerminalRebuildState} from './terminalState/terminalState_rebuild';
import {DirectiveBaseOperator} from "./powerCreeps/baseOperator";

/**
* This is the initializer for directives, which maps flags by their color code to the corresponding directive
Expand Down Expand Up @@ -128,6 +129,13 @@ export function DirectiveWrapper(flag: Flag): Directive | undefined {
return new DirectiveRPBunker(flag);
}
break;
// Power directives ====================================================================================
case COLOR_CYAN:
switch (flag.secondaryColor) {
case COLOR_PURPLE:
return new DirectiveBaseOperator(flag);
}
break;
}

}
288 changes: 288 additions & 0 deletions src/directives/powerCreeps/baseOperator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
import {CombatPlanner, SiegeAnalysis} from "../../strategy/CombatPlanner";
import {profile} from "../../profiler/decorator";
import {Directive} from "../Directive";
import {log} from "../../console/log";
import {Visualizer} from "../../visuals/Visualizer";
import {Power} from "./powers/genericPower";
import {GenerateOps} from "./powers/generateOps";
import {DirectiveNukeResponse} from "../situational/nukeResponse";
import {OperateExtension} from "./powers/operateExtension";


interface DirectiveBaseOperatorMemory extends FlagMemory {
powerPriorities: PowerConstant[];
}

export enum types {
opgen,
baseoperator,
basedefender
}

/**
* Simple directive to run a power creep where the flag name is the power creep name
*/
@profile
export class DirectiveBaseOperator extends Directive {

static directiveName = 'BaseOperator';
static color = COLOR_CYAN;
static secondaryColor = COLOR_PURPLE;

memory: DirectiveBaseOperatorMemory;

// Power Creep Hack
//powerCreep: PowerCreep;
powerCreepName: string;

defaultPowerPriorities: PowerConstant[] = [
PWR_GENERATE_OPS,
PWR_REGEN_SOURCE,
PWR_OPERATE_TOWER,
PWR_OPERATE_LAB,
PWR_OPERATE_SPAWN,
PWR_OPERATE_EXTENSION,
PWR_REGEN_MINERAL];

// overlords: {
// scout?: StationaryScoutOverlord;
// destroy?: SwarmDestroyerOverlord | PairDestroyerOverlord;
// guard?: OutpostDefenseOverlord;
// controllerAttack?: ControllerAttackerOverlord;
// };

constructor(flag: Flag) {
super(flag);
const powerCreep = Game.powerCreeps[flag.name];
if (!powerCreep) {
log.error(`Power Creep not found for ${this.print}, deleting directive`);
this.remove();
}
this.memory.powerPriorities = this.memory.powerPriorities || this.defaultPowerPriorities;
}

spawnMoarOverlords() {
}

init(): void {

}


// Wrapped powerCreep methods ===========================================================================================

renew(powerCreep: PowerCreep, powerSource: StructurePowerBank | StructurePowerSpawn) {
if (powerCreep.pos.inRangeToPos(powerSource.pos, 1)) {
return powerCreep.renew(powerSource);
} else {
return powerCreep.moveTo(powerSource, {ignoreRoads: true, range: 1, swampCost: 1, reusePath: 0, visualizePathStyle: {lineStyle: "dashed", fill: 'yellow'}});
}
}

enablePower(powerCreep: PowerCreep, controller: StructureController) {
log.alert(`Trying to enable power for ${controller} with `);
if (powerCreep.pos.inRangeToPos(controller.pos, 1)) {
return powerCreep.enableRoom(controller);
} else {
//let path = powerCreep.pos.findPathTo(controller, {ignoreRoads: true, range: 1, swampCost: 1});
//log.alert(`Trying to enable power for ${controller} with ${JSON.stringify(path)}`);
//return powerCreep.moveByPath(path);
return powerCreep.moveTo(controller.pos, {ignoreRoads: true, range: 1, swampCost: 1, reusePath: 0, visualizePathStyle: {lineStyle: "solid"}});
}
}

usePower(powerCreep: PowerCreep, power: PowerConstant) {
console.log(`The power constant is ${power}`)
switch(power) {
case PWR_GENERATE_OPS: return new GenerateOps(powerCreep);
case PWR_OPERATE_EXTENSION: return new OperateExtension(powerCreep);
// case PWR_OPERATE_SPAWN: return this.operateSpawn();
}

}
//
// /**
// * Generate 1/2/4/6/8 ops resource units. Cooldown 50 ticks. Required creep level: 0/2/7/14/22.
// */
// generateOps() {
// if (powerCreep.powers[PWR_GENERATE_OPS].cooldown !> 0) {
// return powerCreep.usePower(PWR_GENERATE_OPS);
// }
// return ERR_TIRED;
// }
//
// operateSpawn(spawn?: StructureSpawn) {
// // if (powerCreep.powers[PWR_oper])
// // if (!spawn) {
// // spawn = _.first(this.room!.spawns.filter(spawn => spawn.effects.length == 0));
// // if (!spawn) {
// // return ERR;
// // }
// // }
// if (this.pos.inRangeToPos(spawn.pos, 1)) {
// return powerCreep.usePower(PWR_OPERATE_SPAWN, spawn);
// } else {
// return powerCreep.moveTo(spawn);
// }
// }
//
// operateTower(tower: StructureTower) {
// if (this.pos.inRangeToPos(tower.pos, POWER_INFO[PWR_OPERATE_TOWER].range)) {
// return powerCreep.usePower(PWR_OPERATE_TOWER, tower);
// } else {
// return powerCreep.moveTo(tower);
// }
// }
//
// operateStorage(storage: StructureStorage) {
// if (this.pos.inRangeToPos(storage.pos, POWER_INFO[PWR_OPERATE_STORAGE].range)) {
// return powerCreep.usePower(PWR_OPERATE_STORAGE, storage);
// } else {
// return powerCreep.moveTo(storage);
// }
// }
//
// operateExtensions(container: StructureStorage | StructureTerminal | StructureContainer) {
// if (this.pos.inRangeToPos(container.pos, POWER_INFO[PWR_OPERATE_EXTENSION].range)) {
// return powerCreep.usePower(PWR_OPERATE_EXTENSION, container);
// } else {
// return powerCreep.moveTo(container);
// }
// }
//
// operateObserver(observer: StructureObserver) {
// if (this.pos.inRangeToPos(observer.pos, POWER_INFO[PWR_OPERATE_OBSERVER].range)) {
// return powerCreep.usePower(PWR_OPERATE_OBSERVER, observer);
// } else {
// return powerCreep.moveTo(observer);
// }
// }
//
// operateTerminal(terminal: StructureTerminal) {
// if (this.pos.inRangeToPos(terminal.pos, POWER_INFO[PWR_OPERATE_TERMINAL].range)) {
// return powerCreep.usePower(PWR_OPERATE_TERMINAL, terminal);
// } else {
// return powerCreep.moveTo(terminal);
// }
// }
//
// operatePower(power: StructurePowerSpawn) {
// if (this.pos.inRangeToPos(power.pos, POWER_INFO[PWR_OPERATE_POWER].range)) {
// return powerCreep.usePower(PWR_OPERATE_POWER, power);
// } else {
// return powerCreep.moveTo(power);
// }
// }
//
// operateController(controller: StructureController) {
// if (this.pos.inRangeToPos(controller.pos, POWER_INFO[PWR_OPERATE_CONTROLLER].range)) {
// return powerCreep.usePower(PWR_OPERATE_CONTROLLER, controller);
// } else {
// return powerCreep.moveTo(controller);
// }
// }
//
// // operateFactory(factory: StructureFactory) {
// // if (this.pos.inRangeToPos(factory.pos, POWER_INFO[PWR_OPERATE_FACTORY].range)) {
// // return powerCreep.usePower(PWR_OPERATE_FACTORY, factory);
// // } else {
// // return this.moveTo(factory);
// // }
// // }
//
// shield() {
// if (powerCreep.powers[PWR_SHIELD].cooldown !> 0) {
// return powerCreep.usePower(PWR_SHIELD);
// }
// return ERR_TIRED;
// }
//
// regenSource(source : Source) {
// if (this.pos.inRangeToPos(source.pos, POWER_INFO[PWR_REGEN_SOURCE].range)) {
// return powerCreep.usePower(PWR_REGEN_SOURCE, source);
// } else {
// return powerCreep.moveTo(source);
// }
// }
//
// regenMineral(mineral: Mineral) {
// if (this.pos.inRangeToPos(mineral.pos, POWER_INFO[PWR_REGEN_MINERAL].range)) {
// return powerCreep.usePower(PWR_REGEN_MINERAL, mineral);
// } else {
// return powerCreep.moveTo(mineral);
// }
// }
//
// fortify(rampart: StructureRampart) {
// if (this.pos.inRangeToPos(rampart.pos, POWER_INFO[PWR_FORTIFY].range)) {
// return powerCreep.usePower(PWR_FORTIFY, rampart);
// } else {
// return powerCreep.moveTo(rampart);
// }
// }
//
// operateLab(lab: StructureLab) {
// if (this.pos.inRangeToPos(lab.pos, POWER_INFO[PWR_OPERATE_LAB].range)) {
// return powerCreep.usePower(PWR_OPERATE_LAB, lab);
// } else {
// return powerCreep.moveTo(lab);
// }
// }


runPowers(powerCreep: PowerCreep) {
const priorities = this.memory.powerPriorities;
console.log(`Powerid of priority list of ${priorities}`);
for (let powerId in priorities) {
console.log(`Powerid of ${powerId} and list of ${priorities}`);
let powerToUse = this.usePower(powerCreep, priorities[powerId]);
if (powerToUse && powerToUse.operatePower()) {
break;
}
}
}


run(): void {
const powerCreep = Game.powerCreeps[this.powerCreepName];

// For the power creeps that just sit on power spawn
const isStationary = powerCreep.name.toLowerCase().indexOf(types.basedefender.toString());

console.log(`Running power creep ${JSON.stringify(powerCreep)} with ttl ${powerCreep.ticksToLive} with ${this.room!.powerSpawn}`);
if (!this.room) {
return;
} else if (!powerCreep.ticksToLive && this.room && this.room.powerSpawn) {
// Spawn creep
let res = powerCreep.spawn(this.room.powerSpawn);
log.alert(`Running ${powerCreep} with spawn of ${res}`);
} else if (this.room.controller && !this.room.controller.isPowerEnabled && !isStationary) {
// Enable power
let res = this.enablePower(powerCreep, this.room.controller);
log.alert(`Running ${powerCreep} with enable power of ${res}`);
} else if (powerCreep && powerCreep.ticksToLive && powerCreep.ticksToLive < 900 && this.room.powerSpawn) {
let res = this.renew(powerCreep, this.room.powerSpawn);
log.alert(`Running ${powerCreep} with renew of ${res}`);
} else {
let res = this.runPowers(powerCreep);
log.alert(`Running ${powerCreep} with power of ${res}`);
}

if (this.room.hostiles.length > 2 || (powerCreep.pos && DirectiveNukeResponse.isPresent(powerCreep.pos, 'room'))) {
const towersToBoost = this.colony.towers.filter(tower => !tower.effects || tower.effects.length == 0);
if (towersToBoost.length > 0) {
powerCreep.usePower(PWR_OPERATE_TOWER, towersToBoost[0])
}
if ((!powerCreep.carry.ops || powerCreep.carry.ops < 20) && this.room.storage && this.room.storage.store.ops && this.room.storage.store.ops > 100) {
powerCreep.withdraw(this.room.storage, RESOURCE_OPS, 100);
}
}


}

visuals(): void {
Visualizer.marker(this.pos, {color: 'red'});
}

}
31 changes: 31 additions & 0 deletions src/directives/powerCreeps/powers/generateOps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {profile} from "../../../profiler/decorator";
import {Power} from "./genericPower";
import {log} from "../../../console/log";

export const powerId = PWR_GENERATE_OPS;

/**
* An abstract class for encapsulating power creep power usage.
*/
@profile
export class GenerateOps extends Power {

constructor(powerCreep: PowerCreep, target?: RoomObject) {
super(powerCreep, target);
}

operatePower() {
if (this.powerCreep.carry.ops && this.powerCreep.carry.ops > (this.powerCreep.carryCapacity * 0.9)) {
const terminal = this.powerCreep.room!.terminal;
if (!terminal) {
log.error(`Ops power creep with no storage`);
} else {
this.powerCreep.moveTo(terminal);
this.powerCreep.transfer(terminal, RESOURCE_OPS, this.powerCreep.carry.ops);
}
} else {
return this.powerCreep.usePower(powerId);
}
return ERR_TIRED;
}
}
Loading