From a1433f235c0afc00a15d79ff99711c0cd520dc7f Mon Sep 17 00:00:00 2001 From: reddivision Date: Fri, 29 Jul 2016 01:01:58 -0700 Subject: [PATCH] Moved egg hatching to incubation worker, added feedback for users (#1568) --- CONTRIBUTORS.md | 1 + README.md | 4 +- pokemongo_bot/__init__.py | 1 - .../cell_workers/incubate_eggs_worker.py | 165 ++++++++++++------ 4 files changed, 116 insertions(+), 55 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 09ec6ccfc7..005c5d5727 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -41,3 +41,4 @@ * surceis * SpaceWhale * klingan + * reddivision diff --git a/README.md b/README.md index 6ea0b8e8e7..e11526f42e 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ We use [Slack](https://slack.com) as a web chat. [Click here to join the chat!]( - [x] Ignore certain pokemon filter - [x] Adjust delay between Pokemon capture & Transfer as per configuration - [ ] Standalone Desktop Application -- [ ] Hatch eggs -- [ ] Incubate eggs +- [x] Hatch eggs +- [x] Incubate eggs - [ ] Use candy - [ ] Inventory cleaner diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index 518c4a33ee..19133cb9a6 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -491,7 +491,6 @@ def heartbeat(self): in self.fort_timeouts.iteritems() if timeout >= time.time() * 1000} self.api.get_player() - self.api.get_hatched_eggs() self.api.check_awarded_badges() self.api.call() self.update_web_location() # updates every tick diff --git a/pokemongo_bot/cell_workers/incubate_eggs_worker.py b/pokemongo_bot/cell_workers/incubate_eggs_worker.py index 44370b3cb6..9459988dd3 100644 --- a/pokemongo_bot/cell_workers/incubate_eggs_worker.py +++ b/pokemongo_bot/cell_workers/incubate_eggs_worker.py @@ -1,66 +1,127 @@ -from utils import distance, format_dist from pokemongo_bot.human_behaviour import sleep from pokemongo_bot import logger - class IncubateEggsWorker(object): + last_km_walked = 0 + def __init__(self, bot): - self.api = bot.api - self.config = bot.config self.bot = bot - # self.position = bot.position + self.ready_incubators = [] + self.used_incubators = [] + self.eggs = [] + self.km_walked = 0 + self.hatching_animation_delay = 4.20 def work(self): - if not self.config.hatch_eggs: + if not self.bot.config.hatch_eggs: return - response_dict = self.bot.get_inventory() - inv = {} - incubators = [] - eggs = [] - try: - inv = reduce(dict.__getitem__, [ - "responses", "GET_INVENTORY", "inventory_delta", "inventory_items"], response_dict) - except KeyError: - pass - else: - for inv_data in inv: - inv_data = inv_data.get("inventory_item_data", {}) - - if "egg_incubators" in inv_data: - for incubator in inv_data.get("egg_incubators", {}).get("egg_incubator", []): - if "pokemon_id" not in incubator: - incubators.append({"id":incubator.get("id", -1), "used":False}) - - if "pokemon_data" in inv_data: - pokemon = inv_data.get("pokemon_data", {}) - if pokemon.get("is_egg", False) and "egg_incubator_id" not in pokemon: - eggs.append({"id": pokemon.get("id", -1), "km": pokemon.get("egg_km_walked_target", -1), "used": False}) - - sorting = self.config.longer_eggs_first - eggs.sort(key=lambda x: x.get("km"), reverse=sorting) - - for incubator in incubators: - if incubator["used"]: - continue + self._check_inventory() + except: + return + + if self.used_incubators and IncubateEggsWorker.last_km_walked!=self.km_walked: + self.used_incubators.sort(key=lambda x: x.get("km")) + km_left = self.used_incubators[0]['km']-self.km_walked + if km_left<=0: + self._hatch_eggs() + else: + logger.log('[x] Next egg incubates in {:.2f} km'.format(km_left),'yellow') + IncubateEggsWorker.last_km_walked = self.km_walked + + sorting = self.bot.config.longer_eggs_first + self.eggs.sort(key=lambda x: x.get("km"),reverse=sorting) + + if self.ready_incubators: + self._apply_incubators() - for egg in eggs: - if egg["used"] or egg["km"] == -1: - continue + def _apply_incubators(self): + for incubator in self.ready_incubators: + for egg in self.eggs: + if egg["used"] or egg["km"] == -1: + continue + if self.bot.config.debug: + logger.log('[x] Attempting to apply incubator {} to egg {}'.format(incubator['id'],egg['id'])) + self.bot.api.use_item_egg_incubator(item_id=incubator["id"], pokemon_id=egg["id"]) + ret = self.bot.api.call() + if ret: + code = ret.get("responses", {}).get("USE_ITEM_EGG_INCUBATOR", {}).get("result", 0) + if code == 1: + logger.log('[x] Now incubating a ' + str(egg["km"]) + "km egg", 'green') + egg["used"] = True + incubator["used"] = True + break + elif code == 5 or code == 7: + if self.bot.config.debug: + logger.log('[x] Incubator already in use') + incubator["used"] = True + break + elif code == 6: + if self.bot.config.debug: + logger.log('[x] Egg already incubating') + egg["used"] = True - self.api.use_item_egg_incubator(item_id=incubator["id"], pokemon_id=egg["id"]) - ret = self.api.call() - if ret: - code = ret.get("responses", {}).get("USE_ITEM_EGG_INCUBATOR", {}).get("result", 0) - if code == 1: - logger.log('Successfully incubated a ' + str(egg["km"]) + "km egg", 'green') - egg["used"] = True - incubator["used"] = True - break - elif code == 5 or code == 7: - incubator["used"] = True - break - elif code == 6: - egg["used"] = True + def _check_inventory(self,lookup_ids=[]): + inv = {} + response_dict = self.bot.get_inventory() + matched_pokemon = [] + inv = reduce(dict.__getitem__, ["responses", "GET_INVENTORY", "inventory_delta", "inventory_items"], response_dict) + for inv_data in inv: + inv_data = inv_data.get("inventory_item_data", {}) + if "egg_incubators" in inv_data: + incubators = inv_data.get("egg_incubators", {}).get("egg_incubator",[]) + if isinstance(incubators, basestring): # checking for old response + incubators = [incubators] + for incubator in incubators: + if 'pokemon_id' in incubator: + self.used_incubators.append({"id":incubator.get('id', -1), "km":incubator.get('target_km_walked', 9001)}) + else: + self.ready_incubators.append({"id":incubator.get('id',-1)}) + continue + if "pokemon_data" in inv_data: + pokemon = inv_data.get("pokemon_data", {}) + if pokemon.get("is_egg", False) and "egg_incubator_id" not in pokemon: + self.eggs.append({"id": pokemon.get("id", -1), "km": pokemon.get("egg_km_walked_target", -1), "used": False}) + elif 'is_egg' not in pokemon and pokemon['id'] in lookup_ids: + matched_pokemon.append({"pokemon_id":pokemon.get('pokemon_id',-1),"cp":pokemon.get('cp',-1),"iv":[pokemon.get('individual_attack',-1), + pokemon.get('individual_stamina',-1), + pokemon.get('individual_defense',-1)]}) + continue + if "player_stats" in inv_data: + self.km_walked = inv_data.get("player_stats", {}).get("km_walked", 0) + return matched_pokemon + def _hatch_eggs(self): + self.bot.api.get_hatched_eggs() + response_dict = self.bot.api.call() + log_color = 'green' + try: + result = reduce(dict.__getitem__, ["responses", "GET_HATCHED_EGGS"], response_dict) + except KeyError: + return + if 'pokemon_id' in result: + pokemon_ids = [id for id in result['pokemon_id']] + stardust = result.get('stardust_awarded', 0) + candy = result.get('candy_awarded', 0) + xp = result.get('experience_awarded', 0) + sleep(self.hatching_animation_delay) + self.bot.latest_inventory = None + try: + pokemon_data = self._check_inventory(pokemon_ids) + except: + pass # just proceed with what we have + for pokemon in pokemon_data: + pokemon['name'] = self.bot.pokemon_list[(pokemon['pokemon_id']-1)]['Name'] # pokemon ids seem to be offset by one + logger.log("-"*30,log_color) + logger.log("[!] {} eggs hatched! Received:".format(len(pokemon_data)), log_color) + for i in range(len(pokemon_data)): + logger.log("-"*30,log_color) + logger.log("[!] Pokemon: {}".format(pokemon_data[i]['name']),log_color) + logger.log("[!] CP: {}".format(pokemon_data[i]['cp']),log_color) + logger.log("[!] IV: {}".format("/".join(map(str,pokemon_data[i]['iv']))),log_color) + logger.log("[!] XP: {}".format(xp[i]),log_color) + logger.log("[!] Stardust: {}".format(stardust[i]),log_color) + logger.log("[!] Candy: {}".format(candy[i]),log_color) + logger.log("-"*30,log_color) + \ No newline at end of file