From b5acdd5f3394f7de40926cacfd2ca35ae019cad4 Mon Sep 17 00:00:00 2001 From: goedzo Date: Fri, 14 Jul 2017 14:29:04 +0200 Subject: [PATCH 01/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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/23] 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 432a51c3908b1148b33a61c431fb740e58bf3d9f Mon Sep 17 00:00:00 2001 From: goedzo Date: Tue, 18 Jul 2017 00:56:34 +0200 Subject: [PATCH 15/23] Fixed Heal Pokemon Event "revived_pokemon" was not registerd. --- pokemongo_bot/__init__.py | 1 + pokemongo_bot/event_handlers/logging_handler.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index 08b7b208ca..3095b34224 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -559,6 +559,7 @@ def _register_events(self): self.event_manager.register_event('catch_limit') self.event_manager.register_event('spin_limit') self.event_manager.register_event('show_best_pokemon', parameters=('pokemons')) + self.event_manager.register_event('revived_pokemon') # level up stuff self.event_manager.register_event( diff --git a/pokemongo_bot/event_handlers/logging_handler.py b/pokemongo_bot/event_handlers/logging_handler.py index c873cc7a0f..ce07aeb6c1 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', + 'revived_pokemon': 'green' } COLOR_CODE = { 'gray': '\033[90m', From de9cb21f590331c4870fb1d9ce3635a114bd2f99 Mon Sep 17 00:00:00 2001 From: goedzo Date: Tue, 18 Jul 2017 01:08:50 +0200 Subject: [PATCH 16/23] Fixed all Heal Pokemon bugs --- pokemongo_bot/__init__.py | 1 + pokemongo_bot/event_handlers/logging_handler.py | 4 +++- pokemongo_bot/inventory.py | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index 3095b34224..3e8bd41a67 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -560,6 +560,7 @@ def _register_events(self): self.event_manager.register_event('spin_limit') self.event_manager.register_event('show_best_pokemon', parameters=('pokemons')) self.event_manager.register_event('revived_pokemon') + self.event_manager.register_event('healing_pokemon') # level up stuff self.event_manager.register_event( diff --git a/pokemongo_bot/event_handlers/logging_handler.py b/pokemongo_bot/event_handlers/logging_handler.py index ce07aeb6c1..86c9fa5a92 100644 --- a/pokemongo_bot/event_handlers/logging_handler.py +++ b/pokemongo_bot/event_handlers/logging_handler.py @@ -129,7 +129,9 @@ class LoggingHandler(EventHandler): 'used_lucky_egg': 'none', 'catch_limit_on': 'yellow', 'catch_limit_off': 'green', - 'revived_pokemon': 'green' + 'revived_pokemon': 'green', + 'healing_pokemon': 'green' + } COLOR_CODE = { 'gray': '\033[90m', diff --git a/pokemongo_bot/inventory.py b/pokemongo_bot/inventory.py index 49de951e78..e7a5129e4b 100644 --- a/pokemongo_bot/inventory.py +++ b/pokemongo_bot/inventory.py @@ -522,6 +522,11 @@ def add(self, pokemon): raise ValueError("Pokemon already present in the inventory") self._data[pokemon.unique_id] = pokemon + def get_from_unique_id(self, pokemon_unique_id): + if pokemon_unique_id not in self._data: + raise ValueError("Pokemon not present in the inventory") + return self._data[pokemon_unique_id] + def remove(self, pokemon_unique_id): if pokemon_unique_id not in self._data: raise ValueError("Pokemon not present in the inventory") From d6bcbd592917de415e6dc9a52d355840cb213ee9 Mon Sep 17 00:00:00 2001 From: goedzo Date: Tue, 18 Jul 2017 02:02:32 +0200 Subject: [PATCH 17/23] 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 6ed8089a535f67f13823d13b292db04ba29a8e1f Mon Sep 17 00:00:00 2001 From: David Westerink Date: Tue, 18 Jul 2017 08:57:12 +0200 Subject: [PATCH 18/23] Changes to spinning Pokestops and Gyms --- pokemongo_bot/cell_workers/spin_fort.py | 66 +++++++++++++++++++++---- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/pokemongo_bot/cell_workers/spin_fort.py b/pokemongo_bot/cell_workers/spin_fort.py index e47d20f1a7..5712dd27e0 100644 --- a/pokemongo_bot/cell_workers/spin_fort.py +++ b/pokemongo_bot/cell_workers/spin_fort.py @@ -19,6 +19,7 @@ SPIN_REQUEST_RESULT_OUT_OF_RANGE = 2 SPIN_REQUEST_RESULT_IN_COOLDOWN_PERIOD = 3 SPIN_REQUEST_RESULT_INVENTORY_FULL = 4 +SPIN_REQUEST_RESULT_POI_INACCESSIBLE = 5 LURE_REQUEST_RESULT_SUCCESS = 1 LURE_REQUEST_FORT_ALREADY_HAS_MODIFIER= 2 @@ -35,6 +36,8 @@ def __init__(self, bot, config): def initialize(self): # 10 seconds from current time self.next_update = datetime.now() + timedelta(0, 10) + self.fort_spins = 0 + self.streak_forts = [] self.ignore_item_count = self.config.get("ignore_item_count", False) self.spin_wait_min = self.config.get("spin_wait_min", 2) @@ -42,6 +45,10 @@ def initialize(self): self.min_interval = int(self.config.get('min_interval', 120)) self.exit_on_limit_reached = self.config.get("exit_on_limit_reached", True) self.use_lure = self.config.get("use_lure", False) + self.try_to_keep_streak = self.config.get("try_to_keep_streak", True) + + # if self.try_to_keep_streak and len(self.bot.recent_forts) is not 10: + # self.logger.warn("You enabled the setting for keeping a 10 stop streak, but the number of recent forts is not set to 10! It is set to %s. This will cause the streak to fail!" % len(self.bot.recent_forts)) def should_run(self): has_space_for_loot = inventory.Items.has_space_for_loot() @@ -74,27 +81,36 @@ def work(self): fort = forts[0] + if fort['id'] in self.streak_forts: + self.fort_spins = 1 + self.streak_forts = [fort['id']] + elif self.fort_spins >= 10: + self.fort_spins = 1 + self.streak_forts = [fort['id']] + else: + self.fort_spins += 1 + lat = fort['latitude'] lng = fort['longitude'] details = fort_details(self.bot, fort['id'], lat, lng) - fort_name = details.get('name', 'Unknown') + fort_name = details.get('name', 'Unknown') check_fort_modifier = details.get('modifiers', {}) - if check_fort_modifier: + if self.use_lure and check_fort_modifier: # check_fort_modifier_id = check_fort_modifier[0].get('item_id') self.emit_event('lure_info', formatted='A lure is already in fort, skip deploying lure') - + if self.use_lure and not check_fort_modifier: # check lures availiblity lure_count = inventory.items().get(501).count - + if lure_count > 1: # Only use lures when there's more than one request = self.bot.api.create_request() request.add_fort_modifier( modifier_type=501, - fort_id = fort['id'], - player_latitude = f2i(self.bot.position[0]), + fort_id = fort['id'], + player_latitude = f2i(self.bot.position[0]), player_longitude = f2i(self.bot.position[1]) ) response_dict = request.call() @@ -114,7 +130,7 @@ def work(self): self.emit_event('lure_info', formatted='Unkown Error') else: self.emit_event('lure_not_enough', formatted='Not enough lure in inventory') - + request = self.bot.api.create_request() request.fort_search( fort_id=fort['id'], @@ -124,7 +140,7 @@ def work(self): player_longitude=f2i(self.bot.position[1]) ) response_dict = request.call() - + if ('responses' in response_dict) and ('FORT_SEARCH' in response_dict['responses']): spin_details = response_dict['responses']['FORT_SEARCH'] spin_result = spin_details.get('result', -1) @@ -134,20 +150,39 @@ def work(self): experience_awarded = spin_details.get('experience_awarded', 0) items_awarded = self.get_items_awarded_from_fort_spinned(response_dict) egg_awarded = spin_details.get('pokemon_data_egg', None) + gym_badge_awarded = spin_details.get('awarded_gym_badge', None) + chain_hack_sequence_number = spin_details.get('chain_hack_sequence_number', 0) if egg_awarded is not None: items_awarded[u'Egg'] = egg_awarded['egg_km_walked_target'] + # if gym_badge_awarded is not None: + # self.logger.info("Gained a Gym Badge! %s" % gym_badge_awarded) + # + # if chain_hack_sequence_number > 0: + # self.logger.info("Chain hack sequence: %s" % chain_hack_sequence_number) + if experience_awarded or items_awarded: awards = ', '.join(["{}x {}".format(items_awarded[x], x) for x in items_awarded if x != u'Egg']) if egg_awarded is not None: awards += u', {} Egg'.format(egg_awarded['egg_km_walked_target']) + self.fort_spins = chain_hack_sequence_number + + if "type" in fort and fort["type"] == 1: + # It's a Pokestop + stop_kind = "pokestop" + else: + # It's a gym + stop_kind = "gym" + self.emit_event( 'spun_pokestop', - formatted="Spun pokestop {pokestop}. Experience awarded: {exp}. Items awarded: {items}", + formatted="Spun {stop_kind} {pokestop} ({spin_amount_now} streak). Experience awarded: {exp}. Items awarded: {items}", data={ + 'stop_kind': stop_kind, 'pokestop': fort_name, 'exp': experience_awarded, + 'spin_amount_now': chain_hack_sequence_number, 'items': awards } ) @@ -196,6 +231,9 @@ def work(self): formatted="Pokestop {pokestop} on cooldown. Time left: {minutes_left}.", data={'pokestop': fort_name, 'minutes_left': minutes_left} ) + elif spin_result == SPIN_REQUEST_RESULT_POI_INACCESSIBLE: + self.logger.info("Pokestop not accessable at this time.") + self.bot.fort_timeouts[fort["id"]] = (time.time() + 300) * 1000 # Don't spin for 5m else: self.emit_event( 'unknown_spin_result', @@ -224,7 +262,7 @@ def work(self): result = c.fetchone() if result[0] == 1: - source = str("PokemonCatchWorker") + source = str("SpinFort") status = str("Possible Softban") conn.execute('''INSERT INTO softban_log (status, source) VALUES (?, ?)''', (status, source)) else: @@ -246,6 +284,14 @@ def work(self): def get_forts_in_range(self): forts = self.bot.get_forts(order_by_distance=True) forts = filter(lambda fort: fort["id"] not in self.bot.fort_timeouts, forts) + if self.bot.camping_forts and self.try_to_keep_streak: + if datetime.now() >= self.next_update: + self.logger.info("Camping forts, ignoring 10 stops streak.") + elif self.try_to_keep_streak: + if len(self.streak_forts) > 10: + self.streak_forts.pop() + # Remove all forts which were spun in the last ticks to keep 10 stops streak + forts = filter(lambda x: x["id"] not in self.streak_forts, forts) if self.bot.config.replicate_gps_xy_noise: forts = filter(lambda fort: distance( From 424bae09c6d3146ca1e5db702be1f69ad8696509 Mon Sep 17 00:00:00 2001 From: David Westerink Date: Tue, 18 Jul 2017 08:58:39 +0200 Subject: [PATCH 19/23] Trying to solve move to fort issues Inspired on PokemonHunter, when having difficulties moving try to change the walker and if it doesnt help, ignore the stop --- pokemongo_bot/cell_workers/move_to_fort.py | 57 ++++++++++++++++++++-- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/pokemongo_bot/cell_workers/move_to_fort.py b/pokemongo_bot/cell_workers/move_to_fort.py index 40c4d68658..24a65523b8 100644 --- a/pokemongo_bot/cell_workers/move_to_fort.py +++ b/pokemongo_bot/cell_workers/move_to_fort.py @@ -9,6 +9,7 @@ from pokemongo_bot.base_task import BaseTask from .utils import distance, format_dist, fort_details from datetime import datetime, timedelta +import time class MoveToFort(BaseTask): SUPPORTED_TASK_API_VERSION = 1 @@ -22,6 +23,8 @@ def initialize(self): self.walker = self.config.get('walker', 'StepWalker') self.wait_at_fort = self.config.get('wait_on_lure', False) self.wait_log_sent = None + self.previous_distance = [] + self.target_id = None def should_run(self): has_space_for_loot = inventory.Items.has_space_for_loot() @@ -39,6 +42,9 @@ def work(self): if not self.should_run(): return WorkerResult.SUCCESS + if hasattr(self.bot, "hunter_locked_target") and self.bot.hunter_locked_target is not None: + return WorkerResult.SUCCESS + nearest_fort = self.get_nearest_fort() if nearest_fort is None: @@ -50,6 +56,9 @@ def work(self): details = fort_details(self.bot, fortID, lat, lng) fort_name = details.get('name', 'Unknown') + if self.target_id is None: + self.target_id = fort_name + unit = self.bot.config.distance_unit # Unit to use when printing formatted distance dist = distance( @@ -67,24 +76,64 @@ def work(self): 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 + distance_to_target = int(noised_dist if self.bot.config.replicate_gps_xy_noise else dist) + if len(self.previous_distance) == 0: + self.previous_distance.append(distance_to_target) + elif self.target_id is not fort_name: + # self.logger.info("Changed target from %s to %s" % (self.target_id, fort_name)) + self.previous_distance = [distance_to_target] + self.target_id = fort_name + if self.walker is not self.config.get('walker', 'StepWalker'): + self.walker = self.config.get('walker', 'StepWalker') + else: + # self.logger.info("Previous distances: %s" % self.previous_distance) + if len(self.previous_distance) > 5: + self.previous_distance.pop(0) + error_moving = False + times_found = 0 + for prev_distance in self.previous_distance: + if prev_distance == distance_to_target: + error_moving = True + break + + if error_moving: + if self.walker == 'StepWalker': + self.logger.info("Having difficulty walking to %s" % fort_name) + self.bot.recent_forts = self.bot.recent_forts[1:] + [fortID] + return WorkerResult.ERROR + else: + self.logger.info("Having difficulty walking to %s. Changing walker." % fort_name) + self.walker = 'StepWalker' + self.previous_distance = [distance_to_target] + else: + self.previous_distance.append(distance_to_target) + if moving: self.wait_log_sent = None + if "type" in nearest_fort and nearest_fort["type"] == 1: + # It's a Pokestop + target_type = "pokestop" + else: + # It's a gym + target_type = "gym" + fort_event_data = { 'fort_name': u"{}".format(fort_name), 'distance': format_dist(dist, unit), + 'target_type': target_type, } if self.is_attracted() > 0: fort_event_data.update(lure_distance=format_dist(self.lure_distance, unit)) self.emit_event( 'moving_to_lured_fort', - formatted="Moving towards pokestop {fort_name} - {distance} (attraction of lure {lure_distance})", + formatted="Moving towards {target_type} {fort_name} - {distance} (attraction of lure {lure_distance})", data=fort_event_data ) else: self.emit_event( 'moving_to_fort', - formatted="Moving towards pokestop {fort_name} - {distance}", + formatted="Moving towards {target_type} {fort_name} - {distance}", data=fort_event_data ) @@ -178,7 +227,7 @@ def get_nearest_fort(self): if len(forts) >= 3: # Get ID of fort, store it. Check index 0 & index 2. Both must not be same nearest_fort = forts[0] - + if len(self.fort_ids) < 3: self.fort_ids.extend(nearest_fort['id']) else: @@ -191,7 +240,7 @@ def get_nearest_fort(self): else: self.fort_ids.pop(0) self.fort_ids.extend(nearest_fort['id']) - + return nearest_fort else: return None From 8241825dfe74ed132ad2e1c5c060a616998245eb Mon Sep 17 00:00:00 2001 From: David Westerink Date: Tue, 18 Jul 2017 09:04:52 +0200 Subject: [PATCH 20/23] Caching of forts small adjustment When a fort is too far away, dont try to get the details. When it is in range do --- pokemongo_bot/cell_workers/utils.py | 32 +++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/pokemongo_bot/cell_workers/utils.py b/pokemongo_bot/cell_workers/utils.py index b0112a0958..25a8f6a9ce 100644 --- a/pokemongo_bot/cell_workers/utils.py +++ b/pokemongo_bot/cell_workers/utils.py @@ -26,8 +26,28 @@ def fort_details(bot, fort_id, latitude, longitude): """ Lookup fort metadata and (if possible) serve from cache. """ - + first_call = False if fort_id not in FORT_CACHE: + if distance(latitude, longitude, bot.position[0], bot.position[1]) > 1000: + # Fort too far away to get the details! + FORT_CACHE[fort_id] = dict() + first_call = True + else: + """ + Lookup the fort details and cache the response for future use. + """ + request = bot.api.create_request() + request.fort_details(fort_id=fort_id, latitude=latitude, longitude=longitude) + try: + response_dict = request.call() + FORT_CACHE[fort_id] = response_dict['responses']['FORT_DETAILS'] + first_call = True + except Exception: + FORT_CACHE[fort_id] = dict() + first_call = True + + if not first_call and FORT_CACHE.get(fort_id, dict()) == dict(): + if distance(latitude, longitude, bot.position[0], bot.position[1]) < 1000: """ Lookup the fort details and cache the response for future use. """ @@ -37,7 +57,7 @@ def fort_details(bot, fort_id, latitude, longitude): response_dict = request.call() FORT_CACHE[fort_id] = response_dict['responses']['FORT_DETAILS'] except Exception: - pass + FORT_CACHE[fort_id] = dict() # Just to avoid KeyErrors return FORT_CACHE.get(fort_id, {}) @@ -133,14 +153,14 @@ def getSeconds(strTime): try: x = dt.strptime(strTime, '%H:%M:%S') seconds = int(timedelta(hours=x.hour,minutes=x.minute,seconds=x.second).total_seconds()) - except ValueError: + except ValueError: seconds = 0; - + if seconds < 0: seconds = 0; - + return seconds - + def format_time(seconds): # Return a string displaying the time given as seconds or minutes num, duration = 0, long(round(seconds)) From 2f9ab1760e83d63ec63028b0f8ffd01f25955ad9 Mon Sep 17 00:00:00 2001 From: David Westerink Date: Tue, 18 Jul 2017 09:07:55 +0200 Subject: [PATCH 21/23] 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 22/23] 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', From 38d488d302a15aceb7388c02cb0e5483eafb423a Mon Sep 17 00:00:00 2001 From: David Westerink Date: Tue, 18 Jul 2017 10:53:29 +0200 Subject: [PATCH 23/23] Fixing missed events --- pokemongo_bot/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index b51901fc3e..769b61f47d 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -372,6 +372,7 @@ def _register_events(self): 'moving_to_fort', parameters=( 'fort_name', + 'target_type', 'distance' ) ) @@ -379,6 +380,7 @@ def _register_events(self): 'moving_to_lured_fort', parameters=( 'fort_name', + 'target_type', 'distance', 'lure_distance' ) @@ -386,7 +388,7 @@ def _register_events(self): self.event_manager.register_event( 'spun_pokestop', parameters=( - 'pokestop', 'exp', 'items' + 'pokestop', 'exp', 'items', 'stop_kind', 'spin_amount_now' ) ) self.event_manager.register_event(