Skip to content

Refactor recommendation for Structure.isActive #140

@CarsonBurke

Description

@CarsonBurke

Why?

The existing isActive function has two main problems. Firstly, it is incredibly inefficient for its goal, sorting structures by range to controller simply to determine which structures a player can use while the controller is downgraded. Secondly, and far more notably, the code has a chance to return false information to a bot! This seems to happen because there are multiple calls to isActive - a function with pseudo-random return order - for two different situations. First is when the engine runs this to determine which structures it will allow interaction with, and second is when the user runs it to determine which structures they can interact with. So, for example, when two extensions have the same range to the controller, the engine vs user calls to isActive can determine a different extension to be not active.

image
image (12)

Here you can see a non-parallel determination of isActive states between the user and engine calls. (compare the energyAvail to energyCapacity in the console to the 800 energy in what are supposed to be active extensions + spawn)

Nikolay and I agreed there needs to be a fully deterministic solution to address this issue, so enough selling, what can be done?

Solution

Both the Room.structureOfType and Structure.buildOrder properties do not need to be exposed to users for this logic to function. Only the game engine needs access to them.

  • An ideally persistent Room.structuresOfType: {[key: StructureTypes]: number} is used to record the number of structures each structureType in the room. So a count for extensions, spawns, etc.
  • Each structure has a persistent buildOrder: number, a record of what order the structure is in relative to other structures of the same structureType
  • When a structure is destroyed
    • If the buildOrder is not equal to the structure's structureType, splice the buildOrder: loop through each structure of the same structureType and, if their buildOrder is more than that of the structure that is being deleted, decrement their buildOrder by 1
    • decrease the count for the structureType by 1
  • When a structure is built
    • increase the structuresOfType for the new structure's structureType
    • the new structure is assigned the lowest unique build order possible (should just be the current Room.structuresOfType[newStructure.structureType]
  • For existing structures not yet integrated with this new system
    • Simply loop through each structure and apply the "When a structure is built" logic to them
  • When isActive is called
    • As a guard clause to avoid running the entire algorithm, check if the number of structures of the structureType in question is more than the max structures the current RCL can support. If it is not, the structure is definitively active.
    • Loop through each structure of the structureType in question. Record inActive for every structure with a buildOrder less or equal to the max structures the current RCL can support.
    • It can now be a linear search, and is entirely deterministic! This should speed up the algorithm by at least 10x, at the cost of some extra Room and Structure properties. It also fixes the energyAvail/energyCapacity discrepancy bug, which should be a big priority considering it affects many users.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions