ilpersi / BHBot

A bot that automates a game called Bit Heroes
GNU General Public License v3.0
28 stars 32 forks source link

Configuring activity priority #84

Closed Fortigate closed 5 years ago

Fortigate commented 5 years ago

I would like to add a feature to change activity selection from the current method (doRaids 1 etc) to system similar to the autoFunctions (doActivity r t g d) running the activities in the configured order.

The current system has a static order so if you are doing a shard basket run the bot will ignore energy/tokens until the shards have been depleted. I've set up the settings code to load the string, but can't work out how to remove the activity functions from the main loop and select them from the settings file in a clean manner, anyone have some time to look at this? I'll upload the settings side code I wrote later on

eschwim commented 5 years ago

I've been thinking along similar lines, actually. I was thinking about prioritizing activities based on the percentage of "fuel" there is available. If two activities were at (or above) 100% you could randomly choose one of them. This should keep the majority of the focus on a single activity when doing large raid/exped runs.

The difficulty I can see with this approach is that you would have to continuously poll the "hidden" fuels (shards/badges) to keep accurate counts.

Fortigate commented 5 years ago

Polling should be built in due to the scheduler already, if you are burning energy packs with the current build the bot will use available shards and tokens first as they are before energy in the main loop and then continually use energy until the 'TOKENS/TRIALS_CHECK_INTERVAL' has been met, then it will check those resources again before continuing to use energy.

ilpersi commented 5 years ago

I have an idea on how to make this work. If I understand correctly you want all the activities to be always run in the order they are defined in activitysEnabled regardless of the fuels.

So for example if you are doing a shard basked and in settings.ini you have activitysEnabled t w r you always want to run

  1. one trial
  2. one world boss
  3. one raid
  4. restart from point 1

@Fortigate Am I correct?

ilpersi commented 5 years ago

I am out of town without a reliable internet connection, so I pushed my idea in a dedicate branch for you to check it out.

Fortigate commented 5 years ago

I was thinking more of a priority list, with the current timer system still in place;

1, Clear Tokens, then 2, Clear Energy activity, then 3, Clear Shards, etc

With the timer still activating a check on activities higher in the priority list.

I think I can make something with the Iterator and a timer check, will test it and upload

ilpersi commented 5 years ago

Whatever you decide to do, it should be optional. I prefer the bot to steady consume all the fuels, not just one.

What I want to avoid is that, for example, while I am doing one or more shard baskets, the tokens get to 100% and they don't regen anymore because they are not used while the bot is focusing on shards.

Fortigate commented 5 years ago

This is what I'm trying to solve, so that if you are doing a raid basket burn you can configure the activity order to stop other resources from capping. Currently I have to stop the bot intermittently to disable raids and use the other resources manually.

I'll keep it in the test branch while we're looking at it, but I imagine it will replace the current system, as it will function the same as it does now, but with an adjustable order.

Fortigate commented 5 years ago

Working test code is in the branch, I tested it yesterday with a badge burn and with Expedition as the lowest priority it worked as expected, periodically checking all higher priority resources when the timers where met before returning to badges. Can you try it and let me know if you have reservations about replacing the current system?

ilpersi commented 5 years ago

I am having a busy period lately, I should be able to get some free time in the upcoming week end to look at it.

Anyway, as it is a modification of the core logic, it will probably require extended tests.

Fortigate commented 5 years ago

No rush for it, I've had the code running on my accounts for a week now with no issues. I've got one last change to make (separating trials/gauntlet timer) and I consider it ready, but would appreciate a second set of eyes on it to see if there's a more logical way to do it.

ilpersi commented 5 years ago

@Fortigate can you please merge the latest master changes in the activitysEnabled branch? This would help me to review your code.

I wanted to do this by myself and, as there are some conflicts and overlapping changes in the two brances, your help would be really appreciated. :)

Fortigate commented 5 years ago

Merged, sorry for the mess between the branches!

ilpersi commented 5 years ago

Much more easy now! :)

