-
Notifications
You must be signed in to change notification settings - Fork 159
Framework overview
Most of the content in this Wiki page is adapted from a longer blog post I wrote about redesigning Overmind. Some of the links in this article point to specific points in past commits; content may have changed.
I’ll explain the main components of the AI in decreasing order of hierarchy, but first, a brief glossary:
- Overmind: the top-level object that contains and runs colonies and wraps all game objects
- Colony: groups together rooms and their objects into a single unit and instantiates HiveClusters
- HiveCluster, (Wiki page): groups together structures with related functionality and their logic
- Directive: a wrapper for a flag with contextual behavior changes
- Overlord: handles creep spawning and control for a specific goal; can be plopped on any of the above three objects
- Overseer: tracks directives and overlords as they are instantiated and runs them by priority; places new directives to respond to stimuli
-
Task (Wiki page): a customizable object which you can hand to a creep with
creep.task = Tasks.X
; generalizes the notion of “do action X to thing Y until condition Z is met” - Zerg: task- and overlord-contextualized wrapper for a creep
Excluding memory checking and sandbox code, there are three major phases in each tick:
-
build()
: All caching and object instantiation is done in this phase. Colonies and their overlords are instantiated, then colonies instantiate their hive clusters and their overlords. Finally, directives and their overlords are instantiated. (See the Overlords Wiki page for more on this.) -
init()
: This phase handles all pre-state-changing actions, primarily various requests like creep spawning requests and transport and link requests. -
run()
: This is where the action happens. All state-changing actions happen here; most will require information that is populated in the init() phase. HiveClusters will look through their various requests to determine what actions should be taken (spawning the highest priority creep(s) from the requests, loading/unloading the storage link, etc.). Overlords will scan through their Zerg and assign new tasks through a decision tree to each one that isIdle, such as maintaining a miningSite, determining which structures to supply, or hauling back energy from a remote source. The Overseer examines each room to look for any anomalous conditions, such as an invasion or a colony crash, and responds by placing Directives accordingly.
The main idea behind colonies and hive clusters is to organize what belongs to what in a hierarchical manner based on what each object is instantiated by. Colonies are instantiated by an owned room and a list of outpost rooms (determined by directives) and organize these rooms into a single unit. HiveClusters are instantiated by a RoomObject belonging to a colony and group multiple structures and components together which share related functionality. Both Colonies and HiveClusters can have overlords put on them.
Directives are on the same hierarchical level as HiveClusters, but they are a little different, since the colony does not directly instantiate them. They are instantiated from flags by the Overmind and assigned to a colony based on their location. Directives don’t have much internal logic (some will remove themselves, but that’s about as complex as it gets right now) but their main function is to be a conditional attachment point for overlords. Directives are categorized by color codes, with the primary color indicating a category and a secondary color indicating the specific type. See the color codes wiki page for more detail.
An Overlord is a generalization of a set of related things that need to be done in a colony like mining from a site, bootstrapping a new colony, guarding against invaders, or building construction sites. Overlords handle spawning or obtaining suitable creeps to do these things and contain the actual implementation of doing them, replacing the messy Objective
system in the older AI. If HiveClusters are the organs of a colony, Overlords are the biological processes which make those organs function.
One of the biggest (and hardest) design decisions I had to make with this rewrite was how to handle instantiation of Overlords. Initially, I was drawn toward using directives as the only instantiation method, such that every process in a colony would have its own flag. However, I decided against this idea for two reasons: (1) it seemed to be unnecessary and unintuitive to use directives for normal operation (HiveClusters would need to be changed to be instantiated from flags, which is against their design, or would have a split cluster-directive nature which I didn’t like) and (2) there is speculation that the flag cap may eventually be lowered from 10,000 to 100, so I don’t want to rely on flags too heavily.
Eventually, I decided that an overlord can be instantiated from anything that has the following properties:
-
name
: for generating unique Overlord references -
room
: an Overlord handles operations which primarily take place in one room -
pos
: Overlords must be instantiated from a physical object -
colony
: for assigning which colony handles the spawn requests (I added a self-referencing Colony.colony property so that Colonies could instantiate Overlords as well) -
memory
: Overlord memory is stored ininstantiator.memory.overlords[this.ref]
This allows Overlords to be instantiated from a Colony, HiveCluster, or Directive, which makes them a very versatile control model. Colony overlords are for constant, colony-wide operations, like handling workers to build new things. HiveCluster overlords are more specialized but still always present, like spawning miners for a site or a dedicated Hatchery attendant. Directive overlords tend to be conditional, like guarding against NPC invaders or claiming a new room.
When an Overlord is instantiated with a specified priority, it automatically adds itself to a priority queue on the colony Overseer
. The Overseer is responsible for running all Directives and Overlords, as well as placing new Directives to respond to various stimuli.