def test_one_small_speed(self): walk_max = self.bot.config.walk_max walk_min = self.bot.config.walk_min speed = 0.247503233266 precision = 0.0 dlat = 47.17064 dlng = 8.51674 self.bot.config.walk_max = speed self.bot.config.walk_min = speed pw = PolylineWalker(self.bot, ex_dest[0], ex_dest[1], precision=precision) self.assertEqual(pw.dest_lat, ex_dest[0], 'dest_lat did not match') self.assertEqual(pw.dest_lng, ex_dest[1], 'dest_lng did not match') @mock.patch('random.uniform') def run_step(mock_random): mock_random.return_value = 0.0 return pw.step() finishedWalking = run_step() self.assertFalse(finishedWalking, 'step should return False') distance = Geodesic.WGS84.Inverse(dlat, dlng, self.bot.position[0], self.bot.position[1])["s12"] self.assertTrue(0.0 <= distance <= (pw.precision + pw.epsilon)) self.polyline._last_pos = (dlat, dlng) self.assertTrue(abs(self.polyline.get_alt() - self.bot.position[2]) <= 1) self.bot.config.walk_max = walk_max self.bot.config.walk_min = walk_min
def test_bigger_then_total_speed_big_precision_offset(self): walk_max = self.bot.config.walk_max walk_min = self.bot.config.walk_min speed = 300 precision = 2.5 self.bot.config.walk_max = speed self.bot.config.walk_min = speed pw = PolylineWalker(self.bot, ex_dest[0], ex_dest[1], precision=precision) self.assertEqual(pw.dest_lat, ex_dest[0], 'dest_lat did not match') self.assertEqual(pw.dest_lng, ex_dest[1], 'dest_lng did not match') @mock.patch('random.uniform') def run_step(mock_random): mock_random.return_value = 0.0 return pw.step() finishedWalking = run_step() self.assertTrue(finishedWalking, 'step should return False') distance = Geodesic.WGS84.Inverse(ex_dest[0], ex_dest[1], self.bot.position[0], self.bot.position[1])["s12"] self.assertTrue(0.0 <= distance <= (pw.precision + pw.epsilon)) self.polyline._last_pos = self.polyline.destination self.assertTrue(abs(self.polyline.get_alt() - self.bot.position[2]) <= 1) self.bot.config.walk_max = walk_max self.bot.config.walk_min = walk_min
def work(self): if not self.enabled: return WorkerResult.SUCCESS if self.get_pokeball_count() <= 0: self.destination = None self.last_cell_id = None return WorkerResult.SUCCESS now = time.time() pokemons = self.get_nearby_pokemons() if self.destination is None: worth_pokemons = self.get_worth_pokemons(pokemons) if len(worth_pokemons) > 0: self.destination = worth_pokemons[0] self.lost_counter = 0 self.logger.info("New destination at %(distance).2f meters: %(name)s", self.destination) self.no_log_until = now + 60 if self.destination["s2_cell_id"] != self.search_cell_id: self.search_points = self.get_search_points(self.destination["s2_cell_id"]) self.walker = PolylineWalker(self.bot, self.search_points[0][0], self.search_points[0][1]) self.search_cell_id = self.destination["s2_cell_id"] self.search_points = self.search_points[1:] + self.search_points[:1] else: if self.no_log_until < now: self.logger.info("There is no nearby pokemon worth hunting down [%s]", ", ".join(p["name"] for p in pokemons)) self.no_log_until = now + 120 self.last_cell_id = None return WorkerResult.SUCCESS if any(self.destination["encounter_id"] == p["encounter_id"] for p in self.bot.cell["catchable_pokemons"] + self.bot.cell["wild_pokemons"]): self.destination = None elif self.walker.step(): if not any(self.destination["encounter_id"] == p["encounter_id"] for p in pokemons): self.lost_counter += 1 else: self.lost_counter = 0 if self.lost_counter >= 3: self.destination = None else: self.logger.info("Now searching for %(name)s", self.destination) self.walker = StepWalker(self.bot, self.search_points[0][0], self.search_points[0][1]) self.search_points = self.search_points[1:] + self.search_points[:1] elif self.no_log_until < now: distance = great_circle(self.bot.position, (self.walker.dest_lat, self.walker.dest_lng)).meters self.logger.info("Moving to destination at %s meters: %s", round(distance, 2), self.destination["name"]) self.no_log_until = now + 30 return WorkerResult.RUNNING
def set_target(self): if not 's2_cell_id' in self.destination: # This Pokemon has coords self.search_points = [] self.walker = PolylineWalker(self.bot, self.destination["latitude"], self.destination["longitude"]) self.logger.info("Target must be close by...") # self.logger.info("destination: %s" % self.destination) # self.search_points = self.get_search_points(self.bot.cell["s2_cell_id"]) # self.search_cell_id = self.bot.cell["s2_cell_id"] # self.search_points = self.search_points[1:] + self.search_points[:1] else: self.search_points = self.get_search_points( self.destination["s2_cell_id"]) self.walker = PolylineWalker(self.bot, self.search_points[0][0], self.search_points[0][1]) self.search_cell_id = self.destination["s2_cell_id"] self.search_points = self.search_points[1:] + self.search_points[:1] if "fort_id" in self.destination: # The Pokemon is hding at a POkestop, so move to that Pokestop! # Get forts forts = self.bot.get_forts(order_by_distance=True) for fort in forts: if fort['id'] == self.destination['fort_id']: # Found our fort! lat = fort['latitude'] lng = fort['longitude'] details = fort_details(self.bot, fort['id'], lat, lng) fort_name = details.get('name', 'Unknown') self.logger.info("%s is hiding at %s, going there first!" % (self.destination["name"], fort_name)) self.walker = PolylineWalker(self.bot, lat, lng) else: nearest_fort = self.get_nearest_fort_on_the_way() if nearest_fort is not None: lat = nearest_fort['latitude'] lng = nearest_fort['longitude'] details = fort_details(self.bot, nearest_fort['id'], lat, lng) fort_name = details.get('name', 'Unknown') self.logger.info("Moving to %s via %s." % (self.destination["name"], fort_name)) self.walker = PolylineWalker(self.bot, lat, lng)
def set_target(self): self.search_points = self.get_search_points(self.destination["s2_cell_id"]) self.walker = PolylineWalker(self.bot, self.search_points[0][0], self.search_points[0][1]) self.search_cell_id = self.destination["s2_cell_id"] self.search_points = self.search_points[1:] + self.search_points[:1] if "fort_id" in self.destination: # The Pokemon is hding at a POkestop, so move to that Pokestop! # Get forts forts = self.bot.get_forts(order_by_distance=True) for fort in forts: if fort['id'] == self.destination['fort_id']: # Found our fort! lat = fort['latitude'] lng = fort['longitude'] details = fort_details(self.bot, fort['id'], lat, lng) fort_name = details.get('name', 'Unknown') self.logger.info("%s is hiding at %s, going there first!" % (self.destination["name"], fort_name)) self.walker = PolylineWalker(self.bot, lat, lng)
def work(self): if not self.enabled: return WorkerResult.SUCCESS now = time.time() if now < self.move_until: return WorkerResult.SUCCESS if 0 < self.stay_until < now: self.destination = None self.stay_until = 0 self.move_until = now + self.config_moving_time if self.config_moving_time > 0: return WorkerResult.SUCCESS if self.destination is None: forts = self.get_forts() forts_clusters = self.get_forts_clusters(forts) if len(forts_clusters) > 0: self.destination = forts_clusters[0] self.logger.info("New destination at %s meters: %s forts, %s lured.", int(self.destination[4]), self.destination[3], self.destination[2]) else: # forts = [f for f in forts if f.get("cooldown_complete_timestamp_ms", 0) < now * 1000] # fort = min(forts, key=lambda f: self.dist(self.bot.position, f)) # self.destination = (fort["latitude"], fort["longitude"]) return WorkerResult.SUCCESS if (now - self.last_position_update) < 1: return WorkerResult.RUNNING else: self.last_position_update = now if self.stay_until >= now: lat = self.destination[0] + random_lat_long_delta() / 5 lon = self.destination[1] + random_lat_long_delta() / 5 alt = self.walker.pol_alt + random_alt_delta() / 2 self.bot.api.set_position(lat, lon, alt) else: self.walker = PolylineWalker(self.bot, self.destination[0], self.destination[1]) self.walker.step() dst = distance(self.bot.position[0], self.bot.position[1], self.destination[0], self.destination[1]) if dst < 1: forts = self.get_forts() circle = (self.destination[0], self.destination[1], Constants.MAX_DISTANCE_FORT_IS_REACHABLE) cluster = self.get_cluster(forts, circle) self.logger.info("Arrived at destination: %s forts, %s lured.", cluster[3], cluster[2]) self.stay_until = now + self.config_camping_time return WorkerResult.RUNNING
def walker_factory(name, bot, dest_lat, dest_lng, *args, **kwargs): ''' Charlie and the Walker Factory ''' if 'StepWalker' == name: ret = StepWalker(bot, dest_lat, dest_lng) elif 'PolylineWalker' == name: try: ret = PolylineWalker(bot, dest_lat, dest_lng) except: ret = StepWalker(bot, dest_lat, dest_lng) return ret
def test_teleport(self): walk_max = self.bot.config.walk_max walk_min = self.bot.config.walk_min precision = 0.0 speed = float("inf") self.bot.config.walk_max = 4 self.bot.config.walk_min = 2 pw = PolylineWalker(self.bot, ex_dest[0], ex_dest[1], precision=precision) self.assertEqual(pw.dest_lat, ex_dest[0], 'dest_lat did not match') self.assertEqual(pw.dest_lng, ex_dest[1], 'dest_lng did not match') finishedWalking = pw.step(speed=speed) self.assertTrue(finishedWalking, 'step should return True') distance = Geodesic.WGS84.Inverse(ex_dest[0], ex_dest[1], self.bot.position[0], self.bot.position[1])["s12"] self.assertTrue(0.0 <= distance <= (pw.precision + pw.epsilon)) self.polyline._last_pos = self.polyline.destination self.assertTrue(abs(self.polyline.get_alt() - self.bot.position[2]) <= 1) self.bot.config.walk_max = walk_max self.bot.config.walk_min = walk_min
def test_stay_put(self): altitude = 429.5 self.bot.position = [47.1706378, 8.5167405, altitude] walk_max = self.bot.config.walk_max walk_min = self.bot.config.walk_min precision = 0.0 speed = 0.0 self.bot.config.walk_max = 4 self.bot.config.walk_min = 2 pw = PolylineWalker(self.bot, ex_dest[0], ex_dest[1], precision=precision) self.assertEqual(pw.dest_lat, ex_dest[0], 'dest_lat did not match') self.assertEqual(pw.dest_lng, ex_dest[1], 'dest_lng did not match') finishedWalking = pw.step(speed=speed) self.assertFalse(finishedWalking, 'step should return False') distance = Geodesic.WGS84.Inverse(ex_orig[0], ex_orig[1], self.bot.position[0], self.bot.position[1])["s12"] self.assertTrue(0.0 <= distance <= (pw.precision + pw.epsilon)) self.assertTrue(altitude - 1 <= self.bot.position[2] <= altitude + 1) self.bot.config.walk_max = walk_max self.bot.config.walk_min = walk_min
def work(self): if not self.enabled: return WorkerResult.SUCCESS now = time.time() if now < self.move_until: return WorkerResult.SUCCESS if 0 < self.stay_until < now: self.cluster = None self.stay_until = 0 self.move_until = now + self.config_moving_time if self.config_moving_time > 0: return WorkerResult.SUCCESS # Let's make sure we have balls before we sit at a lure! # See also catch_pokemon.py if self.get_pokeball_count() <= 0: self.emit_event( 'refuse_to_sit', formatted='No pokeballs left, refuse to sit at lure!', ) # Move away from lures for a time self.cluster = None self.stay_until = 0 self.move_until = now + max(self.config_moving_time, NO_BALLS_MOVING_TIME) return WorkerResult.SUCCESS forts = self.get_forts() if self.cluster is None: if self.clusters is None: self.clusters = self.get_clusters(forts.values()) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: self.cluster = available_clusters[0] self.walker = PolylineWalker(self.bot, self.cluster["center"][0], self.cluster["center"][1]) self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event( "new_destination", formatted= 'New destination at {distance:.2f} meters: {size} forts, {lured} lured' .format(**self.cluster)) else: return WorkerResult.SUCCESS self.update_cluster_distance(self.cluster) self.update_cluster_lured(self.cluster, forts) if self.stay_until >= now: if self.no_log_until < now: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event( "staying_at_destination", formatted= 'Staying at destination: {size} forts, {lured} lured'. format(**self.cluster)) if self.cluster["lured"] == 0: self.stay_until -= NO_LURED_TIME_MALUS self.walker.step(speed=0) elif self.walker.step(): self.stay_until = now + self.config_camping_time self.emit_event( "arrived_at_destination", formatted="Arrived at destination: {size} forts, {lured} lured" .format(**self.cluster)) elif self.no_log_until < now: if self.cluster["lured"] == 0: self.cluster = None self.emit_event("reset_destination", formatted="Lures gone! Resetting destination!") else: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event( "moving_to_destination", formatted= "Moving to destination at {distance:.2f} meters: {size} forts, {lured} lured" .format(**self.cluster)) return WorkerResult.RUNNING
class CampFort(BaseTask): SUPPORTED_TASK_API_VERSION = 1 def __init__(self, bot, config): super(CampFort, self).__init__(bot, config) def initialize(self): self.destination = None self.stay_until = 0 self.move_until = 0 self.last_position_update = 0 self.walker = None self.config_max_distance = self.config.get("max_distance", 2000) self.config_min_forts_count = self.config.get("min_forts_count", 2) self.config_min_lured_forts_count = self.config.get("min_lured_forts_count", 1) self.config_camping_time = self.config.get("camping_time", 1800) self.config_moving_time = self.config.get("moving_time", 600) def work(self): if not self.enabled: return WorkerResult.SUCCESS now = time.time() if now < self.move_until: return WorkerResult.SUCCESS if 0 < self.stay_until < now: self.destination = None self.stay_until = 0 self.move_until = now + self.config_moving_time if self.config_moving_time > 0: return WorkerResult.SUCCESS if self.destination is None: forts = self.get_forts() forts_clusters = self.get_forts_clusters(forts) if len(forts_clusters) > 0: self.destination = forts_clusters[0] self.logger.info("New destination at %s meters: %s forts, %s lured.", int(self.destination[4]), self.destination[3], self.destination[2]) else: # forts = [f for f in forts if f.get("cooldown_complete_timestamp_ms", 0) < now * 1000] # fort = min(forts, key=lambda f: self.dist(self.bot.position, f)) # self.destination = (fort["latitude"], fort["longitude"]) return WorkerResult.SUCCESS if (now - self.last_position_update) < 1: return WorkerResult.RUNNING else: self.last_position_update = now if self.stay_until >= now: lat = self.destination[0] + random_lat_long_delta() / 5 lon = self.destination[1] + random_lat_long_delta() / 5 alt = self.walker.pol_alt + random_alt_delta() / 2 self.bot.api.set_position(lat, lon, alt) else: self.walker = PolylineWalker(self.bot, self.destination[0], self.destination[1]) self.walker.step() dst = distance(self.bot.position[0], self.bot.position[1], self.destination[0], self.destination[1]) if dst < 1: forts = self.get_forts() circle = (self.destination[0], self.destination[1], Constants.MAX_DISTANCE_FORT_IS_REACHABLE) cluster = self.get_cluster(forts, circle) self.logger.info("Arrived at destination: %s forts, %s lured.", cluster[3], cluster[2]) self.stay_until = now + self.config_camping_time return WorkerResult.RUNNING def get_forts(self): radius = self.config_max_distance + Constants.MAX_DISTANCE_FORT_IS_REACHABLE forts = [f for f in self.bot.cell["forts"] if ("latitude" in f) and ("type" in f)] forts = [f for f in forts if self.dist(self.bot.start_position, f) <= radius] return forts def get_forts_clusters(self, forts): clusters = [] points = self.get_all_snap_points(forts) for c1, c2, fort1, fort2 in points: cluster_1 = self.get_cluster(forts, c1) cluster_2 = self.get_cluster(forts, c2) cluster_key_1 = self.get_cluster_key(cluster_1) cluster_key_2 = self.get_cluster_key(cluster_2) radius = Constants.MAX_DISTANCE_FORT_IS_REACHABLE if cluster_key_1 >= cluster_key_2: cluster = cluster_1 while True: new_circle, _ = self.get_enclosing_circles(fort1, fort2, radius - 1) if not new_circle: break new_cluster = self.get_cluster(forts, new_circle) if new_cluster[3] < cluster[3]: break cluster = new_cluster radius -= 1 else: cluster = cluster_2 while True: _, new_circle = self.get_enclosing_circles(fort1, fort2, radius - 1) if not new_circle: break new_cluster = self.get_cluster(forts, new_circle) if new_cluster[3] < cluster[3]: break cluster = new_cluster radius -= 1 clusters.append(cluster) clusters = [c for c in clusters if c[2] >= self.config_min_lured_forts_count] clusters = [c for c in clusters if c[3] >= self.config_min_forts_count] clusters.sort(key=lambda c: self.get_cluster_key(c), reverse=True) return clusters def get_all_snap_points(self, forts): points = [] radius = Constants.MAX_DISTANCE_FORT_IS_REACHABLE for i in range(0, len(forts)): for j in range(i + 1, len(forts)): c1, c2 = self.get_enclosing_circles(forts[i], forts[j], radius) if c1 and c2: points.append((c1, c2, forts[i], forts[j])) return points def get_enclosing_circles(self, fort1, fort2, radius): # This is an approximation which is good enough for us # since we are dealing with small distances x1, y1 = coord2merc(fort1["latitude"], fort1["longitude"]) x2, y2 = coord2merc(fort2["latitude"], fort2["longitude"]) dx = x2 - x1 dy = y2 - y1 d = math.sqrt(dx ** 2 + dy ** 2) if (d == 0) or (d > 2 * radius): return None, None cx, cy = (x1 + x2) / 2, (y1 + y2) / 2 cd = math.sqrt(radius ** 2 - (d / 2) ** 2) c1 = merc2coord((cx - cd * dy / d, cy + cd * dx / d)) + (radius,) c2 = merc2coord((cx + cd * dy / d, cy - cd * dx / d)) + (radius,) return c1, c2 def get_cluster(self, forts, circle): forts_in_circle = [f for f in forts if self.dist(circle, f) <= circle[2]] count = len(forts_in_circle) lured = len([f for f in forts_in_circle if "active_fort_modifier" in f]) dst = distance(self.bot.position[0], self.bot.position[1], circle[0], circle[1]) return (circle[0], circle[1], lured, count, dst) def get_cluster_key(self, cluster): return (cluster[2], cluster[3], -cluster[4]) def dist(self, location, fort): return distance(location[0], location[1], fort["latitude"], fort["longitude"])
def work(self): if not self.enabled: return WorkerResult.SUCCESS if self.bot.catch_disabled: if not hasattr(self.bot,"camper_disabled_global_warning") or \ (hasattr(self.bot,"camper_disabled_global_warning") and not self.bot.camper_disabled_global_warning): self.logger.info("All catching tasks are currently disabled until {}. Camping of lured forts disabled till then.".format(self.bot.catch_resume_at.strftime("%H:%M:%S"))) self.bot.camper_disabled_global_warning = True return WorkerResult.SUCCESS else: self.bot.camper_disabled_global_warning = False if self.bot.softban: if not hasattr(self.bot, "camper_softban_global_warning") or \ (hasattr(self.bot, "camper_softban_global_warning") and not self.bot.camper_softban_global_warning): self.logger.info("Possible softban! Not camping forts till fixed.") self.bot.camper_softban_global_warning = True return WorkerResult.SUCCESS else: self.bot.softban_global_warning = False now = time.time() if now < self.move_until: return WorkerResult.SUCCESS if 0 < self.stay_until < now: self.cluster = None self.stay_until = 0 self.move_until = now + self.config_moving_time if self.config_moving_time > 0: return WorkerResult.SUCCESS # Let's make sure we have balls before we sit at a lure! # See also catch_pokemon.py if self.get_pokeball_count() <= 0: self.emit_event( 'refuse_to_sit', formatted='No pokeballs left, refuse to sit at lure!', ) # Move away from lures for a time self.cluster = None self.stay_until = 0 self.move_until = now + max(self.config_moving_time, NO_BALLS_MOVING_TIME) return WorkerResult.SUCCESS forts = self.get_forts() if self.cluster is None: if self.clusters is None: self.clusters = self.get_clusters(forts.values()) # self.logger.info("Forts: {}".format(len(forts))) # self.logger.info("Checking {} clusters for availiblity....".format(len(self.clusters))) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: self.cluster = available_clusters[0] self.walker = PolylineWalker(self.bot, self.cluster["center"][0], self.cluster["center"][1]) self.no_log_until = now + LOG_TIME_INTERVAL self.no_recheck_cluster_until = now + NO_BALLS_MOVING_TIME self.emit_event("new_destination", formatted='New destination at {distance:.2f} meters: {size} forts, {lured} lured'.format(**self.cluster)) else: # self.logger.info("No clusters found.") self.cluster = None self.clusters = None return WorkerResult.SUCCESS # We can check if the cluster is still the best elif self.no_recheck_cluster_until < now: self.clusters = self.get_clusters(forts.values()) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: if self.cluster is not available_clusters[0]: self.cluster = available_clusters[0] self.stay_until = 0 self.emit_event("new_destination", formatted='Better destination found at {distance:.2f} meters: {size} forts, {lured} lured'.format(**self.cluster)) self.no_recheck_cluster_until = now + NO_BALLS_MOVING_TIME self.update_cluster_distance(self.cluster) self.update_cluster_lured(self.cluster, forts) if self.stay_until >= now: if self.no_log_until < now: self.no_log_until = now + LOG_TIME_INTERVAL self.bot.camping_forts = True self.emit_event("staying_at_destination", formatted='Staying at destination: {size} forts, {lured} lured'.format(**self.cluster)) if self.cluster["lured"] == 0: self.bot.camping_forts = False # Allow hunter to move self.stay_until -= NO_LURED_TIME_MALUS self.walker.step(speed=0) elif self.walker.step(): self.stay_until = now + self.config_camping_time self.bot.camping_forts = True self.emit_event("arrived_at_destination", formatted="Arrived at destination: {size} forts, {lured} lured.".format(**self.cluster)) elif self.no_log_until < now: if self.cluster["lured"] == 0: self.cluster = None self.bot.camping_forts = False self.emit_event("reset_destination", formatted="Lures gone! Resetting destination!") else: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event("moving_to_destination", formatted="Moving to destination at {distance:.2f} meters: {size} forts, {lured} lured".format(**self.cluster)) return WorkerResult.RUNNING
class CampFort(BaseTask): SUPPORTED_TASK_API_VERSION = 1 def __init__(self, bot, config): super(CampFort, self).__init__(bot, config) def initialize(self): self.clusters = None self.cluster = None self.walker = None self.stay_until = 0 self.move_until = 0 self.no_log_until = 0 self.config_max_distance = self.config.get("max_distance", 2000) self.config_min_forts_count = self.config.get("min_forts_count", 2) self.config_min_lured_forts_count = self.config.get( "min_lured_forts_count", 1) self.config_camping_time = self.config.get("camping_time", 1800) self.config_moving_time = self.config.get("moving_time", 600) def work(self): if not self.enabled: return WorkerResult.SUCCESS now = time.time() if now < self.move_until: return WorkerResult.SUCCESS if 0 < self.stay_until < now: self.cluster = None self.stay_until = 0 self.move_until = now + self.config_moving_time if self.config_moving_time > 0: return WorkerResult.SUCCESS # Let's make sure we have balls before we sit at a lure! # See also catch_pokemon.py if self.get_pokeball_count() <= 0: self.emit_event( 'refuse_to_sit', formatted='No pokeballs left, refuse to sit at lure!', ) # Move away from lures for a time self.cluster = None self.stay_until = 0 self.move_until = now + max(self.config_moving_time, NO_BALLS_MOVING_TIME) return WorkerResult.SUCCESS forts = self.get_forts() if self.cluster is None: if self.clusters is None: self.clusters = self.get_clusters(forts.values()) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: self.cluster = available_clusters[0] self.walker = PolylineWalker(self.bot, self.cluster["center"][0], self.cluster["center"][1]) self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event( "new_destination", formatted= 'New destination at {distance:.2f} meters: {size} forts, {lured} lured' .format(**self.cluster)) else: return WorkerResult.SUCCESS self.update_cluster_distance(self.cluster) self.update_cluster_lured(self.cluster, forts) if self.stay_until >= now: if self.no_log_until < now: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event( "staying_at_destination", formatted= 'Staying at destination: {size} forts, {lured} lured'. format(**self.cluster)) if self.cluster["lured"] == 0: self.stay_until -= NO_LURED_TIME_MALUS self.walker.step(speed=0) elif self.walker.step(): self.stay_until = now + self.config_camping_time self.emit_event( "arrived_at_destination", formatted="Arrived at destination: {size} forts, {lured} lured" .format(**self.cluster)) elif self.no_log_until < now: if self.cluster["lured"] == 0: self.cluster = None self.emit_event("reset_destination", formatted="Lures gone! Resetting destination!") else: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event( "moving_to_destination", formatted= "Moving to destination at {distance:.2f} meters: {size} forts, {lured} lured" .format(**self.cluster)) return WorkerResult.RUNNING def get_pokeball_count(self): return sum([ inventory.items().get(ball.value).count for ball in [Item.ITEM_POKE_BALL, Item.ITEM_GREAT_BALL, Item.ITEM_ULTRA_BALL] ]) def get_forts(self): radius = self.config_max_distance + Constants.MAX_DISTANCE_FORT_IS_REACHABLE forts = [ f for f in self.bot.cell["forts"] if ("latitude" in f) and ("type" in f) ] forts = [ f for f in forts if self.get_distance(self.bot.start_position, f) <= radius ] return {f["id"]: f for f in forts} def get_available_clusters(self, forts): for cluster in self.clusters: self.update_cluster_distance(cluster) self.update_cluster_lured(cluster, forts) available_clusters = [ c for c in self.clusters if c["lured"] >= self.config_min_lured_forts_count ] available_clusters = [ c for c in available_clusters if c["size"] >= self.config_min_forts_count ] available_clusters.sort(key=lambda c: self.get_cluster_key(c), reverse=True) return available_clusters def get_clusters(self, forts): clusters = [] points = self.get_all_snap_points(forts) for c1, c2, fort1, fort2 in points: cluster_1 = self.get_cluster(forts, c1) cluster_2 = self.get_cluster(forts, c2) self.update_cluster_distance(cluster_1) self.update_cluster_distance(cluster_2) key_1 = self.get_cluster_key(cluster_1) key_2 = self.get_cluster_key(cluster_2) radius = Constants.MAX_DISTANCE_FORT_IS_REACHABLE if key_1 >= key_2: cluster = cluster_1 while True: new_circle, _ = self.get_enclosing_circles( fort1, fort2, radius - 1) if not new_circle: break new_cluster = self.get_cluster(cluster["forts"], new_circle) if len(new_cluster["forts"]) < len(cluster["forts"]): break cluster = new_cluster radius -= 1 else: cluster = cluster_2 while True: _, new_circle = self.get_enclosing_circles( fort1, fort2, radius - 1) if not new_circle: break new_cluster = self.get_cluster(cluster["forts"], new_circle) if len(new_cluster["forts"]) < len(cluster["forts"]): break cluster = new_cluster radius -= 1 clusters.append(cluster) return clusters def get_all_snap_points(self, forts): points = [] radius = Constants.MAX_DISTANCE_FORT_IS_REACHABLE for i in range(0, len(forts)): for j in range(i + 1, len(forts)): c1, c2 = self.get_enclosing_circles(forts[i], forts[j], radius) if c1 and c2: points.append((c1, c2, forts[i], forts[j])) return points def get_enclosing_circles(self, fort1, fort2, radius): x1, y1 = coord2merc(fort1["latitude"], fort1["longitude"]) x2, y2 = coord2merc(fort2["latitude"], fort2["longitude"]) dx = x2 - x1 dy = y2 - y1 d = math.sqrt(dx**2 + dy**2) if (d == 0) or (d > 2 * radius): return None, None cx, cy = (x1 + x2) / 2, (y1 + y2) / 2 cd = math.sqrt(radius**2 - (d / 2)**2) c1 = merc2coord((cx - cd * dy / d, cy + cd * dx / d)) + (radius, ) c2 = merc2coord((cx + cd * dy / d, cy - cd * dx / d)) + (radius, ) return c1, c2 def get_cluster(self, forts, circle): forts_in_circle = [ f for f in forts if self.get_distance(circle, f) <= circle[2] ] cluster = { "center": (circle[0], circle[1]), "distance": 0, "forts": forts_in_circle, "size": len(forts_in_circle), "lured": sum(1 for f in forts_in_circle if f.get("active_fort_modifier", None) is not None) } return cluster def get_cluster_key(self, cluster): return (cluster["lured"], cluster["size"], -cluster["distance"]) def update_cluster_distance(self, cluster): cluster["distance"] = great_circle(self.bot.position, cluster["center"]).meters def update_cluster_lured(self, cluster, forts): cluster["lured"] = sum(1 for f in cluster["forts"] if forts.get( f["id"], {}).get("active_fort_modifier", None) is not None) def get_distance(self, location, fort): return great_circle(location, (fort["latitude"], fort["longitude"])).meters
class CampFort(BaseTask): SUPPORTED_TASK_API_VERSION = 1 def __init__(self, bot, config): super(CampFort, self).__init__(bot, config) def initialize(self): self.clusters = None self.cluster = None self.walker = None self.bot.camping_forts = False self.stay_until = 0 self.move_until = 0 self.no_log_until = 0 self.no_recheck_cluster_until = 0 self.config_max_distance = self.config.get("max_distance", 2000) self.config_min_forts_count = self.config.get("min_forts_count", 2) self.config_min_lured_forts_count = self.config.get("min_lured_forts_count", 1) self.config_camping_time = self.config.get("camping_time", 1800) self.config_moving_time = self.config.get("moving_time", 600) def work(self): if not self.enabled: return WorkerResult.SUCCESS if self.bot.catch_disabled: if not hasattr(self.bot,"camper_disabled_global_warning") or \ (hasattr(self.bot,"camper_disabled_global_warning") and not self.bot.camper_disabled_global_warning): self.logger.info("All catching tasks are currently disabled until {}. Camping of lured forts disabled till then.".format(self.bot.catch_resume_at.strftime("%H:%M:%S"))) self.bot.camper_disabled_global_warning = True return WorkerResult.SUCCESS else: self.bot.camper_disabled_global_warning = False if self.bot.softban: if not hasattr(self.bot, "camper_softban_global_warning") or \ (hasattr(self.bot, "camper_softban_global_warning") and not self.bot.camper_softban_global_warning): self.logger.info("Possible softban! Not camping forts till fixed.") self.bot.camper_softban_global_warning = True return WorkerResult.SUCCESS else: self.bot.softban_global_warning = False now = time.time() if now < self.move_until: return WorkerResult.SUCCESS if 0 < self.stay_until < now: self.cluster = None self.stay_until = 0 self.move_until = now + self.config_moving_time if self.config_moving_time > 0: return WorkerResult.SUCCESS # Let's make sure we have balls before we sit at a lure! # See also catch_pokemon.py if self.get_pokeball_count() <= 0: self.emit_event( 'refuse_to_sit', formatted='No pokeballs left, refuse to sit at lure!', ) # Move away from lures for a time self.cluster = None self.stay_until = 0 self.move_until = now + max(self.config_moving_time, NO_BALLS_MOVING_TIME) return WorkerResult.SUCCESS forts = self.get_forts() if self.cluster is None: if self.clusters is None: self.clusters = self.get_clusters(forts.values()) # self.logger.info("Forts: {}".format(len(forts))) # self.logger.info("Checking {} clusters for availiblity....".format(len(self.clusters))) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: self.cluster = available_clusters[0] self.walker = PolylineWalker(self.bot, self.cluster["center"][0], self.cluster["center"][1]) self.no_log_until = now + LOG_TIME_INTERVAL self.no_recheck_cluster_until = now + NO_BALLS_MOVING_TIME self.emit_event("new_destination", formatted='New destination at {distance:.2f} meters: {size} forts, {lured} lured'.format(**self.cluster)) else: # self.logger.info("No clusters found.") self.cluster = None self.clusters = None return WorkerResult.SUCCESS # We can check if the cluster is still the best elif self.no_recheck_cluster_until < now: self.clusters = self.get_clusters(forts.values()) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: if self.cluster is not available_clusters[0]: self.cluster = available_clusters[0] self.stay_until = 0 self.emit_event("new_destination", formatted='Better destination found at {distance:.2f} meters: {size} forts, {lured} lured'.format(**self.cluster)) self.no_recheck_cluster_until = now + NO_BALLS_MOVING_TIME self.update_cluster_distance(self.cluster) self.update_cluster_lured(self.cluster, forts) if self.stay_until >= now: if self.no_log_until < now: self.no_log_until = now + LOG_TIME_INTERVAL self.bot.camping_forts = True self.emit_event("staying_at_destination", formatted='Staying at destination: {size} forts, {lured} lured'.format(**self.cluster)) if self.cluster["lured"] == 0: self.bot.camping_forts = False # Allow hunter to move self.stay_until -= NO_LURED_TIME_MALUS self.walker.step(speed=0) elif self.walker.step(): self.stay_until = now + self.config_camping_time self.bot.camping_forts = True self.emit_event("arrived_at_destination", formatted="Arrived at destination: {size} forts, {lured} lured.".format(**self.cluster)) elif self.no_log_until < now: if self.cluster["lured"] == 0: self.cluster = None self.bot.camping_forts = False self.emit_event("reset_destination", formatted="Lures gone! Resetting destination!") else: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event("moving_to_destination", formatted="Moving to destination at {distance:.2f} meters: {size} forts, {lured} lured".format(**self.cluster)) return WorkerResult.RUNNING def get_pokeball_count(self): return sum([inventory.items().get(ball.value).count for ball in [Item.ITEM_POKE_BALL, Item.ITEM_GREAT_BALL, Item.ITEM_ULTRA_BALL]]) def get_forts(self): radius = self.config_max_distance + Constants.MAX_DISTANCE_FORT_IS_REACHABLE forts = [f for f in self.bot.cell["forts"] if ("latitude" in f) and ("type" in f)] forts = [f for f in forts if self.get_distance(self.bot.start_position, f) <= radius] return {f["id"]: f for f in forts} def get_available_clusters(self, forts): for cluster in self.clusters: self.update_cluster_distance(cluster) self.update_cluster_lured(cluster, forts) available_clusters = [c for c in self.clusters if c["lured"] >= self.config_min_lured_forts_count] available_clusters = [c for c in available_clusters if c["size"] >= self.config_min_forts_count] available_clusters.sort(key=lambda c: self.get_cluster_key(c), reverse=True) return available_clusters def get_clusters(self, forts): clusters = [] points = self.get_all_snap_points(forts) for c1, c2, fort1, fort2 in points: cluster_1 = self.get_cluster(forts, c1) cluster_2 = self.get_cluster(forts, c2) self.update_cluster_distance(cluster_1) self.update_cluster_distance(cluster_2) key_1 = self.get_cluster_key(cluster_1) key_2 = self.get_cluster_key(cluster_2) radius = Constants.MAX_DISTANCE_FORT_IS_REACHABLE if key_1 >= key_2: cluster = cluster_1 while True: new_circle, _ = self.get_enclosing_circles(fort1, fort2, radius - 1) if not new_circle: break new_cluster = self.get_cluster(cluster["forts"], new_circle) if len(new_cluster["forts"]) < len(cluster["forts"]): break cluster = new_cluster radius -= 1 else: cluster = cluster_2 while True: _, new_circle = self.get_enclosing_circles(fort1, fort2, radius - 1) if not new_circle: break new_cluster = self.get_cluster(cluster["forts"], new_circle) if len(new_cluster["forts"]) < len(cluster["forts"]): break cluster = new_cluster radius -= 1 clusters.append(cluster) return clusters def get_all_snap_points(self, forts): points = [] radius = Constants.MAX_DISTANCE_FORT_IS_REACHABLE for i in range(0, len(forts)): for j in range(i + 1, len(forts)): c1, c2 = self.get_enclosing_circles(forts[i], forts[j], radius) if c1 and c2: points.append((c1, c2, forts[i], forts[j])) return points def get_enclosing_circles(self, fort1, fort2, radius): x1, y1 = coord2merc(fort1["latitude"], fort1["longitude"]) x2, y2 = coord2merc(fort2["latitude"], fort2["longitude"]) dx = x2 - x1 dy = y2 - y1 d = math.sqrt(dx ** 2 + dy ** 2) if (d == 0) or (d > 2 * radius): return None, None cx, cy = (x1 + x2) / 2, (y1 + y2) / 2 cd = math.sqrt(radius ** 2 - (d / 2) ** 2) c1 = merc2coord((cx - cd * dy / d, cy + cd * dx / d)) + (radius,) c2 = merc2coord((cx + cd * dy / d, cy - cd * dx / d)) + (radius,) return c1, c2 def get_cluster(self, forts, circle): forts_in_circle = [f for f in forts if self.get_distance(circle, f) <= circle[2]] cluster = {"center": (circle[0], circle[1]), "distance": 0, "forts": forts_in_circle, "size": len(forts_in_circle), "lured": sum(1 for f in forts_in_circle if f.get("active_fort_modifier", None) is not None)} return cluster def get_cluster_key(self, cluster): return (cluster["lured"], cluster["size"], -cluster["distance"]) def update_cluster_distance(self, cluster): cluster["distance"] = great_circle(self.bot.position, cluster["center"]).meters def update_cluster_lured(self, cluster, forts): cluster["lured"] = sum(1 for f in cluster["forts"] if forts.get(f["id"], {}).get("active_fort_modifier", None) is not None) def get_distance(self, location, fort): return great_circle(location, (fort["latitude"], fort["longitude"])).meters
def work(self): if not self.enabled: return WorkerResult.SUCCESS if self.bot.catch_disabled: if not hasattr(self.bot,"camper_disabled_global_warning") or \ (hasattr(self.bot,"camper_disabled_global_warning") and not self.bot.camper_disabled_global_warning): self.logger.info("All catching tasks are currently disabled until {}. Camping of lured forts disabled till then.".format(self.bot.catch_resume_at.strftime("%H:%M:%S"))) self.bot.camper_disabled_global_warning = True return WorkerResult.SUCCESS else: self.bot.camper_disabled_global_warning = False now = time.time() if now < self.move_until: return WorkerResult.SUCCESS if 0 < self.stay_until < now: self.cluster = None self.stay_until = 0 self.move_until = now + self.config_moving_time if self.config_moving_time > 0: return WorkerResult.SUCCESS # Let's make sure we have balls before we sit at a lure! # See also catch_pokemon.py if self.get_pokeball_count() <= 0: self.emit_event( 'refuse_to_sit', formatted='No pokeballs left, refuse to sit at lure!', ) # Move away from lures for a time self.cluster = None self.stay_until = 0 self.move_until = now + max(self.config_moving_time, NO_BALLS_MOVING_TIME) return WorkerResult.SUCCESS forts = self.get_forts() if self.cluster is None: if self.clusters is None: self.clusters = self.get_clusters(forts.values()) # self.logger.info("Forts: {}".format(len(forts))) # self.logger.info("Checking {} clusters for availiblity....".format(len(self.clusters))) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: self.cluster = available_clusters[0] self.walker = PolylineWalker(self.bot, self.cluster["center"][0], self.cluster["center"][1]) self.no_log_until = now + LOG_TIME_INTERVAL self.no_recheck_cluster_until = now + NO_BALLS_MOVING_TIME self.emit_event("new_destination", formatted='New destination at {distance:.2f} meters: {size} forts, {lured} lured'.format(**self.cluster)) else: # self.logger.info("No clusters found.") self.cluster = None self.clusters = None return WorkerResult.SUCCESS # We can check if the cluster is still the best elif self.no_recheck_cluster_until < now: self.clusters = self.get_clusters(forts.values()) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: if self.cluster is not available_clusters[0]: self.cluster = available_clusters[0] self.stay_until = 0 self.emit_event("new_destination", formatted='Better destination found at {distance:.2f} meters: {size} forts, {lured} lured'.format(**self.cluster)) self.no_recheck_cluster_until = now + NO_BALLS_MOVING_TIME self.update_cluster_distance(self.cluster) self.update_cluster_lured(self.cluster, forts) if self.stay_until >= now: if self.no_log_until < now: self.no_log_until = now + LOG_TIME_INTERVAL self.bot.camping_forts = True self.emit_event("staying_at_destination", formatted='Staying at destination: {size} forts, {lured} lured'.format(**self.cluster)) if self.cluster["lured"] == 0: self.bot.camping_forts = False # Allow hunter to move self.stay_until -= NO_LURED_TIME_MALUS self.walker.step(speed=0) elif self.walker.step(): self.stay_until = now + self.config_camping_time self.bot.camping_forts = True self.emit_event("arrived_at_destination", formatted="Arrived at destination: {size} forts, {lured} lured.".format(**self.cluster)) elif self.no_log_until < now: if self.cluster["lured"] == 0: self.cluster = None self.bot.camping_forts = False self.emit_event("reset_destination", formatted="Lures gone! Resetting destination!") else: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event("moving_to_destination", formatted="Moving to destination at {distance:.2f} meters: {size} forts, {lured} lured".format(**self.cluster)) return WorkerResult.RUNNING
def work(self): if not self.enabled: return WorkerResult.SUCCESS if self.config_disabled_while_camping and hasattr( self.bot, 'camping_forts') and self.bot.camping_forts: return WorkerResult.SUCCESS if not self.config_lock_on_target: self.bot.hunter_locked_target = None if self.no_hunt_until != None and self.no_hunt_until > time.time(): # No hunting now, cooling down return WorkerResult.SUCCESS else: # Resume hunting self.no_hunt_until = None if self.bot.catch_disabled: if not hasattr(self.bot,"hunter_disabled_global_warning") or \ (hasattr(self.bot,"hunter_disabled_global_warning") and not self.bot.hunter_disabled_global_warning): self.logger.info( "All catching tasks are currently disabled until {}. Pokemon Hunter will resume when catching tasks are re-enabled" .format(self.bot.catch_resume_at.strftime("%H:%M:%S"))) self.bot.hunter_disabled_global_warning = True return WorkerResult.SUCCESS else: self.bot.hunter_disabled_global_warning = False if self.bot.softban: if not hasattr(self.bot, "softban_global_warning") or \ (hasattr(self.bot, "softban_global_warning") and not self.bot.softban_global_warning): self.logger.info( "Possible softban! Not trying to catch Pokemon.") self.bot.softban_global_warning = True return WorkerResult.SUCCESS else: self.bot.softban_global_warning = False if self.get_pokeball_count() <= 0: self.destination = None self.last_cell_id = None return WorkerResult.SUCCESS if self.destination is not None: if self.destination_caught(): self.logger.info( "We found a %(name)s while hunting. Aborting the current search.", self.destination) self.destination = None wait = uniform(120, 600) self.no_hunt_until = time.time() + wait self.logger.info("Hunting on cooldown until {}.".format( (datetime.now() + timedelta(seconds=wait)).strftime("%H:%M:%S"))) return WorkerResult.SUCCESS now = time.time() pokemons = self.get_nearby_pokemons() pokemons = filter(lambda x: x["pokemon_id"] not in self.recent_tries, pokemons) if self.destination is None: worth_pokemons = self.get_worth_pokemons(pokemons) if len(worth_pokemons) > 0: # Pick a random target from the list random.shuffle(worth_pokemons) # Prevents the bot from looping the same Pokemon self.destination = worth_pokemons[0] self.lost_counter = 0 self.hunt_started_at = datetime.now() self.logger.info( "New destination at %(distance).2f meters: %(name)s", self.destination) if self._is_vip_pokemon(self.destination): self.logger.info("This is a VIP Pokemon! Starting hunt.") if self.config_lock_on_target: self.bot.hunter_locked_target = self.destination elif self._is_needed_pokedex(self.destination): self.logger.info( "I need a %(name)s to complete the Pokedex! I have %(candies)s candies.", self.destination) if self.config_lock_on_target and not self.config_lock_vip_only: self.bot.hunter_locked_target = self.destination else: self.bot.hunter_locked_target = None self.no_log_until = now + 60 if self.destination["s2_cell_id"] != self.search_cell_id: self.search_points = self.get_search_points( self.destination["s2_cell_id"]) self.walker = PolylineWalker(self.bot, self.search_points[0][0], self.search_points[0][1]) self.search_cell_id = self.destination["s2_cell_id"] self.search_points = self.search_points[ 1:] + self.search_points[:1] else: if self.no_log_until < now: # Show like "Pidgey (12), Zubat(2)" names = Counter((p["name"] for p in pokemons)) sorted(names) # unicode object, no lower? , key=str.lower) self.logger.info( "There is no nearby pokemon worth hunting down [%s]", ", ".join('{}({})'.format(key, val) for key, val in names.items())) self.no_log_until = now + 120 self.destination = None wait = uniform(120, 600) self.no_hunt_until = now + wait self.logger.info("Will look again around {}.".format( (datetime.now() + timedelta(seconds=wait)).strftime("%H:%M:%S"))) self.last_cell_id = None return WorkerResult.SUCCESS if self.config_lock_on_target and not self.config_lock_vip_only: if self.bot.hunter_locked_target == None: self.logger.info( "We found a %(name)s while hunting. Aborting the current search.", self.destination) self.destination = None wait = uniform(120, 600) self.no_hunt_until = now + wait self.logger.info("Hunting on cooldown until {}.".format( (datetime.now() + timedelta(seconds=wait)).strftime("%H:%M:%S"))) return WorkerResult.SUCCESS if any(self.destination["encounter_id"] == p["encounter_id"] for p in self.bot.cell["catchable_pokemons"] + self.bot.cell["wild_pokemons"]): self.destination = None elif self.walker.step(): if not any(self.destination["encounter_id"] == p["encounter_id"] for p in pokemons): self.lost_counter += 1 else: self.lost_counter = 0 if self.lost_counter >= 3: self.logger.info("I haven't found %(name)s", self.destination) self.bot.hunter_locked_target = None self.destination = None wait = uniform(120, 600) self.no_hunt_until = now + wait self.logger.info("Hunting on cooldown until {}.".format( (datetime.now() + timedelta(seconds=wait)).strftime("%H:%M:%S"))) else: self.logger.info("Now searching for %(name)s", self.destination) self.walker = StepWalker(self.bot, self.search_points[0][0], self.search_points[0][1]) self.search_points = self.search_points[ 1:] + self.search_points[:1] elif self.no_log_until < now: distance = great_circle( self.bot.position, (self.walker.dest_lat, self.walker.dest_lng)).meters if round(distance, 2) == self.distance_to_target: # Hmm, not moved toward the Pokemon? self.distance_counter += 1 else: self.distance_counter = 0 if self.distance_counter >= 3: # Ignore last 3 if len(self.recent_tries) > 3: self.recent_tries.pop() self.recent_tries.append(self.destination['pokemon_id']) self.logger.info( "I cant move toward %(name)s! Aborting search.", self.destination) self.bot.hunter_locked_target = None self.destination = None wait = uniform(120, 600) self.no_hunt_until = now + wait self.logger.info("Hunting on cooldown until {}.".format( (datetime.now() + timedelta(seconds=wait)).strftime("%H:%M:%S"))) return WorkerResult.ERROR else: self.logger.info("Moving to destination at %s meters: %s", round(distance, 2), self.destination["name"]) # record the new distance... self.distance_to_target = round(distance, 2) if self.config_lock_on_target and not self.config_lock_vip_only: # Just to ensure we stay on target self.bot.hunter_locked_target = self.destination self.no_log_until = now + 30 return WorkerResult.RUNNING
def work(self): if not self.enabled: return WorkerResult.SUCCESS now = time.time() if now < self.move_until: return WorkerResult.SUCCESS if 0 < self.stay_until < now: self.cluster = None self.stay_until = 0 self.move_until = now + self.config_moving_time if self.config_moving_time > 0: return WorkerResult.SUCCESS # Let's make sure we have balls before we sit at a lure! # See also catch_pokemon.py if self.get_pokeball_count() <= 0: self.emit_event( 'refuse_to_sit', formatted='No pokeballs left, refuse to sit at lure!', ) # Move away from lures for a time self.cluster = None self.stay_until = 0 self.move_until = now + max(self.config_moving_time, NO_BALLS_MOVING_TIME) return WorkerResult.SUCCESS forts = self.get_forts() if self.cluster is None: if self.clusters is None: self.clusters = self.get_clusters(forts.values()) available_clusters = self.get_available_clusters(forts) if len(available_clusters) > 0: self.cluster = available_clusters[0] self.walker = PolylineWalker(self.bot, self.cluster["center"][0], self.cluster["center"][1]) self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event("new_destination", formatted='New destination at {distance:.2f} meters: {size} forts, {lured} lured'.format(**self.cluster)) else: return WorkerResult.SUCCESS self.update_cluster_distance(self.cluster) self.update_cluster_lured(self.cluster, forts) if self.stay_until >= now: if self.no_log_until < now: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event("staying_at_destination", formatted='Staying at destination: {size} forts, {lured} lured'.format(**self.cluster)) if self.cluster["lured"] == 0: self.stay_until -= NO_LURED_TIME_MALUS self.walker.step(speed=0) elif self.walker.step(): self.stay_until = now + self.config_camping_time self.emit_event("arrived_at_destination", formatted="Arrived at destination: {size} forts, {lured} lured".format(**self.cluster)) elif self.no_log_until < now: if self.cluster["lured"] == 0: self.cluster = None self.emit_event("reset_destination", formatted="Lures gone! Resetting destination!") else: self.no_log_until = now + LOG_TIME_INTERVAL self.emit_event("moving_to_destination", formatted="Moving to destination at {distance:.2f} meters: {size} forts, {lured} lured".format(**self.cluster)) return WorkerResult.RUNNING
def work(self): if not self.enabled: return WorkerResult.SUCCESS if self.bot.catch_disabled: if not hasattr(self.bot,"hunter_disabled_global_warning") or \ (hasattr(self.bot,"hunter_disabled_global_warning") and not self.bot.hunter_disabled_global_warning): self.logger.info( "All catching tasks are currently disabled until {}. Pokemon Hunter will resume when catching tasks are re-enabled" .format(self.bot.catch_resume_at.strftime("%H:%M:%S"))) self.bot.hunter_disabled_global_warning = True return WorkerResult.SUCCESS else: self.bot.hunter_disabled_global_warning = False if self.get_pokeball_count() <= 0: self.destination = None self.last_cell_id = None return WorkerResult.SUCCESS now = time.time() pokemons = self.get_nearby_pokemons() if self.destination is None: worth_pokemons = self.get_worth_pokemons(pokemons) if len(worth_pokemons) > 0: self.destination = worth_pokemons[0] self.lost_counter = 0 self.logger.info( "New destination at %(distance).2f meters: %(name)s", self.destination) self.no_log_until = now + 60 if self.destination["s2_cell_id"] != self.search_cell_id: self.search_points = self.get_search_points( self.destination["s2_cell_id"]) self.walker = PolylineWalker(self.bot, self.search_points[0][0], self.search_points[0][1]) self.search_cell_id = self.destination["s2_cell_id"] self.search_points = self.search_points[ 1:] + self.search_points[:1] else: if self.no_log_until < now: self.logger.info( "There is no nearby pokemon worth hunting down [%s]", ", ".join(p["name"] for p in pokemons)) self.no_log_until = now + 120 self.last_cell_id = None return WorkerResult.SUCCESS if any(self.destination["encounter_id"] == p["encounter_id"] for p in self.bot.cell["catchable_pokemons"] + self.bot.cell["wild_pokemons"]): self.destination = None elif self.walker.step(): if not any(self.destination["encounter_id"] == p["encounter_id"] for p in pokemons): self.lost_counter += 1 else: self.lost_counter = 0 if self.lost_counter >= 3: self.destination = None else: self.logger.info("Now searching for %(name)s", self.destination) self.walker = StepWalker(self.bot, self.search_points[0][0], self.search_points[0][1]) self.search_points = self.search_points[ 1:] + self.search_points[:1] elif self.no_log_until < now: distance = great_circle( self.bot.position, (self.walker.dest_lat, self.walker.dest_lng)).meters self.logger.info("Moving to destination at %s meters: %s", round(distance, 2), self.destination["name"]) self.no_log_until = now + 30 return WorkerResult.RUNNING