Skip to content

Commit

Permalink
Bugfixes with bootstrapping and directive.getColony; 0.4.1 release
Browse files Browse the repository at this point in the history
  • Loading branch information
bencbartlett committed Jun 16, 2018
1 parent c074be1 commit d652d7e
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 25 deletions.
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file. The format

## [Unreleased]


## Overmind [0.4.1] - 2018.6.15

This patch makes Abathur a little smarter in which reactions he chooses and fixes some bugs accidentally introduced by changes in the last release.

### Added
- Initial (incomplete) room planner support for bunkers; this will be finished in a later release
- UpgradeSite inputs now actively request that minerals be removed from them in case they get in there somehow (such as a transporter dying on top of the container)

### Changed
- Abathur now checks to see if a colony can acquire the necessary base ingredients for a reaction queue through terminal transfers or via trading before assigning it to the evolutionChamber
- Renamed `LogisticsNetwork.request()` and `LogisticsNetwork.provide()` to `LogisticsNetwork.requestInput()` and `LogisticsNetwork.requestOutput()` to be less confusing

### Fixed
- Fixed a bug where colony substrings in a flag name could cause a directive to reference the wrong colony, e.g. "E11S12" directs to "E11S1"
- Fixed a bug introduced when CreepSetups were refactored in the last release that could cause bootstrapping directives to fail to run
- Fixed a bug in LogisticsNetwork where predicted carry amounts could exceed carry capacity


## Overmind [0.4.0]: "require('more-minerals')" - 2018.6.14

*"We require more minerals."* Well finally, we now have them! This long-overdue release (the largest update to date by additions/deletions) adds fully automatic mineral mining, processing, trading, and boosting capabilities to Overmind!
Expand Down Expand Up @@ -192,7 +211,8 @@ This release was initially deployed on 2018.3.2 but was re-versioned on 2018.3.1
- Initial pre-release of Overmind after 190 commits and about 80,000 additions.


[Unreleased]: https://github.com/bencbartlett/Overmind/compare/v0.4.0...HEAD
[Unreleased]: https://github.com/bencbartlett/Overmind/compare/v0.4.1...HEAD
[0.4.1]: https://github.com/bencbartlett/Overmind/compare/v0.4.0...v0.4.1
[0.4.0]: https://github.com/bencbartlett/Overmind/compare/v0.3.1...v0.4.0
[0.3.1]: https://github.com/bencbartlett/Overmind/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/bencbartlett/Overmind/compare/v0.2.1...v0.3.0
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Overmind",
"version": "0.4.0",
"version": "0.4.1",
"description": "Overmind Screeps AI",
"author": "Ben Bartlett",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/console/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
//

declare const __VERSION__: string;
global.__VERSION__ = '0.4.0';
global.__VERSION__ = '0.4.1';

declare function deref(ref: string): RoomObject | null;

