Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
elicwhite opened this issue Jul 22, 2016 · 13 comments
Closed

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

elicwhite opened this issue Jul 22, 2016 · 13 comments

Comments

@elicwhite
Copy link
Contributor

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?

@tstumm
Copy link
Contributor

tstumm commented Jul 22, 2016

A more modular approach would be nice, but configuration should be more easy. It is "just" Pokemon Go, it is not that complex that we need full "if this than that" configuration.

@PokemonGoF
Copy link
Collaborator

PR are welcomed :)

@jtdroste
Copy link
Contributor

I disagree with @tstumm, this is a great idea. I'd add an optional "weight" param though, so we can set the order which tasks execute.

@elicwhite
Copy link
Contributor Author

elicwhite commented Jul 22, 2016

@jtdroste I'm thinking that to start the order will be the order in the tasks array. The old WoW bot had the ability to set the ordering though. It kinda made it confusing for people because multiple tasks could be configured with the same weights which made it not very clear. Here is an example configuration. This was pre json: http://pastebin.com/EjFt6L3E

@tstumm
Copy link
Contributor

tstumm commented Jul 22, 2016

@jtdroste So you disagree with easy configuration? If you do "if this than that" you easily have an overly complex configuration. Ordering by position in configuration seems a good approach for me.

@elicwhite
Copy link
Contributor Author

@douglascamata I thing nearly everything could be implemented as a task. For example, a RestForSoftBan task that people would put early in the list and it would simply wait and keep the rest of the things from executing. Or maybe it would be configured to use that time to walk to a certain location instead of just standing still.

Tasks provide clean, standalone, drop in functionality decoupled from everything else around it.

@elicwhite
Copy link
Contributor Author

Some recommended reading to understand decision trees more broadly, and then it goes into how they are implemented. I want to make sure people understand the system well enough to be able to make an informed decision on whether this is the approach the bot should take before writing out a lot of code for this.

http://guineashots.com/2014/07/25/an-introduction-to-behavior-trees-part-1/

@TCB13
Copy link

TCB13 commented Jul 24, 2016

If you really let the config be JSON files it would be a very nice and welcome addition!! Other older (XML?) bulkier / more complex formats are just not worth it.

@thellimist
Copy link

thellimist commented Jul 25, 2016

@TheSavior I agree with the task logic but I think the config file shouldn't be structured liket that. The bot should be designed easy enough for non-technical people to figure it out. Having every setting in a single config file is just too overwhelming. Also it creates lots of merge conflicts.

A better approach would be having a main config file just for the simple stuff like API Keys and for stuff which can have default settings they would be grouped in a in a folder in seperate json files. The separation would lead settings advance feature a lot easier.

Your example will eventually be have so many features it'll look like this

{
    "tasks": [
        {
            "type": "TransferPokemon",
            "arguments": {
                "minimumRemainingSlots": 10,
                "minimumCP": 100,
                "ignorePokemon": [......]
            }
        }, {
            "type": "CatchPokemon",
            "arguments": {
                "greatBallCP": 300,
                "ultraBallCP": 500,
            }
        }, {
            "type": "ClearBag",
            "arguments": {
                "minimumRemainingSlots": 5,
                "itemStructure": {
                    "minPokeBallLimit": 50,
                    "minReviveLimit": 5,
                   ...
               }
            }
        }, {
            type: "SpinPokestops"
        }, {
            type: "WalkToLocations",
            arguments: {
                "locations": [
                    "40.781362, -73.969046", 
                    "41.781362, -73.969046", 
                    "42.781362, -73.969046", 
                    "43.781362, -73.969046", 
                    "44.781362, -73.969046", 
                    "45.768075, -73.976339",
                    ...
                ]
            }
        }
    ]
}

All of these task will have complicated settings since some people will need them and they'll add. We should make the core structure simple and support really complex plugins with a good structure.

A good way to balance complex plugin support is having default settings set for everyone of them and only the users who need those features will take a look and change the settings. Also every configuration file should have their own documentation inside the code with comments

@codybaldwin
Copy link
Contributor

Also, imagine how easy it would be to create a GUI to set these configurations and run the bot.

@elicwhite
Copy link
Contributor Author

@thellimist: The configuration file will only require the configuration for the tasks they are using. But it also defines the order in which they want the tasks to run. I could imagine a complicated task like ReleasePokemon having an argument that defines another json file it loads more configuration from such as what we have in release_config right now.

@mommy742
Copy link

mommy742 commented Aug 3, 2016

question and this might be stupid but since me and my brother set up the bot I wanna try to use the advanced config setting to see if I can make a better setup pattern for the bot so: how do you use and control advanced config settings because me and my brother are sort of lost on this part and my brother is a computer programmer. so any help? thanks ^-^ and sorry for asking a maybe stupid question.

@elicwhite
Copy link
Contributor Author

@mommy742 Using the example config.json file should help you get pointed in the right direction. If you need help beyond that, your best bet is asking the lovely people that hang out in slack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants