Most of my previous posts have focused on a single aspect of my bot development. This is not one of those posts.
Over the last few months since my last post, Overmind has evolved considerably as I’ve added a ton of new features to my bot (read: 22k new lines of code). While none of them were individually as technically challenging or original as the logistics system to warrant their own post, I figured I’d make this post a show-and-tell session for some of the new features I’ve been working on.
The classic “box and flower” layout (like the one in this post) was designed primarily with logistics in mind. Having a physically separated “hatchery” (spawning block) and “command center” (storage block) allows for you to place the central dropoff point for resources closer to the ideal location that minimizes total path length to nearby sources without being constrained by the full bulk of the base. This design served this purpose well, but it suffered from two key defensive flaws: the tower spread reduces total tower damage at siege points, and the spawning rate can be limited by the hatchery link bandwidth.
Enter bunkers. Bunker assets have been sitting in the AI for a long time, but living next to everyone’s friendly neighborhood tiger forced me to prioritize their development one he figured out how to exploit the flaws of my previous layout. The final design went through a lot of iterations, but I’m quite happy with how it turned out. Here’s an annotated image of a fully-developed base:
Each bunker has three permanent attendants: a manager and two queens. Managers are stationary 16-CARRY 0-MOVE creeps that sit in the center of each bunker, connecting the storage, terminal, central link, and RCL8 structures. Queens are general-purpose base attendants which fill and empty structures requesting any type of resource.
Managers are relatively unchanged in bunker colonies and are run by the same overlord as in the classic layout. The most notable difference is that managers for RCL8 bunkers are immobile (a design choice enabled by some improvements to my creep spawning code), spending their entire life at the central “anchor” tile of the bunker. If there are ramparts within range 3 of the anchor below their target hits, the manager will be spawned with 32 WORK parts and will fortify the ramparts when it is idling.
Although they share the same role name as the hatchery attendants in the classic layout, queens are run by a separate overlord in bunker-type colonies, which features a large number of hard-coded optimizations specific to the bunker layout. Each “quadrant” (group of contiguous buildings) in the bunker has a hard-coded fill order (illustrated in the above image) to minimize walking distance, and each queen gets assigned two quadrants and a “battery” (the top and bottom containers in the bunker, which serve as an energy buffer). To further reduce the CPU cost, rather than executing the fill logic after every transfer, queens are assigned a single chained task object which represents an entire “manifest” of supply operations which can be done with the creep’s carry capacity. (The chained task also sets the
nextPos property of each subtask to ensure that the queen promptly moves to her next destination so no ticks are wasted idling between tasks.)
The task-chaining logic and the generality of the logistics system makes handling requests for multiple resources in a single carry quite straightforward. So in bunker-type colonies, queens are double-purposed as lab attendants (a job handled by the manager in the classic layout). A nice feature of my bunker layout is that every spawn has a lab adjacent to it, meaning that creeps can be boosted while they are still spawning! This helps to reduce congestion within the base and maximizes the boosted lifetime of the creeps.
Another quirk of my new layout is that at RCL8, only 51 of the available 60 extensions are built in the main bunker. Having only 51 extensions significantly improves the compactness of the design while still allowing for one exit on each side. The remaining extensions will be placed next to “dropoff” links in the room (links not claimed by a miningSite or upgradeSite) and will be filled by idle transporters. In the event of a siege where the links and external extensions could easily be destroyed, 51 extensions poses almost no limitation to the types of defensive creeps which can be spawned, as the colony could still spawn the most expensive healer creeps with 38-HEAL, 12-MOVE bodies.
If bunkers’ greatest strength is the high tower damage resulting from their compactness, their greatest weakness is the congestion resulting from their compactness. Making bunkers work required some massive improvement to my traffic management code and resulted in a completely new movement library. (Previously, I used Traveler; my new library uses some of the same code under the hood but adds a number of new features and integrates more tightly with the Overmind framework.)
All creeps in my AI now have a role-dependent movement priority, and they will push slower or blocking creeps with lesser move priority out of their way. In general, this results in the two creeps switching locations, but if the blocking creep is performing a task (such as a worker blocking a pathway while sitting in the base fortifying a rampart), it will try to move to a position that is out of the way and still in range of its task target. This allows for some pretty cool behavior like this:
Even if creeps are able to fluidly move past each other, another complication with bunkers is that groups of creeps clogging the alleyways can result in baby creeps being unable to exit their spawns. This is a particularly pronounced issue with my design, as each spawn has only two exit tiles. To solve this, I implemented a
vacatePos method which recursively pushes creeps down alleyways and blocks further movement attempts for that tick to vacate the target position.
“Exceptional” terminal logic
Switching base layouts across most of my colonies without evacuating energy and minerals prior to demolition would mean a lot of wasted resources! Fortunately, my terminal network has improved a lot over the last few months, and introducing terminal “exception states” to my terminal network was a nice solution to this problem.
If everything is functioning normally, the terminal network works by equalizing resource amounts for energy and base minerals between rooms. On top of this, terminals can request resources from the network for boosting or lab production. The highest priority treatment are reserved for terminals which are in exception states. If a terminal is in an exception state (determined by the presence of an appropriate directive at the terminal position), it is removed from the list of terminals which undergo normal operation and is given priority treatment, evacuating and/or requesting resources in decreasing order of value.
Exception states have proven to be pretty handy for a variety of uses: the emergency state maintains a constant supply of energy and T3 boosts to fight off enemies during a siege; the rebuild state evacuates all minerals and keeps a small constant energy supply behind while a room is rebuilding itself; and the evacuate state is triggered when a room is about to fall after a failed defense, evacuating all resources from the room to prevent them from falling into enemy hands.
We require more minerals!
Overmind v0.4 finally added long-overdue fully automatic mineral mining, processing, trading, and boosting capabilities. Colonies now automatically start mining minerals once at RCL6. Minerals are transferred between colonies as needed for resource production. Excess minerals are sold on the market, and once a player reaches a credit threshold, missing base minerals required for resource production are purchased from the market. Labs (managed by the
EvolutionChamber object) automatically cycle through reaction queues to build up a stockpile of prioritized resources. Reaction cycles are planned by the
Colony.abathur object, which recursively generates needed reaction queues to produce the highest priority needed compound. When creeps request to get boosted, the necessary resources are transferred to the appropriate colony automatically, or, if the player has sufficient credits, they are be bought on the market if not present.
Overmind v0.5 is the first release capable of fully automatic operation! One of the biggest challenges in achieving this milestone was figuring out a system to determine approximately optimal base layouts. Fortunately, making the switch to bunkers simplified this process considerably.
There are three new modules which facilitate this process. The
BasePlanner analyzes a room to figure out if and where a bunker can be placed. If there are many possible “anchor” positions, small sample is randomly chosen, and the position with the minimum total path length to points of interest within the room (sources and controller) is returned. The
ExpansionPlanner looks at a room and a given anchor position (from BasePlanner) and determines a score (roughly, energy per tick) for the room and possible nearby mining outposts. Periodically, the scores for a room are re-computed by the
RoomIntel module, and the best score to-date and corresponding anchor position is recorded in the room memory. Over time, this results in a semi-optimal choice of bunker placement. Finally, the new
Strategist module looks at possible rooms to colonize and chooses the one with the highest score, as long as it is not too close or too far from another colony. (Eventually, the Strategist will be responsible for other high-level decision making, but for now it only does room expansion.)
Of course, this system is still quite new and has many improvements that can be made to it, but (even rudimentary) full autonomy a big milestone in the development of my bot.
Let’s end on a cliffhanger
In a previous blog post, I talked about the remaining boxes I wanted to check off before releasing version 1.0 of my bot. At this point, the boxes are all checked (with checkmarks of various messiness), and the next release will be Overmind v1.0.
So what happens now? Well, there are three major things I want to polish before release.
First, I need to restructure parts of the AI to be more CPU efficient. I am currently fairly limited by CPU, as I have been holding out on making some much needed improvements for the devs to release persistent game objects. I’ll likely hold out until the promised PTR content in late August, but if persistent game objects aren’t included, I’ll start to develop an emulator for them myself.
Second, I want to write proper military code. I do have passable defense and offense code in place already, but my combat code has always lagged behind my economics code. I’ve added a lot of the framework for fully automatic combat over the last few months, including distributed spawning and combat movement, but I have yet to properly plug it all in.
Finally, I have something special that will define the 1.0 release. (You might have heard about it already in the #overmind Slack channel.) I won’t spoil the surprise yet, but in the words of my favorite Westworld character, “It’s something I’ve been working on for quite some time… Something quite original.”