In the end, the logic you have now is the same as my original proposal: the only difference is that you centralized the logic in the activitySelector method and this can be an interesting idea. There are a couple of issues though:

  1. https://github.com/Betalord/BHBot/blob/activitysEnabled/src/main/java/MainThread.java#L3089 here you always initialize the iterator, so you will always have the same element ('r' for raid, the first in the list). Look at my original propnose and you you will see that the iterator is initialized only when required (no more elements to iterate)
  2. activitySelector may return null and there are no failsafe for this. At the moment this is not an issue because of point 1: you will always get the first element of the list
  3. now that I fully understand your requirement a simple iterator is not enough. The iterator only allows you to a) centralize the doXXXX settings in one place (and I prefer to have them separate) b) manage the order in which the activities are performed and c) make sure that all the fuel are used with a "circular" logic.

Using the simple iterator you can make it so that all the fuels are consumed regardless of any bonus you use. If you want to focus on the highest fuel (shards for example) and avoid to cap other fuels a much deeper review of the logic is required. My approach would probably be to poll the resources at the begin and the use a weighted random selection with the RandomCollection class updating the weights every time a dungeon is over.

Last but not least: I also see some unrelated fishing commits in the activitysEnabled is there a reason for this? As there may be some important changes to the core, I think that is better to only use the activitySelector branch for scheduling logic modifications.

Fortigate commented 5 years ago

I think there's some misunderstanding about what I'm trying to achieve here, it's not a round-robin check through the list of given activities, but a priority list using the iterator and time checks.

  1. This is intended, each time we call activitySelector we start from the top (highest priority) and work through the list until we find an activity that matches (both timer and resource amount) then pick that activity. When we complete an activity and there are not enough resources left resetAppropriateTimers() does not reset the timer, and so activitySelector will not check the resource again until that timer is met.

  2. Also intended, when we have scanned through the list and there are no activities available we return null (and so idle) until one of the conditions in activitySelector is met and we check the resource again.

3a, It is still possible to remove activities by removing them from the list, this method feels more in line with the way that we select other activities than doXXXX 0/1 3b/c. It does feel that another method would be easier, I tried with a for loop but had difficulties with it not returning and matching Strings.

Lastly, that was laziness on my part, I'd had any idea for getting fishing to work for a while (in a very hacky fashion) and since I was actively committing to the activitySelector branch and testing it on my accounts I put it in there to test alongside. I'll try and keep better etiquette on the on project :)

Let me know what you think.

ilpersi commented 5 years ago

Ok, I hope to get it right this time. 😄

So in the end, with the current logic if I use a shard basket, the bot will perform only raids till the box is fully consumed, am I correct?

One more thing: I've spent a lot of time fixing the latest commits with the new worldboss setting format and merging changes between branches instead of testing this. Please please please, make sure you double-check your commits before pushing them. 🙏🙏

Fortigate commented 5 years ago

If r was at the front of the activity list it would have priority and while shards where available other activities wouldn't be checked, correct.

If you moved r to the end of the list the checks for other resources would take precedence and those would be run until we reached raids, and after each raid they higher priority tasks would be checked if the activity timer had been met to see if they could be run.

Apologies on the worldBoss settings mess, I was testing the master branch last night with the same commits to the checks but didn't push the changes.

ilpersi commented 5 years ago

It is not how I would like it, as I would prefer the round robin strategy to always be sure that no resource is capped. It is not an issue though, we can go this way and add the round robin strategy in a second time (I also have an idea on how to).

If you want to merge the branch in the master one, I am fine with it: we can release it in v41 (more tests and tweaks are yet required) and it will be easier for all of us to manage commits.

Fortigate commented 5 years ago

Ahhh I think finally understand, it'd be better to have round robin so that no manual configuration of the activity order is necessary to prevent resource capping? If so I'll revert the branch to that and merge it into the master branch, if necessary we can revisit it later on.

ilpersi commented 5 years ago

I am fine with how it is now: there is still room to revisit it later. If you are fine also, go on with the merge.

ilpersi commented 5 years ago

Managing two branches was too time-consuming, so I did the merge into master.