diff --git a/src/directives/initializer.ts b/src/directives/initializer.ts index 081a081bd..8565d94bd 100644 --- a/src/directives/initializer.ts +++ b/src/directives/initializer.ts @@ -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 {DirectiveHarass} from "./offense/harass"; /** * This is the initializer for directives, which maps flags by their color code to the corresponding directive @@ -58,6 +59,8 @@ export function DirectiveWrapper(flag: Flag): Directive | undefined { return new DirectivePairDestroy(flag); case COLOR_PURPLE: return new DirectiveControllerAttack(flag); + case COLOR_WHITE: + return new DirectiveHarass(flag); } break; diff --git a/src/directives/offense/harass.ts b/src/directives/offense/harass.ts new file mode 100644 index 000000000..4fc6732b2 --- /dev/null +++ b/src/directives/offense/harass.ts @@ -0,0 +1,90 @@ +import {RoomIntel} from '../../intel/RoomIntel'; +import {profile} from '../../profiler/decorator'; +import {Directive} from '../Directive'; +import {HarassOverlord} from "../../overlords/offense/harass"; +import {log, Log} from "../../console/log"; +import {MY_USERNAME} from "../../~settings"; + +interface DirectiveHarassMemory extends FlagMemory { + enhanced?: boolean; + targetPlayer?: string; + roomsToHarass: string[]; +} + +/** + * Harass Directive that wanders through enemy rooms killing stuff + * Placed on an enemy room, it will harass all of it's remotes periodically + */ +@profile +export class DirectiveHarass extends Directive { + + static directiveName = 'harass'; + static color = COLOR_RED; + static secondaryColor = COLOR_WHITE; + + memory: DirectiveHarassMemory; + + constructor(flag: Flag) { + super(flag); + this.memory.targetPlayer = RoomIntel.roomOwnedBy(flag.pos.roomName); + if (this.memory.targetPlayer == MY_USERNAME) { + log.error(`Ahhhhhh harassing self in room ${flag.pos.roomName}`); + this.remove(); + } + if (this.memory.targetPlayer) { + this.memory.roomsToHarass = this.findNearbyReservedRooms(flag.pos.roomName, this.memory.targetPlayer); + } + } + + spawnMoarOverlords() { + // For now, just spawn from RCL 5+ rooms + this.overlords.harassOverlord = new HarassOverlord(this, this.memory.enhanced); + } + + init(): void { + // if + // if (!this.memory.roomsToHarass && this.memory.targetPlayer) + + + } + + findNearbyReservedRoomsForHarassment() { + if (this.memory.targetPlayer) { + return this.findNearbyReservedRooms(this.flag.pos.roomName, this.memory.targetPlayer); + } + return []; + } + + /** + * Finds the rooms to harass + * + * @param roomName + * @param playerName + */ + findNearbyReservedRooms(roomName: string, playerName: string): string[] { + if (!this.memory.targetPlayer) { + log.error(`Unable to find which player to harass in room ${roomName}`); + return []; + } + let reservedByTargetPlayer: string[] = []; + let adjacentRooms = _.values(Game.map.describeExits(roomName)) as string[]; + adjacentRooms.forEach(room => { + if (RoomIntel.roomReservedBy(room) == playerName) { + reservedByTargetPlayer.push(room); + // This will double add rooms next to owned rooms, making it more likely to harass them + (_.values(Game.map.describeExits(room)) as string[]).forEach(room => { + if (RoomIntel.roomReservedBy(room) == playerName) { + reservedByTargetPlayer.push(room); + } + }) + } + }); + Game.notify(`Looking for nearby rooms to harass, found ${reservedByTargetPlayer}`); + return reservedByTargetPlayer; + } + + run(): void { + // Probably something modifying frequency of harassment + + } +} diff --git a/src/overlords/offense/harass.ts b/src/overlords/offense/harass.ts new file mode 100644 index 000000000..8fb8fc87d --- /dev/null +++ b/src/overlords/offense/harass.ts @@ -0,0 +1,80 @@ +import {CreepSetup} from '../../creepSetups/CreepSetup'; +import {CombatSetups, Roles} from '../../creepSetups/setups'; +import {DirectiveInvasionDefense} from '../../directives/defense/invasionDefense'; +import {CombatIntel} from '../../intel/CombatIntel'; +import {OverlordPriority} from '../../priorities/priorities_overlords'; +import {profile} from '../../profiler/decorator'; +import {boostResources} from '../../resources/map_resources'; +import {CombatZerg} from '../../zerg/CombatZerg'; +import {CombatOverlord} from '../CombatOverlord'; +import {DirectiveHarass} from "../../directives/offense/harass"; +import {log} from "../../console/log"; + +/** + * Spawns ranged harassers to stop mining for an enemy room + */ +@profile +export class HarassOverlord extends CombatOverlord { + + hydralisks: CombatZerg[]; + room: Room; + targetRemoteToHarass: string; + directive: DirectiveHarass; + + + static settings = { + retreatHitsPercent : 0.85, + reengageHitsPercent: 0.95, + }; + + constructor(directive: DirectiveHarass, + boosted = false, + priority = OverlordPriority.offense.harass) { + super(directive, 'harass', priority, 1); + this.directive = directive; + this.hydralisks = this.combatZerg(Roles.ranged, { + boostWishlist: boosted ? [boostResources.ranged_attack[3], boostResources.heal[3], boostResources.move[3]] + : undefined + }); + } + + private handleHarass(hydralisk: CombatZerg): void { + hydralisk.autoCombat(this.targetRemoteToHarass || hydralisk.room.name); + + //this.chooseRemoteToHarass(hydralisk, hydralisk.room.name); + if (!this.targetRemoteToHarass) { + this.chooseRemoteToHarass(hydralisk, hydralisk.room.name); + } + if (this.targetRemoteToHarass && hydralisk.room.name != this.targetRemoteToHarass) { + hydralisk.goToRoom(this.targetRemoteToHarass); + } else if (hydralisk.room.dangerousPlayerHostiles.length > 2) { + // Time to move on + this.chooseRemoteToHarass(hydralisk, hydralisk.room.name); + } + // Clean up construction sites then move on to another room + } + + chooseRemoteToHarass(hydralisk: CombatZerg, currentRoom: string) { + if (!this.directive.memory.roomsToHarass || this.directive.memory.roomsToHarass.length == 0) { + this.directive.memory.roomsToHarass = this.directive.findNearbyReservedRoomsForHarassment(); + } + let nextRoom = this.directive.memory.roomsToHarass.shift(); + if (nextRoom) { + this.directive.memory.roomsToHarass.push(nextRoom); + this.targetRemoteToHarass = nextRoom; + log.debug(`Selecting new target of ${this.targetRemoteToHarass} for ${hydralisk.print} from ${this.directive.memory.roomsToHarass}`); + hydralisk.say(`Tgt ${this.targetRemoteToHarass}`); + hydralisk.goToRoom(this.targetRemoteToHarass); + } + } + + init() { + this.reassignIdleCreeps(Roles.ranged); + const setup = CombatSetups.hydralisks.default; + this.wishlist(1, setup); + } + + run() { + this.autoRun(this.hydralisks, hydralisk => this.handleHarass(hydralisk)); + } +} diff --git a/src/priorities/priorities_overlords.ts b/src/priorities/priorities_overlords.ts index bef3ab436..1ed197744 100644 --- a/src/priorities/priorities_overlords.ts +++ b/src/priorities/priorities_overlords.ts @@ -22,7 +22,8 @@ export let OverlordPriority = { destroy : 300, healPoint : 301, siege : 302, - controllerAttack: 399 + controllerAttack: 399, + harass : 571, }, colonization: { // Colonizing new rooms