Skip to content

Commit

Permalink
Evolve only if evolvable candidates no less than a certain number.
Browse files Browse the repository at this point in the history
Previously, when user configured use_lucky_egg as true, the bot will use
lucky egg even evolvale candidates is zero. That's kinda of
waste. Meanwhile, if user didn't configured use_lucky_egg, the bot will
try to evolve after sort by cp&iv, but sometimes no good potential
pokemon in that batch, it's better delay the evolution after a
while. By adding a config item evovle_num_min can cope above two
problems. The bot evolves only if evolvable candidates no less than a
certain number.

1. Evolve only if evolvable candidates no less than a certain number.

2. Dragoniar's configuration is abnormal in pokemon.json, which lack of
"Previous evolution(s)" attribute, while the other middle-tier pokemon
has.

Fixed some issues after: Refactor evolve_all worker PokemonGoF#2244

1. The refactoring try to sort by pokemon index desc which is not
good. For example, why Venusaur which is PokemonGoF#3 should be with lower
priority than Pidgey(PokemonGoF#16)?

2. The refactoring always use dict.get(key, {}).get(key, {}) which will
eventually return a {} which will cause side effect. It's better
fail fast when the dict has no attribute which is unexpected by the
developer.

3. The reafctoring try to use cache when the pokemon is not
evovlable. That developer doesn't know previously we didn't caculate the
candy before evovling, thus caused a lot of failure when evovling. After
caculating candy requirements by the refactoring and this patch, the
failure rarely happens. Thus cache is not necessary when the pokemon is
not evovlable.
  • Loading branch information
Zhou committed Aug 13, 2016
1 parent dbf26d5 commit 1e22ae1
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 26 deletions.
1 change: 1 addition & 0 deletions configs/config.json.cluster.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions configs/config.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions configs/config.json.path.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions configs/config.json.pokemon.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
80 changes: 54 additions & 26 deletions pokemongo_bot/cell_workers/evolve_pokemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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

0 comments on commit 1e22ae1

Please sign in to comment.