Skip to content

Refactoring Proposal: Behavior Trees, Tasks, and Plugins #142

@elicwhite

Description

@elicwhite

Problems:
It is hard to configure the bot the way each person wants.
It is hard for engineers to add / extend the functionality of the bot
As this bot grows, there isn't great separation of behavior, causing additional complexity and problems with merge conflicts.

Solution:
Previous bots for games like World of Warcraft have grown to huge heights by being easily configurable, extensible, and easy to understand. The classic solution to this is to implement the bot core as a configurable behavior tree.

The basics are actually pretty straight forward in this case.

Imagine there are tasks like this:

ClearBag
TransferPokemon
CatchPokemon
SpinPokestops
WalkToLocations
WalkToNearestPokestop

These tasks would be implemented as classes that have a run method.

We could then read in a configuration file that people can write which defines how the bot runs. This would make it significantly easier to configure than adding more cli flags.

I imagine people could then write configs like this:

{
    "tasks": [
        {
            "type": "TransferPokemon",
            "arguments": {
                "minimumRemainingSlots": 10,
                "minimumCP": 100
            }
        }, {
            "type": "CatchPokemon",
            "arguments": {
                "greatBallCP": 300,
                "ultraBallCP": 500,
            }
        }, {
            "type": "ClearBag",
            "arguments": {
                "minimumRemainingSlots": 5
            }
        }, {
            type: "SpinPokestops"
        }, {
            type: "WalkToLocations",
            arguments: {
                "locations": [
                    "40.781362, -73.969046", 
                    "40.768075, -73.976339"
                ]
            }
        }
    ]
}

The tool would take the configuration, instantiate an instance of the task type for each element in the tasks array passing the configuration arguments to the constructor. It then uses a game loop, essentially a while loop that on each tick iterates through each task calling run.

By putting tasks higher in the task list, it essentially says it is a higher priority.

In the example above it is saying that it needs to make sure there is space in the pokebox before catching pokemon, space in the bag before spinning pokestops, and it should catch the pokemon around before starting to move in the direction of another location.

By doing this, we can enable other people to create repos that implement new tasks that can be more complex and swapped in for other things, and those classes can be extended as well.

I'm curious what people's thoughts are on this. Is this a direction people would want to go?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions