diff --git a/configs/config.json.cluster.example b/configs/config.json.cluster.example index 1bedbcbab9..5d4c741e35 100644 --- a/configs/config.json.cluster.example +++ b/configs/config.json.cluster.example @@ -48,6 +48,7 @@ "first_evolve_by": "cp", "evolve_above_cp": 500, "evolve_above_iv": 0.8, + "evolve_num_min": 5, "logic": "or", "evolve_speed": 20, "use_lucky_egg": false diff --git a/configs/config.json.example b/configs/config.json.example index 838acc1d4b..3576bf2a73 100644 --- a/configs/config.json.example +++ b/configs/config.json.example @@ -55,6 +55,7 @@ "first_evolve_by": "cp", "evolve_above_cp": 500, "evolve_above_iv": 0.8, + "evolve_num_min": 5, "logic": "or", "evolve_speed": 20, "use_lucky_egg": false diff --git a/configs/config.json.path.example b/configs/config.json.path.example index 2581862b31..254eff6be5 100644 --- a/configs/config.json.path.example +++ b/configs/config.json.path.example @@ -48,6 +48,7 @@ "first_evolve_by": "cp", "evolve_above_cp": 500, "evolve_above_iv": 0.8, + "evolve_num_min": 5, "logic": "or", "evolve_speed": 20, "use_lucky_egg": false diff --git a/configs/config.json.pokemon.example b/configs/config.json.pokemon.example index 2ad81a7369..c656a0a6c2 100644 --- a/configs/config.json.pokemon.example +++ b/configs/config.json.pokemon.example @@ -48,6 +48,7 @@ "first_evolve_by": "cp", "evolve_above_cp": 500, "evolve_above_iv": 0.8, + "evolve_num_min": 5, "logic": "or", "evolve_speed": 20, "use_lucky_egg": false diff --git a/pokemongo_bot/cell_workers/evolve_pokemon.py b/pokemongo_bot/cell_workers/evolve_pokemon.py index 4de40fdb7d..13299f0ed8 100644 --- a/pokemongo_bot/cell_workers/evolve_pokemon.py +++ b/pokemongo_bot/cell_workers/evolve_pokemon.py @@ -15,6 +15,7 @@ def initialize(self): self.first_evolve_by = self.config.get('first_evolve_by', 'cp') self.evolve_above_cp = self.config.get('evolve_above_cp', 500) self.evolve_above_iv = self.config.get('evolve_above_iv', 0.8) + self.evolve_num_min = self.config.get('evolve_num_min', 5) self.cp_iv_logic = self.config.get('logic', 'or') self.use_lucky_egg = self.config.get('use_lucky_egg', False) self._validate_config() @@ -27,29 +28,26 @@ def work(self): if not self._should_run(): return - evolve_list = self._sort_and_filter() - - if self.evolve_all[0] != 'all': - # filter out non-listed pokemons - evolve_list = filter(lambda x: x.name in self.evolve_all, evolve_list) - - cache = {} - for pokemon in evolve_list: - if pokemon.can_evolve_now(): - self._execute_pokemon_evolve(pokemon, cache) + cache = set() - def _should_run(self): - if not self.evolve_all or self.evolve_all[0] == 'none': - return False + evolve_list = self._sort_and_filter() + # filter out non-listed pokemons, top-tier pokemons and those with not enough candy + evolve_list = [x for x in evolve_list if self._is_evolvable(x, inventory.candies().deepcopy())] - # Evolve all is used - Use Lucky egg only at the first tick - if self.bot.tick_count is not 1 or not self.use_lucky_egg: - return True + # Don't evolve unless the evolvable candidates number is no less than evolve_num_min + if len(evolve_list) < self.evolve_num_min: + return - lucky_egg_count = self.bot.item_inventory_count(Item.ITEM_LUCKY_EGG.value) + if self.use_lucky_egg: + lucky_egg_count = self.bot.item_inventory_count(Item.ITEM_LUCKY_EGG.value) + # Sometimes remaining lucky egg count get changed, check again for sure + if lucky_egg_count <= 0: + self.emit_event( + 'skip_evolve', + formatted='Skipping evolve because has no lucky egg.' + ) + return - # Make sure the user has a lucky egg and skip if not - if lucky_egg_count > 0: response_dict_lucky_egg = self.bot.use_lucky_egg() if response_dict_lucky_egg: result = response_dict_lucky_egg.get('responses', {}).get('USE_ITEM_XP_BOOST', {}).get('result', 0) @@ -58,32 +56,45 @@ def _should_run(self): 'used_lucky_egg', formatted='Used lucky egg ({amount_left} left).', data={ - 'amount_left': lucky_egg_count - 1 + 'amount_left': lucky_egg_count - 1 } ) - return True else: self.emit_event( 'lucky_egg_error', level='error', formatted='Failed to use lucky egg!' ) - return False - else: - # Skipping evolve so they aren't wasted + return + + for pokemon in evolve_list: + self._execute_pokemon_evolve(pokemon, cache) + + def _should_run(self): + # Don't run after the first tick + # Lucky Egg should only be popped at the first tick + if not self.evolve_all or self.evolve_all[0] == 'none' or self.bot.tick_count is 1: + return False + + # Will skip evolving if user wants to use an egg and there is none + lucky_egg_count = self.bot.item_inventory_count(Item.ITEM_LUCKY_EGG.value) + if self.use_lucky_egg and lucky_egg_count <= 0: self.emit_event( 'skip_evolve', formatted='Skipping evolve because has no lucky egg.' ) + return False + # Otherwise try evolving + return True + def _sort_and_filter(self): pokemons = [] logic_to_function = { 'or': lambda pokemon: pokemon.cp >= self.evolve_above_cp or pokemon.iv >= self.evolve_above_iv, 'and': lambda pokemon: pokemon.cp >= self.evolve_above_cp and pokemon.iv >= self.evolve_above_iv } - for pokemon in inventory.pokemons().all(): if pokemon.id > 0 and pokemon.has_next_evolution() and (logic_to_function[self.cp_iv_logic](pokemon)): pokemons.append(pokemon) @@ -95,6 +106,22 @@ def _sort_and_filter(self): return pokemons + + def _is_evolvable(self, pokemon, candies): + # filter out non-listed pokemen + if self.evolve_all[0] != 'all' and pokemon.name not in self.evolve_all: + return False + + if not pokemon.has_seen_next_evolution(): + return False + + if candies.get(pokemon.pokemon_id).quantity >= pokemon.evolution_cost: + candies.get(pokemon.pokemon_id).consume(pokemon.evolution_cost) + return True + # not enough candies + return False + + def _execute_pokemon_evolve(self, pokemon, cache): if pokemon.name in cache: return False @@ -118,10 +145,11 @@ def _execute_pokemon_evolve(self, pokemon, cache): inventory.pokemons().remove(pokemon.id) pokemon = Pokemon(response_dict.get('responses', {}).get('EVOLVE_POKEMON', {}).get('evolved_pokemon_data', {})) inventory.pokemons().add(pokemon) + sleep(self.evolve_speed) return True else: # cache pokemons we can't evolve. Less server calls - cache[pokemon.name] = 1 + cache.add(pokemon.name) sleep(0.7) return False