From b5acdd5f3394f7de40926cacfd2ca35ae019cad4 Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 14:29:04 +0200 Subject: [PATCH 01/17] Adding Gym Cell Worker to deal with Gym Messages --- pokemongo_bot/cell_workers/gym_pokemon.py | 673 ++++++++++++++++++++++ 1 file changed, 673 insertions(+) create mode 100644 pokemongo_bot/cell_workers/gym_pokemon.py diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py new file mode 100644 index 0000000000..638de267de --- /dev/null +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -0,0 +1,673 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals +from __future__ import absolute_import + +from datetime import datetime, timedelta +import sys +import time +import random +from random import uniform +from collections import Counter + +from pgoapi.utilities import f2i +from pokemongo_bot import inventory +from pokemongo_bot.inventory import player + +from pokemongo_bot.constants import Constants +from pokemongo_bot.human_behaviour import action_delay, sleep +from pokemongo_bot.worker_result import WorkerResult +from pokemongo_bot.base_task import BaseTask +from pokemongo_bot import inventory +from .utils import distance, format_time, fort_details, format_dist +from pokemongo_bot.tree_config_builder import ConfigException +from pokemongo_bot.walkers.walker_factory import walker_factory +from pokemongo_bot.inventory import Pokemons + +GYM_DETAIL_RESULT_SUCCESS = 1 +GYM_DETAIL_RESULT_OUT_OF_RANGE = 2 +GYM_DETAIL_RESULT_UNSET = 0 + +TEAM_BLUE = 1 +TEAM_RED = 2 +TEAM_YELLOW = 3 + +TEAMS = { + 1: "Mystic", + 2: "Valor", + 3: "Instinct" +} + +ITEM_RAZZBERRY = 701 +ITEM_NANABBERRY = 703 +ITEM_PINAPBERRY = 705 + + +class GymPokemon(BaseTask): + SUPPORTED_TASK_API_VERSION = 1 + + def __init__(self, bot, config): + super(GymPokemon, self).__init__(bot, config) + + def initialize(self): + # 10 seconds from current time + self.next_update = datetime.now() + timedelta(0, 10) + self.order_by = self.config.get('order_by', 'cp') + self.min_interval = self.config.get('min_interval', 60) + self.min_recheck = self.config.get('min_recheck', 30) + self.max_recheck = self.config.get('max_recheck', 120) + self.recheck = datetime.now() + self.walker = self.config.get('walker', 'StepWalker') + self.destination = None + self.recent_gyms = [] + self.pokemons = [] + self.fort_pokemons = [] + self.expire_recent = 10 + self.next_expire = None + self.dropped_gyms = [] + self.blacklist= [] + self.check_interval = 0 + self.gyms = [] + self.raid_gyms = dict() + self.team = self.bot.player_data['team'] + + def should_run(self): + # Check if we have any Pokemons and are level > 5 + return player()._level >= 5 and len(self.pokemons) > 0 + + def display_fort_pokemon(self): + if len(self.fort_pokemons) == 0: + return + self.logger.info("We currently have %s Pokemon in Gym(s)" % len(self.fort_pokemons) ) + for pokemon in self.fort_pokemons: + lat = self.bot.position[0:2][0] + lng = self.bot.position[0:2][1] + details = fort_details(self.bot, pokemon.fort_id, lat, lng) + fort_name = details.get('name', 'Unknown') + self.logger.info("%s: %s (%s CP)" % (fort_name, pokemon.name, pokemon.cp)) + + def work(self): + self.pokemons = inventory.pokemons().all() + self.fort_pokemons = [p for p in self.pokemons if p.in_fort] + self.pokemons = [p for p in self.pokemons if not p.in_fort] + + self.dropped_gyms = [] + for pokemon in self.fort_pokemons: + self.dropped_gyms.append(pokemon.fort_id) + + if self._should_print(): + self.display_fort_pokemon() + self._compute_next_update() + # Do display teh stats about Pokemon in Gym and collection time [please] + if not self.enabled: + return WorkerResult.SUCCESS + if self.bot.softban: + return WorkerResult.SUCCESS + + if len(self.fort_pokemons) >= 20: + if self._should_print(): + self.logger.info("We have a max of 20 Pokemon in gyms.") + return WorkerResult.SUCCESS + + if hasattr(self.bot, "hunter_locked_target") and self.bot.hunter_locked_target is not None: + # Don't move to a gym when hunting for a Pokemon + return WorkerResult.SUCCESS + + if self.destination is None: + self.check_close_gym() + + if not self.should_run(): + return WorkerResult.SUCCESS + + if self.destination is None: + self.determin_new_destination() + + if self.destination is not None: + result = self.move_to_destination() + # Can return RUNNING to move to a gym + return result + + + return WorkerResult.SUCCESS + + def check_close_gym(self): + # Check if we are walking past a gym + close_gyms = self.get_gyms_in_range() + # Filter active raids from the gyms + close_gyms = filter(lambda gym: gym["id"] not in self.raid_gyms, close_gyms) + + if len(close_gyms) > 0: + # self.logger.info("Walking past a gym!") + for gym in close_gyms: + if gym["id"] in self.dropped_gyms: + continue + + gym_details = self.get_gym_details(gym) + if gym_details: + pokes = self._get_pokemons_in_gym(gym_details) + if len(pokes) == 6: + continue + if 'enabled' in gym: + if not gym['enabled']: + continue + if 'owned_by_team' in gym: + if gym["owned_by_team"] == self.team: + # self.feed_pokemons_in_gym(gym) + + if 'gym_display' in gym: + display = gym['gym_display'] + if 'slots_available' in display: + self.logger.info("Gym has %s open spots!" % display['slots_available']) + if display['slots_available'] > 0 and gym["id"] not in self.dropped_gyms: + self.logger.info("Dropping pokemon in %s" % gym_details["name"]) + self.drop_pokemon_in_gym(gym, pokes) + if self.destination is not None and gym["id"] == self.destination["id"]: + self.destination = None + return WorkerResult.SUCCESS + else: + self.logger.info("Neutral gym? %s" % gym) + self.logger.info("Dropping pokemon in %s" % gym_details["name"]) + self.drop_pokemon_in_gym(gym, []) + if self.destination is not None and gym["id"] == self.destination["id"]: + self.destination = None + return WorkerResult.SUCCESS + + def determin_new_destination(self): + gyms = self.get_gyms() + if len(gyms) == 0: + if len(self.recent_gyms) == 0 and self._should_print(): + self.logger.info("No Gyms in range to scan!") + return WorkerResult.SUCCESS + + self.logger.info("Inspecting %s gyms." % len(gyms)) + self.logger.info("Recent gyms: %s" % len(self.recent_gyms)) + self.logger.info("Active raid gyms: %s" % len(self.raid_gyms)) + teams = [] + for gym in gyms: + # Ignore after done for 5 mins + self.recent_gyms.append(gym["id"]) + + if 'enabled' in gym: + # Gym can be closed for a raid or something, skipp to the next + if not gym['enabled']: + continue + + if 'owned_by_team' in gym: + if gym["owned_by_team"] == 1: + teams.append("Mystic") + elif gym["owned_by_team"] == 2: + teams.append("Valor") + elif gym["owned_by_team"] == 3: + teams.append("Instinct") + # else: + # self.logger.info("Unknown team? %s" % gym) + + if gym["owned_by_team"] == self.team: + if 'gym_display' in gym: + display = gym['gym_display'] + if 'slots_available' in display: + self.logger.info("Gym has %s open spots!" % display['slots_available']) + self.destination = gym + break + else: + # self.logger.info("Found a Neutral gym?") + # self.logger.info("Info: %s" % gym) + self.destination = gym + break + if len(teams) > 0: + count_teams = Counter(teams) + self.logger.info("Gym Teams %s", ", ".join('{}({})'.format(key, val) for key, val in count_teams.items())) + + def move_to_destination(self): + if self.check_interval >= 4: + self.check_interval = 0 + gyms = self.get_gyms() + for g in gyms: + if g["id"] == self.destination["id"]: + # self.logger.info("Inspecting target: %s" % g) + if "owned_by_team" in g and g["owned_by_team"] is not self.team: + self.logger.info("Damn! Team %s took gym before we arrived!" % TEAMS[g["owned_by_team"]]) + self.destination = None + return WorkerResult.SUCCESS + break + else: + self.check_interval += 1 + + # Moving to a gym to deploy Pokemon + unit = self.bot.config.distance_unit # Unit to use when printing formatted distance + lat = self.destination["latitude"] + lng = self.destination["longitude"] + details = fort_details(self.bot, self.destination["id"], lat, lng) + gym_name = details.get('name', 'Unknown') + + dist = distance( + self.bot.position[0], + self.bot.position[1], + lat, + lng + ) + noised_dist = distance( + self.bot.noised_position[0], + self.bot.noised_position[1], + lat, + lng + ) + + moving = noised_dist > Constants.MAX_DISTANCE_FORT_IS_REACHABLE if self.bot.config.replicate_gps_xy_noise else dist > Constants.MAX_DISTANCE_FORT_IS_REACHABLE + + if moving: + fort_event_data = { + 'fort_name': u"{}".format(gym_name), + 'distance': format_dist(dist, unit), + } + self.emit_event( + 'moving_to_fort', + formatted="Moving towards Gym {fort_name} - {distance}", + data=fort_event_data + ) + + step_walker = walker_factory(self.walker, self.bot, lat, lng) + + if not step_walker.step(): + return WorkerResult.RUNNING + else: + self.emit_event( + 'arrived_at_fort', + formatted=("Arrived at Gym %s." % gym_name) + ) + gym_details = self.get_gym_details(self.destination) + current_pokemons = self._get_pokemons_in_gym(gym_details) + self.drop_pokemon_in_gym(self.destination, current_pokemons) + # Feed the Pokemon now we're here... + # self.feed_pokemons_in_gym(self.destination) + self.destination = None + # Look around if there are more gyms to fill + self.determin_new_destination() + # If there is none, we're done, else we go to the next! + if self.destination is None: + return WorkerResult.SUCCESS + else: + return WorkerResult.RUNNING + + def get_gym_details(self, gym): + lat = gym['latitude'] + lng = gym['longitude'] + + in_reach = False + + if self.bot.config.replicate_gps_xy_noise: + if distance(self.bot.noised_position[0], self.bot.noised_position[1], gym['latitude'], gym['longitude']) <= Constants.MAX_DISTANCE_FORT_IS_REACHABLE: + in_reach = True + else: + if distance(self.bot.position[0], self.bot.position[1], gym['latitude'], gym['longitude']) <= Constants.MAX_DISTANCE_FORT_IS_REACHABLE: + in_reach = True + + if in_reach: + request = self.bot.api.create_request() + request.gym_get_info(gym_id=gym['id'], gym_lat_degrees=lat, gym_lng_degrees=lng, player_lat_degrees=self.bot.position[0],player_lng_degrees=self.bot.position[1]) + response_dict = request.call() + + if ('responses' in response_dict) and ('GYM_GET_INFO' in response_dict['responses']): + details = response_dict['responses']['GYM_GET_INFO'] + return details + else: + return False + # details = fort_details(self.bot, , lat, lng) + # fort_name = details.get('name', 'Unknown') + # self.logger.info("Checking Gym: %s (%s pts)" % (fort_name, gym['gym_points'])) + + def _get_pokemons_in_gym(self, gym_details): + pokemon_names = [] + gym_info = gym_details.get('gym_status_and_defenders', None) + if gym_info: + defenders = gym_info.get('gym_defender', []) + for defender in defenders: + motivated_pokemon = defender.get('motivated_pokemon') + pokemon_info = motivated_pokemon.get('pokemon') + pokemon_id = pokemon_info.get('pokemon_id') + pokemon_names.append(Pokemons.name_for(pokemon_id)) + + return pokemon_names + + def feed_pokemons_in_gym(self, gym): + berries = inventory.items().get(ITEM_RAZZBERRY).count + (inventory.items().get(ITEM_PINAPBERRY).count - 10) + inventory.items().get(ITEM_NANABBERRY).count + if berries < 1: + self.logger.info("No berries left to feed Pokemon.") + return True + + max_gym_time = timedelta(hours=8,minutes=20) + gym_info = self.get_gym_details(gym).get('gym_status_and_defenders', None) + # self.logger.info("Defenders in gym:")okemon_info..items()get('pokemon_id') + if gym_info: + defenders = gym_info.get('gym_defender', []) + for defender in defenders: + motivated_pokemon = defender.get('motivated_pokemon') + pokemon_info = motivated_pokemon.get('pokemon') + pokemon_id = pokemon_info.get('pokemon_id') + # timestamp when deployed + deployed_on = datetime.fromtimestamp(int(motivated_pokemon.get('deploy_ms')) / 1e3) + time_deployed = datetime.now() - deployed_on + # % of motivation + current_motivation = motivated_pokemon.get('motivation_now') + + # Let's see if we should feed this Pokemon + if time_deployed < max_gym_time and current_motivation < 1.0: + # Let's feed this Pokemon a candy + # self.logger.info("This pokemon deserves a candy") + berry_id = self._determin_feed_berry_id(motivated_pokemon) + poke_id = pokemon_info.get('id') + quantity = pokemon_info.get('num_upgrades') + self._feed_pokemon(gym, poke_id, berry_id, quantity) + + def _determin_feed_berry_id(self, motivated_pokemon): + # # Store the amount of berries we have + razzb = inventory.items().get(ITEM_RAZZBERRY).count + pinap = inventory.items().get(ITEM_PINAPBERRY).count + nanab = inventory.items().get(ITEM_NANABBERRY).count + missing_motivation = 1.0 - motivated_pokemon.get('motivation_now') + # Always allow feeding with RAZZ and NANAB + allowed_berries = [] + if razzb > 0: + allowed_berries.append(ITEM_RAZZBERRY) + + if nanab > 0: + allowed_berries.append(ITEM_NANABBERRY) + + if pinap > 10: + allowed_berries.append(ITEM_PINAPBERRY) + + food_values = motivated_pokemon['food_value'] + # Only check the berries we wish to feed + food_values = [f for f in food_values if f['food_item'] in allowed_berries] + # Sort by the least restore first + sorted(food_values, key=lambda x: x['motivation_increase']) + + for food_value in food_values: + if food_value['motivation_increase'] >= missing_motivation: + # We fully restore CP with this berry! + return food_value['food_item'] + # Okay, we can't completely fill the CP for the pokemon, get the best berry then NO GOLDEN + return food_values[-1]['food_item'] + + def _feed_pokemon(self, gym, pokemon_id, berry_id, quantity): + request = self.bot.api.create_request() + request.gym_feed_pokemon( + starting_quantity=quantity, + item_id=berry_id, + gym_id=gym["id"], + pokemon_id=pokemon_id, + player_lat_degrees=f2i(self.bot.position[0]), + player_lng_degrees=f2i(self.bot.position[1]) + ) + response_dict = request.call() + if ('responses' in response_dict) and ('GYM_FEED_POKEMON' in response_dict['responses']): + feeding = response_dict['responses']['GYM_FEED_POKEMON'] + result = feeding.get('result', -1) + self.logger.info("Feeding: %s" % feeding) + if result == 1: + # Succesful feeding + self.logger.info("Fed a Pokemon!") + else: + self.logger.info("Feeding failed! %s" % result) + + def drop_pokemon_in_gym(self, gym, current_pokemons): + self.pokemons = inventory.pokemons().all() + self.fort_pokemons = [p for p in self.pokemons if p.in_fort] + self.pokemons = [p for p in self.pokemons if not p.in_fort] + close_gyms = self.get_gyms_in_range() + + empty_gym = False + + for pokemon in self.fort_pokemons: + if pokemon.fort_id == gym["id"]: + self.logger.info("We are already in this gym!") + if pokemon.fort_id not in self.dropped_gyms: + self.dropped_gyms.append(pokemon.fort_id) + self.recent_gyms.append(gym["id"]) + return WorkerResult.SUCCESS + + for g in close_gyms: + if g["id"] == gym["id"]: + if 'owned_by_team' in g: + self.logger.info("Expecting team: %s it is: %s" % (self.bot.player_data['team'], g["owned_by_team"]) ) + if g["owned_by_team"] is not self.team: + self.logger.info("Can't drop in a enemy gym!") + self.recent_gyms.append(gym["id"]) + return WorkerResult.SUCCESS + else: + self.logger.info("Empty gym?? %s" % g) + gym_details = self.get_gym_details(gym) + self.logger.info("Details: %s" % gym_details) + empty_gym = True + if not gym_details or gym_details == {}: + self.logger.info("No details for this Gym? Blacklisting!") + self.blacklist.append(gym["id"]) + return WorkerResult.SUCCESS + + # Check for raid + if 'raid_info' in gym: + raid_info = gym["raid_info"] + raid_starts = datetime.fromtimestamp(int(raid_info["raid_battle_ms"]) / 1e3) + raid_ends = datetime.fromtimestamp(int(raid_info["raid_end_ms"]) / 1e3) + self.logger.info("Raid starts: %s" % raid_starts.strftime('%Y-%m-%d %H:%M:%S.%f')) + self.logger.info("Raid ends: %s" % raid_ends.strftime('%Y-%m-%d %H:%M:%S.%f')) + t = datetime.today() + + if raid_starts < datetime.now(): + self.logger.info("Active raid?") + if raid_ends < datetime.now(): + self.logger.info("No need to wait.") + elif (raid_ends-t).seconds > 600: + self.logger.info("Need to wait long than 10 minutes, skipping") + self.destination = None + self.recent_gyms.append(gym["id"]) + self.raid_gyms[gym["id"]] = raid_ends + return WorkerResult.SUCCESS + else: + while raid_ends > datetime.now(): + self.logger.info("Waiting for %s seconds for raid to end..." % (raid_ends-datetime.today()).seconds) + if (raid_ends-datetime.today()).seconds > 20: + sleep(20) + else: + sleep((raid_ends-datetime.today()).seconds) + break + else: + self.logger.info("Raid has not begun yet!") + + if 'same_team_deploy_lockout_end_ms' in gym: + # self.logger.info("%f" % gym["same_team_deploy_lockout_end_ms"]) + org_time = int(gym["same_team_deploy_lockout_end_ms"]) / 1e3 + lockout_time = datetime.fromtimestamp(org_time) + t = datetime.today() + + if lockout_time > datetime.now(): + self.logger.info("Lockout time: %s" % lockout_time.strftime('%Y-%m-%d %H:%M:%S.%f')) + while lockout_time > datetime.now(): + self.logger.info("Waiting for %s seconds deployment lockout to end..." % (lockout_time-datetime.today()).seconds) + if (lockout_time-datetime.today()).seconds > 20: + sleep(20) + else: + sleep((lockout_time-t).seconds) + break + + #FortDeployPokemon + # self.logger.info("Trying to deploy Pokemon in gym: %s" % gym) + gym_details = self.get_gym_details(gym) + # self.logger.info("Gym details: %s" % gym_details) + fort_pokemon = self._get_best_pokemon(current_pokemons) + pokemon_id = fort_pokemon.unique_id + # self.logger.info("Trying to deploy %s (%s)" % (fort_pokemon, pokemon_id)) + # self.logger.info("Gym in control by %s. I am on team %s" % (gym["owned_by_team"], self.bot.player_data['team'])) + + request = self.bot.api.create_request() + request.gym_deploy( + fort_id=gym["id"], + pokemon_id=pokemon_id, + player_lat_degrees=f2i(self.bot.position[0]), + player_lng_degrees=f2i(self.bot.position[1]) + ) + # self.logger.info("Req: %s" % request) + response_dict = request.call() + # self.logger.info("Called deploy pokemon: %s" % response_dict) + + if ('responses' in response_dict) and ('GYM_DEPLOY' in response_dict['responses']): + deploy = response_dict['responses']['GYM_DEPLOY'] + result = response_dict.get('status_code', -1) + self.recent_gyms.append(gym["id"]) + # self.logger.info("Status: %s" % result) + if result == 1: + self.dropped_gyms.append(gym["id"]) + gym_details = self.get_gym_details(gym) + # SUCCES + self.logger.info("We deployed %s (%s CP) in the gym! We now have %s Pokemon in gyms!" % (fort_pokemon.name, fort_pokemon.cp, len(self.dropped_gyms))) + self.emit_event( + 'deployed_pokemon', + formatted=("We deployed %s (%s CP) in the gym %s!!" % (fort_pokemon.name, fort_pokemon.cp, gym_details["name"])), + data={'gym_id': gym['id'], 'pokemon_id': pokemon_id} + ) + return WorkerResult.SUCCESS + elif result == 2: + #ERROR_ALREADY_HAS_POKEMON_ON_FORT + self.logger.info('ERROR_ALREADY_HAS_POKEMON_ON_FORT') + self.dropped_gyms.append(gym["id"]) + return WorkerResult.ERROR + elif result == 3: + #ERROR_OPPOSING_TEAM_OWNS_FORT + self.logger.info('ERROR_OPPOSING_TEAM_OWNS_FORT') + return WorkerResult.ERROR + elif result == 4: + #ERROR_FORT_IS_FULL + self.logger.info('ERROR_FORT_IS_FULL') + return WorkerResult.ERROR + elif result == 5: + #ERROR_NOT_IN_RANGE + self.logger.info('ERROR_NOT_IN_RANGE') + return WorkerResult.ERROR + elif result == 6: + #ERROR_PLAYER_HAS_NO_TEAM + self.logger.info('ERROR_PLAYER_HAS_NO_TEAM') + return WorkerResult.ERROR + elif result == 7: + #ERROR_POKEMON_NOT_FULL_HP + self.logger.info('ERROR_POKEMON_NOT_FULL_HP') + return WorkerResult.ERROR + elif result == 8: + #ERROR_PLAYER_BELOW_MINIMUM_LEVEL + self.logger.info('ERROR_PLAYER_BELOW_MINIMUM_LEVEL') + return WorkerResult.ERROR + elif result == 8: + #ERROR_POKEMON_IS_BUDDY + self.logger.info('ERROR_POKEMON_IS_BUDDY') + return WorkerResult.ERROR + + def get_gyms(self, skip_recent_filter=False): + if len(self.gyms) == 0: + self.gyms = self.bot.get_gyms(order_by_distance=True) + + if self._should_recheck(): + self.gyms = self.bot.get_gyms(order_by_distance=True) + self._compute_next_recheck() + + if self._should_expire(): + self.recent_gyms = [] + self._compute_next_expire() + # Check raid gyms for raids that ended + for gym_id in list(self.raid_gyms.keys()): + if self.raid_gyms[gym_id] < datetime.now(): + self.logger.info("Raid at %s ended (%s)" % (gym_id, self.raid_gyms[gym_id])) + del(self.raid_gyms[gym_id]) + + gyms = [] + # if not skip_recent_filter: + gyms = filter(lambda gym: gym["id"] not in self.recent_gyms, self.gyms) + # Filter blacklisted gyms + gyms = filter(lambda gym: gym["id"] not in self.blacklist, gyms) + # Filter out gyms we already in + gyms = filter(lambda gym: gym["id"] not in self.dropped_gyms, gyms) + # Filter ongoing raids + gyms = filter(lambda gym: gym["id"] not in self.raid_gyms, gyms) + # filter fake gyms + # self.gyms = filter(lambda gym: "type" not in gym or gym["type"] != 1, self.gyms) + # sort by current distance + gyms.sort(key=lambda x: distance( + self.bot.position[0], + self.bot.position[1], + x['latitude'], + x['longitude'] + )) + + return gyms + + def get_gyms_in_range(self): + gyms = self.get_gyms() + + if self.bot.config.replicate_gps_xy_noise: + gyms = filter(lambda fort: distance( + self.bot.noised_position[0], + self.bot.noised_position[1], + fort['latitude'], + fort['longitude'] + ) <= Constants.MAX_DISTANCE_FORT_IS_REACHABLE, self.gyms) + else: + gyms = filter(lambda fort: distance( + self.bot.position[0], + self.bot.position[1], + fort['latitude'], + fort['longitude'] + ) <= Constants.MAX_DISTANCE_FORT_IS_REACHABLE, self.gyms) + + return gyms + + def _should_print(self): + return self.next_update is None or datetime.now() >= self.next_update + + def _should_expire(self): + return self.next_expire is None or datetime.now() >= self.next_expire + + def _compute_next_expire(self): + self.next_expire = datetime.now() + timedelta(seconds=300) + + def _compute_next_recheck(self): + wait = uniform(self.min_recheck, self.max_recheck) + self.recheck = datetime.now() + timedelta(seconds=wait) + + def _should_recheck(self): + return self.recheck is None or datetime.now() >= self.recheck + + def _compute_next_update(self): + """ + Computes the next update datetime based on the minimum update interval. + :return: Nothing. + :rtype: None + """ + self.next_update = datetime.now() + timedelta(seconds=self.min_interval) + + def _get_best_pokemon(self, current_pokemons): + def get_poke_info(info, pokemon): + poke_info = { + 'cp': pokemon.cp, + 'iv': pokemon.iv, + 'ivcp': pokemon.ivcp, + 'ncp': pokemon.cp_percent, + 'level': pokemon.level, + 'hp': pokemon.hp, + 'dps': pokemon.moveset.dps + } + if info not in poke_info: + raise ConfigException("order by {}' isn't available".format(self.order_by)) + return poke_info[info] + # Don't place a Pokemon which is already in the gym (prevent ALL Blissey etc) + possible_pokemons = [p for p in self.pokemons if not p.name in current_pokemons] + # Don't put in Pokemon above 3000 cp (morale drops too fast) + possible_pokemons = [p for p in possible_pokemons if p.cp < 3000] + # Filter out "bad" Pokemon + possible_pokemons = [p for p in possible_pokemons if not p.is_bad] + # HP Must be max + possible_pokemons = [p for p in possible_pokemons if p.hp == p.hp_max] + possible_pokemons = [p for p in possible_pokemons if not p.in_fort] + # Sort them + pokemons_ordered = sorted(possible_pokemons, key=lambda x: get_poke_info(self.order_by, x), reverse=True) + # Top 10 picks + pokemons_ordered = pokemons_ordered[0:20] + # Pick a random one! + random.shuffle(pokemons_ordered) + return pokemons_ordered[0] From 5f6b963a90cc6437f666e2476150d8dc097dc53b Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 14:36:52 +0200 Subject: [PATCH 02/17] Enable GymPokemon worker This makes sure that we can use the GymPokemon worker to do things for us. --- pokemongo_bot/cell_workers/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pokemongo_bot/cell_workers/__init__.py b/pokemongo_bot/cell_workers/__init__.py index a08e45da4a..e72eb0d477 100644 --- a/pokemongo_bot/cell_workers/__init__.py +++ b/pokemongo_bot/cell_workers/__init__.py @@ -34,3 +34,4 @@ from .catch_limiter import CatchLimiter from .update_hash_stats import UpdateHashStats from .bad_pokemon import BadPokemon +from .gym_pokemon import GymPokemon \ No newline at end of file From 5953744a09e60275ce9a6cb8bf5c057a586af5a8 Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 15:02:20 +0200 Subject: [PATCH 03/17] Making sure that the event of deploying a mon is shown in green --- pokemongo_bot/event_handlers/logging_handler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pokemongo_bot/event_handlers/logging_handler.py b/pokemongo_bot/event_handlers/logging_handler.py index c873cc7a0f..62bf2b3ba6 100644 --- a/pokemongo_bot/event_handlers/logging_handler.py +++ b/pokemongo_bot/event_handlers/logging_handler.py @@ -128,7 +128,8 @@ class LoggingHandler(EventHandler): 'threw_pokeball': 'none', 'used_lucky_egg': 'none', 'catch_limit_on': 'yellow', - 'catch_limit_off': 'green' + 'catch_limit_off': 'green', + 'deployed_pokemon': 'green' } COLOR_CODE = { 'gray': '\033[90m', From b77af34c2b5787029a45d9c96a598d6657d2e93f Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 15:07:07 +0200 Subject: [PATCH 04/17] Share the feeding event --- pokemongo_bot/cell_workers/gym_pokemon.py | 5 +++++ pokemongo_bot/event_handlers/logging_handler.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index 638de267de..f6bfb47920 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -406,6 +406,11 @@ def _feed_pokemon(self, gym, pokemon_id, berry_id, quantity): if result == 1: # Succesful feeding self.logger.info("Fed a Pokemon!") + self.emit_event( + 'fed_pokemon', + formatted=("We fed %s in the gym %s!!" % (pokemon_id, gym_details["name"])), + data={'gym_id': gym['id'], 'pokemon_id': pokemon_id} + ) else: self.logger.info("Feeding failed! %s" % result) diff --git a/pokemongo_bot/event_handlers/logging_handler.py b/pokemongo_bot/event_handlers/logging_handler.py index 62bf2b3ba6..138b933de9 100644 --- a/pokemongo_bot/event_handlers/logging_handler.py +++ b/pokemongo_bot/event_handlers/logging_handler.py @@ -129,7 +129,8 @@ class LoggingHandler(EventHandler): 'used_lucky_egg': 'none', 'catch_limit_on': 'yellow', 'catch_limit_off': 'green', - 'deployed_pokemon': 'green' + 'deployed_pokemon': 'green', + 'fed_pokemon': 'white' } COLOR_CODE = { 'gray': '\033[90m', From 2e65068ef64354a8c729bbd2eac4ba0fed087594 Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 15:26:58 +0200 Subject: [PATCH 05/17] Adding config sample and setting correct base config --- configs/config.json.example | 11 +++++++++++ pokemongo_bot/cell_workers/gym_pokemon.py | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/configs/config.json.example b/configs/config.json.example index 8dc00c4980..b1da623b79 100644 --- a/configs/config.json.example +++ b/configs/config.json.example @@ -481,7 +481,18 @@ "diameter": 4, "step_size": 70 } + }, + { + "type": "GymPokemon", + "config": { + "enabled": false, + "order_by": "cp", + "min_interval":360, + "min_recheck":30, + "max_recheck":120 + } } + ], "map_object_cache_time": 5, "forts": { diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index f6bfb47920..65e643eeae 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -52,7 +52,7 @@ def initialize(self): # 10 seconds from current time self.next_update = datetime.now() + timedelta(0, 10) self.order_by = self.config.get('order_by', 'cp') - self.min_interval = self.config.get('min_interval', 60) + self.min_interval = self.config.get('min_interval', 360) self.min_recheck = self.config.get('min_recheck', 30) self.max_recheck = self.config.get('max_recheck', 120) self.recheck = datetime.now() @@ -671,7 +671,7 @@ def get_poke_info(info, pokemon): possible_pokemons = [p for p in possible_pokemons if not p.in_fort] # Sort them pokemons_ordered = sorted(possible_pokemons, key=lambda x: get_poke_info(self.order_by, x), reverse=True) - # Top 10 picks + # Top 20 picks pokemons_ordered = pokemons_ordered[0:20] # Pick a random one! random.shuffle(pokemons_ordered) From fba2c0421b2d2e8fa2b783d8d2414015dd110d76 Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 15:39:10 +0200 Subject: [PATCH 06/17] Update message frequency to be less chatty --- pokemongo_bot/cell_workers/gym_pokemon.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index 65e643eeae..4e53d33e08 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -405,7 +405,7 @@ def _feed_pokemon(self, gym, pokemon_id, berry_id, quantity): self.logger.info("Feeding: %s" % feeding) if result == 1: # Succesful feeding - self.logger.info("Fed a Pokemon!") + #self.logger.info("Fed a Pokemon!") self.emit_event( 'fed_pokemon', formatted=("We fed %s in the gym %s!!" % (pokemon_id, gym_details["name"])), @@ -523,7 +523,7 @@ def drop_pokemon_in_gym(self, gym, current_pokemons): self.dropped_gyms.append(gym["id"]) gym_details = self.get_gym_details(gym) # SUCCES - self.logger.info("We deployed %s (%s CP) in the gym! We now have %s Pokemon in gyms!" % (fort_pokemon.name, fort_pokemon.cp, len(self.dropped_gyms))) + #self.logger.info("We deployed %s (%s CP) in the gym! We now have %s Pokemon in gyms!" % (fort_pokemon.name, fort_pokemon.cp, len(self.dropped_gyms))) self.emit_event( 'deployed_pokemon', formatted=("We deployed %s (%s CP) in the gym %s!!" % (fort_pokemon.name, fort_pokemon.cp, gym_details["name"])), From 2a19fdb4b063c476ae8d4d00e1f92d6c6ff1ff3b Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 15:53:12 +0200 Subject: [PATCH 07/17] Allow feeding berries from Config file --- configs/config.json.example | 1 + pokemongo_bot/cell_workers/gym_pokemon.py | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/configs/config.json.example b/configs/config.json.example index b1da623b79..c96daa3a88 100644 --- a/configs/config.json.example +++ b/configs/config.json.example @@ -486,6 +486,7 @@ "type": "GymPokemon", "config": { "enabled": false, + "feed_berries": false, "order_by": "cp", "min_interval":360, "min_recheck":30, diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index 4e53d33e08..7bf1765c2c 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -55,6 +55,7 @@ def initialize(self): self.min_interval = self.config.get('min_interval', 360) self.min_recheck = self.config.get('min_recheck', 30) self.max_recheck = self.config.get('max_recheck', 120) + self.feed_berries = self.config.get('feed_berries', False) self.recheck = datetime.now() self.walker = self.config.get('walker', 'StepWalker') self.destination = None @@ -151,7 +152,7 @@ def check_close_gym(self): continue if 'owned_by_team' in gym: if gym["owned_by_team"] == self.team: - # self.feed_pokemons_in_gym(gym) + self.feed_pokemons_in_gym(self,gym) if 'gym_display' in gym: display = gym['gym_display'] @@ -278,7 +279,7 @@ def move_to_destination(self): current_pokemons = self._get_pokemons_in_gym(gym_details) self.drop_pokemon_in_gym(self.destination, current_pokemons) # Feed the Pokemon now we're here... - # self.feed_pokemons_in_gym(self.destination) + self.feed_pokemons_in_gym(self,self.destination) self.destination = None # Look around if there are more gyms to fill self.determin_new_destination() @@ -329,6 +330,10 @@ def _get_pokemons_in_gym(self, gym_details): return pokemon_names def feed_pokemons_in_gym(self, gym): + #Check if berry feeding is enabled from config + if self.feed_berries == False + return True + berries = inventory.items().get(ITEM_RAZZBERRY).count + (inventory.items().get(ITEM_PINAPBERRY).count - 10) + inventory.items().get(ITEM_NANABBERRY).count if berries < 1: self.logger.info("No berries left to feed Pokemon.") From 461cd35dd8d084e93d99af2ed91bbba1de727dc9 Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 16:02:05 +0200 Subject: [PATCH 08/17] Testing the quantity to use for feeding --- pokemongo_bot/cell_workers/gym_pokemon.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index 7bf1765c2c..e9b6f2690c 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -360,7 +360,10 @@ def feed_pokemons_in_gym(self, gym): # self.logger.info("This pokemon deserves a candy") berry_id = self._determin_feed_berry_id(motivated_pokemon) poke_id = pokemon_info.get('id') - quantity = pokemon_info.get('num_upgrades') + + #Testing to see what quantity field does. Probably just the amount of berries you want to feed + #quantity = pokemon_info.get('num_upgrades') + quantity=1 self._feed_pokemon(gym, poke_id, berry_id, quantity) def _determin_feed_berry_id(self, motivated_pokemon): From 8d416015403cbbfbf2003aed6d3c32fda62d737b Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 21:35:40 +0200 Subject: [PATCH 09/17] Adding support to find gyms in range --- pokemongo_bot/__init__.py | 19 +++++++++++++ pokemongo_bot/cell_workers/gym_pokemon.py | 27 ++++++++++++++++--- .../event_handlers/logging_handler.py | 1 + 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index 08b7b208ca..c2959134df 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -1725,6 +1725,25 @@ def get_forts(self, order_by_distance=False): )) return forts + + def get_gyms(self, order_by_distance=False): + forts = [fort + for fort in self.cell['forts'] + if 'latitude' in fort and 'type' not in fort] + # Need to filter out disabled gyms! + forts = filter(lambda x: x["enabled"] is True, forts) + forts = filter(lambda x: 'closed' not in fort, forts) + # forts = filter(lambda x: 'type' not in fort, forts) + + if order_by_distance: + forts.sort(key=lambda x: distance( + self.position[0], + self.position[1], + x['latitude'], + x['longitude'] + )) + + return forts def get_map_objects(self, lat, lng, timestamp, cellid): if time.time() - self.last_time_map_object < self.config.map_object_cache_time: diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index e9b6f2690c..36ea78309d 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -27,11 +27,13 @@ GYM_DETAIL_RESULT_OUT_OF_RANGE = 2 GYM_DETAIL_RESULT_UNSET = 0 +TEAM_NOT_SET = 0 TEAM_BLUE = 1 TEAM_RED = 2 TEAM_YELLOW = 3 TEAMS = { + 0: "Not Set", 1: "Mystic", 2: "Valor", 3: "Instinct" @@ -52,6 +54,7 @@ def initialize(self): # 10 seconds from current time self.next_update = datetime.now() + timedelta(0, 10) self.order_by = self.config.get('order_by', 'cp') + self.enabled = self.config.get('enabled', False) self.min_interval = self.config.get('min_interval', 360) self.min_recheck = self.config.get('min_recheck', 30) self.max_recheck = self.config.get('max_recheck', 120) @@ -69,11 +72,27 @@ def initialize(self): self.check_interval = 0 self.gyms = [] self.raid_gyms = dict() - self.team = self.bot.player_data['team'] + + self.bot.event_manager.register_event('gym_error') + self.bot.event_manager.register_event('fed_pokemon') + self.bot.event_manager.register_event('gym_full') + self.bot.event_manager.register_event('deployed_pokemon') + + #self.logger.info("player_date %s." % self.bot.player_data) + + try: + self.team = self.bot.player_data['team'] + except KeyError: + self.team = TEAM_NOT_SET + if self.enabled: + self.emit_event( + 'gym_error', + formatted="You have no team selected, so the module GymPokemon should be disabled" + ) def should_run(self): - # Check if we have any Pokemons and are level > 5 - return player()._level >= 5 and len(self.pokemons) > 0 + # Check if we have any Pokemons and are level > 5 and have selected a team + return player()._level >= 5 and len(self.pokemons) > 0 and self.team > TEAM_NOT_SET def display_fort_pokemon(self): if len(self.fort_pokemons) == 0: @@ -331,7 +350,7 @@ def _get_pokemons_in_gym(self, gym_details): def feed_pokemons_in_gym(self, gym): #Check if berry feeding is enabled from config - if self.feed_berries == False + if self.feed_berries == False: return True berries = inventory.items().get(ITEM_RAZZBERRY).count + (inventory.items().get(ITEM_PINAPBERRY).count - 10) + inventory.items().get(ITEM_NANABBERRY).count diff --git a/pokemongo_bot/event_handlers/logging_handler.py b/pokemongo_bot/event_handlers/logging_handler.py index 138b933de9..bb30bf8965 100644 --- a/pokemongo_bot/event_handlers/logging_handler.py +++ b/pokemongo_bot/event_handlers/logging_handler.py @@ -130,6 +130,7 @@ class LoggingHandler(EventHandler): 'catch_limit_on': 'yellow', 'catch_limit_off': 'green', 'deployed_pokemon': 'green', + 'gym_error': 'red', 'fed_pokemon': 'white' } COLOR_CODE = { From d17c4e17a69d5beef1a299fb51ee5eb4e2af5586 Mon Sep 17 00:00:00 2001 From: goedzo Date: Sat, 15 Jul 2017 02:49:39 +0200 Subject: [PATCH 10/17] Bugfixes and disabled berry feeding --- configs/config.json.example | 22 ++++---- pokemongo_bot/cell_workers/gym_pokemon.py | 65 +++++++++++++++-------- pokemongo_bot/inventory.py | 3 ++ 3 files changed, 58 insertions(+), 32 deletions(-) diff --git a/configs/config.json.example b/configs/config.json.example index c96daa3a88..f73d4beb93 100644 --- a/configs/config.json.example +++ b/configs/config.json.example @@ -464,6 +464,17 @@ "enabled": true } }, + { + "type": "GymPokemon", + "config": { + "enabled": false, + "feed_berries": false, + "order_by": "cp", + "min_interval":360, + "min_recheck":30, + "max_recheck":120 + } + }, { "type": "MoveToFort", "config": { @@ -481,17 +492,6 @@ "diameter": 4, "step_size": 70 } - }, - { - "type": "GymPokemon", - "config": { - "enabled": false, - "feed_berries": false, - "order_by": "cp", - "min_interval":360, - "min_recheck":30, - "max_recheck":120 - } } ], diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index 36ea78309d..0042025127 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -97,13 +97,11 @@ def should_run(self): def display_fort_pokemon(self): if len(self.fort_pokemons) == 0: return - self.logger.info("We currently have %s Pokemon in Gym(s)" % len(self.fort_pokemons) ) + self.logger.info("We currently have %s Pokemon in Gym(s):" % len(self.fort_pokemons) ) for pokemon in self.fort_pokemons: lat = self.bot.position[0:2][0] lng = self.bot.position[0:2][1] - details = fort_details(self.bot, pokemon.fort_id, lat, lng) - fort_name = details.get('name', 'Unknown') - self.logger.info("%s: %s (%s CP)" % (fort_name, pokemon.name, pokemon.cp)) + self.logger.info("%s (%s CP)" % (pokemon.name, pokemon.cp)) def work(self): self.pokemons = inventory.pokemons().all() @@ -117,7 +115,7 @@ def work(self): if self._should_print(): self.display_fort_pokemon() self._compute_next_update() - # Do display teh stats about Pokemon in Gym and collection time [please] + # Do display the stats about Pokemon in Gym and collection time [please] if not self.enabled: return WorkerResult.SUCCESS if self.bot.softban: @@ -128,16 +126,12 @@ def work(self): self.logger.info("We have a max of 20 Pokemon in gyms.") return WorkerResult.SUCCESS - if hasattr(self.bot, "hunter_locked_target") and self.bot.hunter_locked_target is not None: - # Don't move to a gym when hunting for a Pokemon + if not self.should_run(): return WorkerResult.SUCCESS - + if self.destination is None: self.check_close_gym() - if not self.should_run(): - return WorkerResult.SUCCESS - if self.destination is None: self.determin_new_destination() @@ -146,6 +140,9 @@ def work(self): # Can return RUNNING to move to a gym return result + if hasattr(self.bot, "hunter_locked_target") and self.bot.hunter_locked_target is not None: + # Don't move to a gym when hunting for a Pokemon + return WorkerResult.SUCCESS return WorkerResult.SUCCESS @@ -171,7 +168,7 @@ def check_close_gym(self): continue if 'owned_by_team' in gym: if gym["owned_by_team"] == self.team: - self.feed_pokemons_in_gym(self,gym) + self.feed_pokemons_in_gym(gym) if 'gym_display' in gym: display = gym['gym_display'] @@ -228,6 +225,11 @@ def determin_new_destination(self): self.logger.info("Gym has %s open spots!" % display['slots_available']) self.destination = gym break + else: + #If there are mons we can feed, check them. Note: gym_details returns false if gym is not in range. + gym_to_feed = self.get_gym_details(gym) + if gym_to_feed!=False: + self.feed_pokemons_in_gym(gym_to_feed) else: # self.logger.info("Found a Neutral gym?") # self.logger.info("Info: %s" % gym) @@ -281,7 +283,7 @@ def move_to_destination(self): } self.emit_event( 'moving_to_fort', - formatted="Moving towards Gym {fort_name} - {distance}", + formatted="Moving towards open Gym {fort_name} - {distance}", data=fort_event_data ) @@ -298,7 +300,7 @@ def move_to_destination(self): current_pokemons = self._get_pokemons_in_gym(gym_details) self.drop_pokemon_in_gym(self.destination, current_pokemons) # Feed the Pokemon now we're here... - self.feed_pokemons_in_gym(self,self.destination) + self.feed_pokemons_in_gym(self.destination) self.destination = None # Look around if there are more gyms to fill self.determin_new_destination() @@ -353,6 +355,10 @@ def feed_pokemons_in_gym(self, gym): if self.feed_berries == False: return True + #check if gym is in range. If not, gym=false + if gym == False: + return True + berries = inventory.items().get(ITEM_RAZZBERRY).count + (inventory.items().get(ITEM_PINAPBERRY).count - 10) + inventory.items().get(ITEM_NANABBERRY).count if berries < 1: self.logger.info("No berries left to feed Pokemon.") @@ -364,9 +370,11 @@ def feed_pokemons_in_gym(self, gym): if gym_info: defenders = gym_info.get('gym_defender', []) for defender in defenders: + #self.logger.info("Feed data: defender %s" % defender) + motivated_pokemon = defender.get('motivated_pokemon') pokemon_info = motivated_pokemon.get('pokemon') - pokemon_id = pokemon_info.get('pokemon_id') + pokemon_id=pokemon_info.get('id') # timestamp when deployed deployed_on = datetime.fromtimestamp(int(motivated_pokemon.get('deploy_ms')) / 1e3) time_deployed = datetime.now() - deployed_on @@ -378,12 +386,18 @@ def feed_pokemons_in_gym(self, gym): # Let's feed this Pokemon a candy # self.logger.info("This pokemon deserves a candy") berry_id = self._determin_feed_berry_id(motivated_pokemon) - poke_id = pokemon_info.get('id') + poke_id = pokemon_id #Testing to see what quantity field does. Probably just the amount of berries you want to feed - #quantity = pokemon_info.get('num_upgrades') - quantity=1 - self._feed_pokemon(gym, poke_id, berry_id, quantity) + #quantity = pokemon_info.get('num_upgrades') <- Failed + #quantity=1 <- Failed + quantity=0 + food_values = motivated_pokemon.get('food_value') + for food_value in food_values: + if food_value.get('food_item') == berry_id: + quantity = food_value.get('motivation_increase') + if quantity !=0: + self._feed_pokemon(gym, poke_id, berry_id, quantity) def _determin_feed_berry_id(self, motivated_pokemon): # # Store the amount of berries we have @@ -416,6 +430,13 @@ def _determin_feed_berry_id(self, motivated_pokemon): return food_values[-1]['food_item'] def _feed_pokemon(self, gym, pokemon_id, berry_id, quantity): + + self.logger.info("----THIS IS IN DEVELOPEMENT-----") + self.logger.info("We are feeding pokemon %s with berry %s ",pokemon_id,berry_id) + self.logger.info("Feed data: quantity %s" % quantity) + self.logger.info("----ABORTING HERE SINCE WE HAVE NOT YET FIND THE RIGHT API PARAMETERS-----") + return True + request = self.bot.api.create_request() request.gym_feed_pokemon( starting_quantity=quantity, @@ -466,9 +487,9 @@ def drop_pokemon_in_gym(self, gym, current_pokemons): self.recent_gyms.append(gym["id"]) return WorkerResult.SUCCESS else: - self.logger.info("Empty gym?? %s" % g) + #self.logger.info("Empty gym?? %s" % g) gym_details = self.get_gym_details(gym) - self.logger.info("Details: %s" % gym_details) + #self.logger.info("Details: %s" % gym_details) empty_gym = True if not gym_details or gym_details == {}: self.logger.info("No details for this Gym? Blacklisting!") @@ -515,6 +536,8 @@ def drop_pokemon_in_gym(self, gym, current_pokemons): self.logger.info("Lockout time: %s" % lockout_time.strftime('%Y-%m-%d %H:%M:%S.%f')) while lockout_time > datetime.now(): self.logger.info("Waiting for %s seconds deployment lockout to end..." % (lockout_time-datetime.today()).seconds) + #Feed any mons while we are waiting + self.feed_pokemons_in_gym(gym) if (lockout_time-datetime.today()).seconds > 20: sleep(20) else: diff --git a/pokemongo_bot/inventory.py b/pokemongo_bot/inventory.py index 49de951e78..c897961a82 100644 --- a/pokemongo_bot/inventory.py +++ b/pokemongo_bot/inventory.py @@ -999,6 +999,9 @@ def __init__(self, data): self.nickname = self.nickname_raw or self.name self.in_fort = 'deployed_fort_id' in data + if 'deployed_fort_id' in data: + self.fort_id = data['deployed_fort_id'] + self.is_favorite = data.get('favorite', 0) is 1 self.buddy_candy = data.get('buddy_candy_awarded', 0) self.is_bad = data.get('is_bad', False) From aa306d4df999cae22a91bd2b3ab6d83810fc2770 Mon Sep 17 00:00:00 2001 From: goedzo Date: Sat, 15 Jul 2017 14:10:23 +0200 Subject: [PATCH 11/17] Fix for gyms not sharing their defenders --- pokemongo_bot/cell_workers/gym_pokemon.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index 0042025127..230fe1e4fe 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -365,7 +365,14 @@ def feed_pokemons_in_gym(self, gym): return True max_gym_time = timedelta(hours=8,minutes=20) - gym_info = self.get_gym_details(gym).get('gym_status_and_defenders', None) + + try: + gym_info = self.get_gym_details(gym).get('gym_status_and_defenders', None) + except TypeError: + #This gym does not give status results. + self.team = TEAM_NOT_SET + return True + # self.logger.info("Defenders in gym:")okemon_info..items()get('pokemon_id') if gym_info: defenders = gym_info.get('gym_defender', []) From ac151a8549ae4eff0490b9d29ac132100b892dfa Mon Sep 17 00:00:00 2001 From: goedzo Date: Sat, 15 Jul 2017 14:14:04 +0200 Subject: [PATCH 12/17] Stop moving if running fails --- pokemongo_bot/cell_workers/gym_pokemon.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index 230fe1e4fe..b0a07f4f57 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -291,6 +291,9 @@ def move_to_destination(self): if not step_walker.step(): return WorkerResult.RUNNING + else: + #Running fails. Let's stop moving to the gym + return WorkerResult.SUCCESS else: self.emit_event( 'arrived_at_fort', From 4548311f8f705370e74a9e3d5e72c4ea53255e8d Mon Sep 17 00:00:00 2001 From: goedzo Date: Mon, 17 Jul 2017 01:12:53 +0200 Subject: [PATCH 13/17] Gym Deployment finalized --- pokemongo_bot/cell_workers/gym_pokemon.py | 96 ++++++++++++++++------- 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/pokemongo_bot/cell_workers/gym_pokemon.py b/pokemongo_bot/cell_workers/gym_pokemon.py index b0a07f4f57..ec1ec91549 100644 --- a/pokemongo_bot/cell_workers/gym_pokemon.py +++ b/pokemongo_bot/cell_workers/gym_pokemon.py @@ -44,6 +44,7 @@ ITEM_PINAPBERRY = 705 + class GymPokemon(BaseTask): SUPPORTED_TASK_API_VERSION = 1 @@ -51,6 +52,10 @@ def __init__(self, bot, config): super(GymPokemon, self).__init__(bot, config) def initialize(self): + + #Adding this to play with finding a quantity that works + self.gym_quantity_test = 1 + # 10 seconds from current time self.next_update = datetime.now() + timedelta(0, 10) self.order_by = self.config.get('order_by', 'cp') @@ -72,7 +77,6 @@ def initialize(self): self.check_interval = 0 self.gyms = [] self.raid_gyms = dict() - self.bot.event_manager.register_event('gym_error') self.bot.event_manager.register_event('fed_pokemon') self.bot.event_manager.register_event('gym_full') @@ -227,9 +231,7 @@ def determin_new_destination(self): break else: #If there are mons we can feed, check them. Note: gym_details returns false if gym is not in range. - gym_to_feed = self.get_gym_details(gym) - if gym_to_feed!=False: - self.feed_pokemons_in_gym(gym_to_feed) + self.feed_pokemons_in_gym(gym) else: # self.logger.info("Found a Neutral gym?") # self.logger.info("Info: %s" % gym) @@ -371,16 +373,15 @@ def feed_pokemons_in_gym(self, gym): try: gym_info = self.get_gym_details(gym).get('gym_status_and_defenders', None) - except TypeError: - #This gym does not give status results. - self.team = TEAM_NOT_SET + except (TypeError,KeyError,AttributeError): + #This gym does not give status results. Probably it is not in range return True # self.logger.info("Defenders in gym:")okemon_info..items()get('pokemon_id') if gym_info: defenders = gym_info.get('gym_defender', []) for defender in defenders: - #self.logger.info("Feed data: defender %s" % defender) + #self.logger.info("LOG: Defender data: defender %s" % defender) motivated_pokemon = defender.get('motivated_pokemon') pokemon_info = motivated_pokemon.get('pokemon') @@ -400,14 +401,16 @@ def feed_pokemons_in_gym(self, gym): #Testing to see what quantity field does. Probably just the amount of berries you want to feed #quantity = pokemon_info.get('num_upgrades') <- Failed - #quantity=1 <- Failed - quantity=0 - food_values = motivated_pokemon.get('food_value') - for food_value in food_values: - if food_value.get('food_item') == berry_id: - quantity = food_value.get('motivation_increase') - if quantity !=0: - self._feed_pokemon(gym, poke_id, berry_id, quantity) + quantity=2 + self._feed_pokemon(gym, poke_id, berry_id, quantity) + + # quantity=0 + # food_values = motivated_pokemon.get('food_value') + # for food_value in food_values: + # if food_value.get('food_item') == berry_id: + # quantity = food_value.get('motivation_increase') + # if quantity !=0: + # self._feed_pokemon(gym, poke_id, berry_id, quantity) def _determin_feed_berry_id(self, motivated_pokemon): # # Store the amount of berries we have @@ -443,13 +446,29 @@ def _feed_pokemon(self, gym, pokemon_id, berry_id, quantity): self.logger.info("----THIS IS IN DEVELOPEMENT-----") self.logger.info("We are feeding pokemon %s with berry %s ",pokemon_id,berry_id) - self.logger.info("Feed data: quantity %s" % quantity) + self.logger.info("Feed data: quantity %s" % self.gym_quantity_test) + #self.logger.info("Feed data: gym %s" % gym) self.logger.info("----ABORTING HERE SINCE WE HAVE NOT YET FIND THE RIGHT API PARAMETERS-----") return True - + + #Get the gym_name to show in messages + lat = self.destination["latitude"] + lng = self.destination["longitude"] + + details = fort_details(self.bot, gym["id"], lat, lng) + if details: + gym_name = details.get('name', 'Unknown') + else: + #Seem that we cannot read details here. Let's exit + return True + + + #Overide the quantity to find the right value + #quantity = self.gym_quantity_test + request = self.bot.api.create_request() request.gym_feed_pokemon( - starting_quantity=quantity, + starting_quantity=self.gym_quantity_test, item_id=berry_id, gym_id=gym["id"], pokemon_id=pokemon_id, @@ -459,19 +478,40 @@ def _feed_pokemon(self, gym, pokemon_id, berry_id, quantity): response_dict = request.call() if ('responses' in response_dict) and ('GYM_FEED_POKEMON' in response_dict['responses']): feeding = response_dict['responses']['GYM_FEED_POKEMON'] + self.logger.info("Feeding result: %s" % feeding) result = feeding.get('result', -1) - self.logger.info("Feeding: %s" % feeding) if result == 1: # Succesful feeding - #self.logger.info("Fed a Pokemon!") self.emit_event( 'fed_pokemon', - formatted=("We fed %s in the gym %s!!" % (pokemon_id, gym_details["name"])), + formatted=("We fed %s in the gym %s!!" % (pokemon_id, gym_name)), data={'gym_id': gym['id'], 'pokemon_id': pokemon_id} ) + elif result == 4: #ERROR_POKEMON_NOT_THERE + self.emit_event( + 'fed_pokemon', + formatted=("Pokemon %s has dropped out of the gym %s!" % (pokemon_id, gym_name)), + data={'gym_id': gym['id'], 'pokemon_id': pokemon_id} + ) + elif result == 5: #ERROR_POKEMON_FULL + self.emit_event( + 'fed_pokemon', + formatted=("Pokemon %s is full in gym %s!" % (pokemon_id, gym_name)), + data={'gym_id': gym['id'], 'pokemon_id': pokemon_id} + ) + elif result == 7: #ERROR_WRONG_TEAM + self.emit_event( + 'fed_pokemon', + formatted=("Team Switched while feeding %s in gym %s!" % (pokemon_id, gym_name)), + data={'gym_id': gym['id'], 'pokemon_id': pokemon_id} + ) + elif result == 8: #ERROR_WRONG_COUNT + #Let's try a different quantity + self.gym_quantity_test += 1 else: self.logger.info("Feeding failed! %s" % result) - + + def drop_pokemon_in_gym(self, gym, current_pokemons): self.pokemons = inventory.pokemons().all() self.fort_pokemons = [p for p in self.pokemons if p.in_fort] @@ -546,12 +586,12 @@ def drop_pokemon_in_gym(self, gym, current_pokemons): self.logger.info("Lockout time: %s" % lockout_time.strftime('%Y-%m-%d %H:%M:%S.%f')) while lockout_time > datetime.now(): self.logger.info("Waiting for %s seconds deployment lockout to end..." % (lockout_time-datetime.today()).seconds) - #Feed any mons while we are waiting - self.feed_pokemons_in_gym(gym) - if (lockout_time-datetime.today()).seconds > 20: - sleep(20) + if (lockout_time-datetime.today()).seconds > 40: + sleep(40) + #Feed any mons while we are waiting + self.feed_pokemons_in_gym(gym) else: - sleep((lockout_time-t).seconds) + sleep((lockout_time-datetime.today()).seconds) break #FortDeployPokemon From 9a9b7a6c05bc00efada77b3e243b4474bf46dff6 Mon Sep 17 00:00:00 2001 From: goedzo Date: Mon, 17 Jul 2017 15:58:15 +0200 Subject: [PATCH 14/17] Full API Support for 0.67.2 based on latest compile from POGOProtos Recompiled latest https://github.com/AeonLucid/POGOProtos API and added to my own maintained repository. fixes #6075 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d517615426..f76d0fc5f5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ numpy==1.11.0 networkx==1.11 six==1.10 -git+https://github.com/pogodevorg/pgoapi.git@develop#egg=pgoapi +git+https://github.com/goedzo/pgoapi.git@develop#egg=pgoapi geopy==1.11.0 geographiclib==1.46.3 requests==2.10.0 From d6bcbd592917de415e6dc9a52d355840cb213ee9 Mon Sep 17 00:00:00 2001 From: goedzo Date: Tue, 18 Jul 2017 02:02:32 +0200 Subject: [PATCH 15/17] Making sure we are all fixed now --- pokemongo_bot/event_handlers/logging_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pokemongo_bot/event_handlers/logging_handler.py b/pokemongo_bot/event_handlers/logging_handler.py index 08f2884442..226530f9f0 100644 --- a/pokemongo_bot/event_handlers/logging_handler.py +++ b/pokemongo_bot/event_handlers/logging_handler.py @@ -133,7 +133,7 @@ class LoggingHandler(EventHandler): 'healing_pokemon': 'green', 'deployed_pokemon': 'green', 'gym_error': 'red', - 'fed_pokemon': 'white + 'fed_pokemon': 'white' } COLOR_CODE = { 'gray': '\033[90m', From 2f9ab1760e83d63ec63028b0f8ffd01f25955ad9 Mon Sep 17 00:00:00 2001 From: David Westerink Date: Tue, 18 Jul 2017 09:07:55 +0200 Subject: [PATCH 16/17] Removed unused config unused config should not be in example config --- configs/config.json.example | 1 - 1 file changed, 1 deletion(-) diff --git a/configs/config.json.example b/configs/config.json.example index f73d4beb93..71d098d45a 100644 --- a/configs/config.json.example +++ b/configs/config.json.example @@ -468,7 +468,6 @@ "type": "GymPokemon", "config": { "enabled": false, - "feed_berries": false, "order_by": "cp", "min_interval":360, "min_recheck":30, From db9f99f2a1a34413ae0f68d9e9d7dd6a1dd800ab Mon Sep 17 00:00:00 2001 From: David Westerink Date: Tue, 18 Jul 2017 09:08:42 +0200 Subject: [PATCH 17/17] Removed unused event Event is gone, no need to color that --- pokemongo_bot/event_handlers/logging_handler.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pokemongo_bot/event_handlers/logging_handler.py b/pokemongo_bot/event_handlers/logging_handler.py index 226530f9f0..22db8f75fe 100644 --- a/pokemongo_bot/event_handlers/logging_handler.py +++ b/pokemongo_bot/event_handlers/logging_handler.py @@ -132,8 +132,7 @@ class LoggingHandler(EventHandler): 'revived_pokemon': 'green', 'healing_pokemon': 'green', 'deployed_pokemon': 'green', - 'gym_error': 'red', - 'fed_pokemon': 'white' + 'gym_error': 'red' } COLOR_CODE = { 'gray': '\033[90m',