Expand Down
1 change: 1 addition & 0 deletions src/directives/Directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export abstract class Directive {
let colonyNames = _.keys(Overmind.colonies);
for (let name of colonyNames) {
if (flag.name.includes(name)) {
if (flag.name.split(name)[1] != '') continue; // in case of other substring, e.g. E11S12 and E11S1
flag.memory.colony = name;
return Overmind.colonies[name];
}
Expand Down
23 changes: 23 additions & 0 deletions src/directives/roomPlanner/roomPlanner_bunker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {Directive} from '../Directive';
import {profile} from '../../profiler/decorator';

@profile
export class DirectiveRPBunker extends Directive {

static directiveName = 'roomPlanner:CommandCenter';
static color = COLOR_WHITE;
static secondaryColor = COLOR_PURPLE;

constructor(flag: Flag) {
super(flag);
}

init(): void {
this.colony.roomPlanner.addComponent('bunker', this.pos, this.memory.rotation);
}

run(): void {

}
}

7 changes: 6 additions & 1 deletion src/overlords/situational/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import {Tasks} from '../../tasks/Tasks';
import {OverlordPriority} from '../../priorities/priorities_overlords';
import {profile} from '../../profiler/decorator';

export const EmergencyMinerSetup = new CreepSetup('drone', {
pattern : [WORK, WORK, CARRY, MOVE],
sizeLimit: 1,
});

export const FillerSetup = new CreepSetup('filler', {
pattern : [CARRY, CARRY, MOVE],
sizeLimit: 1,
Expand Down Expand Up @@ -58,7 +63,7 @@ export class BootstrappingOverlord extends Overlord {
creep => creep.getActiveBodyparts(WORK)));
if (miningPowerAssigned < overlord.miningSite.miningPowerNeeded &&
filteredMiners.length < overlord.miningSite.pos.availableNeighbors().length) {
let protoCreep = this.generateProtoCreep(MinerSetup);
let protoCreep = this.generateProtoCreep(EmergencyMinerSetup);
protoCreep.memory.overlord = overlord.ref; // Donate the miner to the miningSite
if (this.colony.hatchery) {
this.colony.hatchery.enqueue(protoCreep, this.priority);
Expand Down
12 changes: 10 additions & 2 deletions src/roomPlanner/RoadPlanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,16 @@ export class RoadPlanner {
if (this.roomPlanner.map != {}) { // use active map
roomPlannerRoads = this.roomPlanner.map[STRUCTURE_ROAD];
} else { // retrieve from memory
roomPlannerRoads = _.map(this.roomPlanner.memory.mapsByLevel[8][STRUCTURE_ROAD],
protoPos => derefRoomPosition(protoPos));
if (this.roomPlanner.memory.bunkerData && this.roomPlanner.memory.bunkerData.anchor) {
let layout = this.roomPlanner.getStructureMapForBunkerAt(this.roomPlanner.memory.bunkerData.anchor);
roomPlannerRoads = layout[STRUCTURE_ROAD] || [];
} else if (this.roomPlanner.memory.mapsByLevel) {
roomPlannerRoads = _.map(this.roomPlanner.memory.mapsByLevel[8][STRUCTURE_ROAD],
protoPos => derefRoomPosition(protoPos));
} else {
log.error(`RoadPlanner@${this.colony.room.print}: could not get road positions from room planner!`);
roomPlannerRoads = [];
}
}
let allRoadPos: RoomPosition[] = _.compact(this.roadPositions.concat(roomPlannerRoads));
// Encode the coordinates of the road as keys in a truthy hash table for fast lookup
Expand Down
100 changes: 81 additions & 19 deletions src/roomPlanner/RoomPlanner.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* Layout: plans future buildings for rooms */
// The room planner allows you to plan the location of all structures in the room semi-automatically by placing
// components with flags. This code is a little messy, sorry.

import {hatcheryLayout} from './layouts/hatchery';
import {commandCenterLayout} from './layouts/commandCenter';
import {log} from '../lib/logger/log';
Expand All @@ -9,6 +11,7 @@ import {Colony} from '../Colony';
import {RoadPlanner} from './RoadPlanner';
import {BarrierPlanner} from './BarrierPlanner';
import {BuildPriorities} from '../priorities/priorities_structures';
import {bunkerLayout} from './layouts/bunker';

export interface BuildingPlannerOutput {
name: string;
Expand Down Expand Up @@ -42,8 +45,11 @@ export interface RoomPlan {

export interface PlannerMemory {
active: boolean;
bunkerData?: {
anchor: protoPos,
};
lastGenerated?: number;
mapsByLevel: { [rcl: number]: { [structureType: string]: protoPos[] } };
mapsByLevel?: { [rcl: number]: { [structureType: string]: protoPos[] } };
savedFlags: { secondaryColor: ColorConstant, pos: protoPos, memory: FlagMemory }[];
}

Expand All @@ -58,7 +64,9 @@ export class RoomPlanner {
colony: Colony; // The colony this is for
map: StructureMap; // Flattened {structureType: RoomPositions[]} for final structure placements
placements: { // Used for generating the plan
[name: string]: RoomPosition
hatchery: RoomPosition | undefined;
commandCenter: RoomPosition | undefined;
bunker: RoomPosition | undefined;
};
plan: RoomPlan; // Contains maps, positions, and rotations of each hivecluster component
barrierPlanner: BarrierPlanner;
Expand All @@ -71,7 +79,11 @@ export class RoomPlanner {

constructor(colony: Colony) {
this.colony = colony;
this.placements = {};
this.placements = {
hatchery : undefined,
commandCenter: undefined,
bunker : undefined,
};
this.plan = {};
this.map = {};
this.barrierPlanner = new BarrierPlanner(this);
Expand Down Expand Up @@ -101,6 +113,9 @@ export class RoomPlanner {
if (this.map[structureType]) {
return this.map[structureType];
}
if (this.memory.bunkerData && this.memory.bunkerData.anchor) {
return this.getBunkerStructurePlacement(structureType, this.memory.bunkerData.anchor);
}
let roomMap = this.memory.mapsByLevel ? this.memory.mapsByLevel[8] : undefined;
if (roomMap && roomMap[structureType]) {
return _.map(roomMap[structureType], protoPos => derefRoomPosition(protoPos));
Expand Down Expand Up @@ -129,6 +144,15 @@ export class RoomPlanner {
}
}

get bunkerPos(): RoomPosition | undefined {
if (this.placements.bunker) {
return this.placements.bunker;
}
if (this.memory.bunkerData && this.memory.bunkerData.anchor) {
return new RoomPosition(this.memory.bunkerData.anchor.x, this.memory.bunkerData.anchor.y, this.colony.name);
}
}

private reactivate(): void {
// Reinstantiate flags
for (let protoFlag of this.memory.savedFlags) {
Expand Down Expand Up @@ -171,7 +195,7 @@ export class RoomPlanner {
this.map[type].push(pos);
}

addComponent(componentName: string, pos: RoomPosition, rotation = 0): void {
addComponent(componentName: 'hatchery' | 'commandCenter' | 'bunker', pos: RoomPosition, rotation = 0): void {
this.placements[componentName] = pos;
}

Expand All @@ -182,6 +206,8 @@ export class RoomPlanner {
return hatcheryLayout;
case 'commandCenter':
return commandCenterLayout;
case 'bunker':
return bunkerLayout;
}
}

Expand All @@ -192,11 +218,11 @@ export class RoomPlanner {
let layout = this.getLayout(name);
if (layout) {
let anchor: Coord = layout.data.anchor;
let pos = this.placements[name];
let rotation: number = pos.lookFor(LOOK_FLAGS)[0]!.memory.rotation || 0;
let pos = this.placements[<'hatchery' | 'commandCenter' | 'bunker'>name];
let rotation: number = pos!.lookFor(LOOK_FLAGS)[0]!.memory.rotation || 0;
let componentMap = this.parseLayout(layout, level);
this.translateComponent(componentMap, anchor, pos);
if (rotation != 0) this.rotateComponent(componentMap, pos, rotation);
this.translateComponent(componentMap, anchor, pos!);
if (rotation != 0) this.rotateComponent(componentMap, pos!, rotation);
plan[name] = {
map : componentMap,
pos : new RoomPosition(anchor.x, anchor.y, this.colony.name),
Expand Down Expand Up @@ -268,6 +294,24 @@ export class RoomPlanner {
}
}

/* Get bunker building placements as a StructureMap */
getStructureMapForBunkerAt(anchor: { x: number, y: number }, level = 8): StructureMap {
let dx = anchor.x - bunkerLayout.data.anchor.x;
let dy = anchor.y - bunkerLayout.data.anchor.y;
let structureLayout = _.mapValues(bunkerLayout[level]!.buildings, obj => obj.pos) as { [s: string]: Coord[] };
return _.mapValues(structureLayout, coordArr =>
_.map(coordArr, coord => new RoomPosition(coord.x + dx, coord.y + dy, this.colony.name)));
}

/* Get the placement for a single type of structure for bunker layout */
getBunkerStructurePlacement(structureType: string, anchor: { x: number, y: number },
level = 8): RoomPosition[] {
let dx = anchor.x - bunkerLayout.data.anchor.x;
let dy = anchor.y - bunkerLayout.data.anchor.y;
let structureLayout = _.mapValues(bunkerLayout[level]!.buildings, obj => obj.pos) as { [s: string]: Coord[] };
return _.map(bunkerLayout[level]!.buildings[structureType].pos,
coord => new RoomPosition(coord.x + dx, coord.y + dy, this.colony.name));
}

/* Generates a list of impassible obstacles from this.map or from this.memory.map */
getObstacles(): RoomPosition[] {
Expand All @@ -280,10 +324,19 @@ export class RoomPlanner {
}
}
} else { // else, serialize from memory
for (let structureType in this.memory.mapsByLevel[8]) {
if (!passableStructureTypes.includes(structureType)) {
obstacles = obstacles.concat(_.map(this.memory.mapsByLevel[8][structureType],
protoPos => derefRoomPosition(protoPos)));
if (this.memory.bunkerData && this.memory.bunkerData.anchor) {
let structureMap = this.getStructureMapForBunkerAt(this.memory.bunkerData.anchor);
for (let structureType in structureMap) {
if (!passableStructureTypes.includes(structureType)) {
obstacles = obstacles.concat(structureMap[structureType]);
}
}
} else if (this.memory.mapsByLevel) {
for (let structureType in this.memory.mapsByLevel[8]) {
if (!passableStructureTypes.includes(structureType)) {
obstacles = obstacles.concat(_.map(this.memory.mapsByLevel[8][structureType],
protoPos => derefRoomPosition(protoPos)));
}
}
}
}
Expand Down Expand Up @@ -315,10 +368,15 @@ export class RoomPlanner {
let layoutIsValid: boolean = !!this.placements.commandCenter && !!this.placements.hatchery;
if (layoutIsValid) { // Write everything to memory
// Generate maps for each rcl
this.memory.mapsByLevel = {};
for (let rcl = 1; rcl <= 8; rcl++) {
this.make(rcl);
this.memory.mapsByLevel[rcl] = this.map;
delete this.memory.bunkerData;
if (this.placements.bunker) {

} else {
this.memory.mapsByLevel = {};
for (let rcl = 1; rcl <= 8; rcl++) {
this.make(rcl);
this.memory.mapsByLevel[rcl] = this.map;
}
}
// Finalize the barrier planner
this.barrierPlanner.finalize();
Expand Down Expand Up @@ -367,8 +425,12 @@ export class RoomPlanner {
// Max buildings that can be placed each tick
let count = RoomPlanner.settings.maxSitesPerColony - this.colony.constructionSites.length;
// Recall the appropriate map
this.map = _.mapValues(this.memory.mapsByLevel[this.colony.controller.level], posArr =>
_.map(posArr, protoPos => derefRoomPosition(protoPos)));
if (this.memory.bunkerData && this.memory.bunkerData.anchor) {
this.map = this.getStructureMapForBunkerAt(this.memory.bunkerData.anchor);
} else if (this.memory.mapsByLevel) {
this.map = _.mapValues(this.memory.mapsByLevel[this.colony.controller.level], posArr =>
_.map(posArr, protoPos => derefRoomPosition(protoPos)));
}
if (!this.map) { // in case a map hasn't been generated yet
log.info(this.colony.name + ' does not have a room plan yet! Unable to build missing structures.');
}
Expand Down

0 comments on commit d652d7e

Please sign in to comment.