mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Fix up breeding
This commit is contained in:
parent
8dee48d966
commit
4f8108d61b
1 changed files with 62 additions and 30 deletions
|
@ -292,7 +292,7 @@ class MovesetSearch(object):
|
||||||
self.evolution_moves[evolution_chain] = move required for evolution
|
self.evolution_moves[evolution_chain] = move required for evolution
|
||||||
self.babies[egg_group_id] = set of baby pokemon
|
self.babies[egg_group_id] = set of baby pokemon
|
||||||
self.hatch_counters[pokemon] = hatch counter
|
self.hatch_counters[pokemon] = hatch counter
|
||||||
self.gender_rates[pokemon] = gender rate
|
self.gender_rates[evolution_chain] = gender rate
|
||||||
"""
|
"""
|
||||||
eg1 = tables.PokemonEggGroup
|
eg1 = tables.PokemonEggGroup
|
||||||
eg2 = aliased(tables.PokemonEggGroup)
|
eg2 = aliased(tables.PokemonEggGroup)
|
||||||
|
@ -324,7 +324,7 @@ class MovesetSearch(object):
|
||||||
item_baby_chains = set() # evolution chains with baby-trigger items
|
item_baby_chains = set() # evolution chains with baby-trigger items
|
||||||
for pokemon, evolution_chain, parent, g1, g2, baby_item, hatch_counter, gender_rate in query:
|
for pokemon, evolution_chain, parent, g1, g2, baby_item, hatch_counter, gender_rate in query:
|
||||||
self.hatch_counters[pokemon] = hatch_counter
|
self.hatch_counters[pokemon] = hatch_counter
|
||||||
self.gender_rates[pokemon] = gender_rate
|
self.gender_rates[evolution_chain] = gender_rate
|
||||||
if g1 in bad_groups:
|
if g1 in bad_groups:
|
||||||
unbreedable[pokemon] = evolution_chain
|
unbreedable[pokemon] = evolution_chain
|
||||||
else:
|
else:
|
||||||
|
@ -483,9 +483,9 @@ class MovesetSearch(object):
|
||||||
return success
|
return success
|
||||||
for group in goal_egg_groups:
|
for group in goal_egg_groups:
|
||||||
handle(group, self.goal_moves, ())
|
handle(group, self.goal_moves, ())
|
||||||
for moves in powerset(self.goal_moves.difference(self.egg_moves)):
|
for moves in powerset(self.goal_moves):
|
||||||
if moves:
|
if moves:
|
||||||
breeds_required[group][frozenset(moves) | self.egg_moves] = 1
|
breeds_required[group][frozenset(moves)] = 1
|
||||||
self.breeds_required = breeds_required
|
self.breeds_required = breeds_required
|
||||||
|
|
||||||
if self.debug:
|
if self.debug:
|
||||||
|
@ -567,7 +567,7 @@ class MovesetSearch(object):
|
||||||
###
|
###
|
||||||
|
|
||||||
default_costs = {
|
default_costs = {
|
||||||
# Costs for learning a move in verious ways
|
# Costs for learning a move in various ways
|
||||||
'level-up': 20, # The normal way
|
'level-up': 20, # The normal way
|
||||||
'machine': 40, # Machines are slightly inconvenient.
|
'machine': 40, # Machines are slightly inconvenient.
|
||||||
'machine-once': 2000, # before gen. 5, TMs only work once. Avoid.
|
'machine-once': 2000, # before gen. 5, TMs only work once. Avoid.
|
||||||
|
@ -592,7 +592,7 @@ default_costs = {
|
||||||
'form-change': 100,
|
'form-change': 100,
|
||||||
|
|
||||||
# Other actions.
|
# Other actions.
|
||||||
# Breeding should cost more than 3 times than a lv-up/machine/tutor move.
|
# Breeding should cost more than 3 times a lv-up/machine/tutor move.
|
||||||
'evolution': 100, # We have to do this anyway, usually.
|
'evolution': 100, # We have to do this anyway, usually.
|
||||||
'evolution-delayed': 50, # *in addition* to evolution. Who wants to mash B on every level.
|
'evolution-delayed': 50, # *in addition* to evolution. Who wants to mash B on every level.
|
||||||
'breed': 400, # Breeding's a pain.
|
'breed': 400, # Breeding's a pain.
|
||||||
|
@ -620,7 +620,7 @@ default_costs = {
|
||||||
class Facade(object):
|
class Facade(object):
|
||||||
@property
|
@property
|
||||||
def pokemon(self):
|
def pokemon(self):
|
||||||
return self.search.get_by_id(tables.Pokemon, self.pokemon_)
|
return self.search.session.query(tables.Pokemon).filter_by(id=self.pokemon_).one()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def version_group(self):
|
def version_group(self):
|
||||||
|
@ -768,7 +768,7 @@ class PokemonNode(Node, Facade, namedtuple('PokemonNode',
|
||||||
level_difference = level - self.level
|
level_difference = level - self.level
|
||||||
if level_difference > 0 or (
|
if level_difference > 0 or (
|
||||||
level_difference == 0 and self.new_level):
|
level_difference == 0 and self.new_level):
|
||||||
cost += level_difference * search.costs['per-level']
|
cost += level - self.level * search.costs['per-level']
|
||||||
yield self._learn(move, method, cost,
|
yield self._learn(move, method, cost,
|
||||||
level=level, new_level=True)
|
level=level, new_level=True)
|
||||||
else:
|
else:
|
||||||
|
@ -870,14 +870,29 @@ class PokemonNode(Node, Facade, namedtuple('PokemonNode',
|
||||||
cost = search.costs['breed']
|
cost = search.costs['breed']
|
||||||
cost += search.costs['egg'] * len(moves)
|
cost += search.costs['egg'] * len(moves)
|
||||||
cost += search.costs['breed-penalty'] * len(search.egg_moves - moves)
|
cost += search.costs['breed-penalty'] * len(search.egg_moves - moves)
|
||||||
for group in egg_groups:
|
gender_rate = search.gender_rates[evo_chain]
|
||||||
if moves in breeds_required[group]:
|
if 0 <= gender_rate:
|
||||||
yield cost, None, BreedNode(search=self.search, dummy='breed',
|
# Only pokemon that have males can pas down moves to other species
|
||||||
group_=group, version_group_=self.version_group_,
|
# (and the other species must have females: checked in BreedNode)
|
||||||
moves_=self.moves_)
|
for group in egg_groups:
|
||||||
|
if moves in breeds_required[group]:
|
||||||
|
yield cost, None, BreedNode(search=self.search, dummy='b',
|
||||||
|
group_=group, version_group_=self.version_group_,
|
||||||
|
moves_=self.moves_)
|
||||||
|
# Since the target family is not included in our breed graph, we
|
||||||
|
# breed with it explicitly. But again, there must be a female to
|
||||||
|
# breed with.
|
||||||
|
if search.gender_rates[search.goal_evolution_chain] > 0:
|
||||||
|
yield cost, None, GoalBreedNode(search=self.search, dummy='g',
|
||||||
|
version_group_=self.version_group_, moves_=self.moves_)
|
||||||
|
elif evo_chain == search.goal_evolution_chain:
|
||||||
|
# Single-gender & genderless pokemon can pass on moves via
|
||||||
|
# breeding with Ditto, to produce the same species again. Obviously
|
||||||
|
# this is only useful when breeding the goal species.
|
||||||
|
yield cost, None, GoalBreedNode(search=self.search, dummy='g',
|
||||||
|
version_group_=self.version_group_, moves_=self.moves_)
|
||||||
|
|
||||||
class BreedNode(Node, namedtuple('BreedNode',
|
class BaseBreedNode(Node):
|
||||||
'search dummy group_ version_group_ moves_')):
|
|
||||||
"""Breed node
|
"""Breed node
|
||||||
This serves to prevent duplicate breeds, by storing only the needed info
|
This serves to prevent duplicate breeds, by storing only the needed info
|
||||||
in the namedtuple.
|
in the namedtuple.
|
||||||
|
@ -889,22 +904,19 @@ class BreedNode(Node, namedtuple('BreedNode',
|
||||||
vg = self.version_group_
|
vg = self.version_group_
|
||||||
gen = search.generation_id_by_version_group[vg]
|
gen = search.generation_id_by_version_group[vg]
|
||||||
hatch_level = 5 if (gen < 4) else 1
|
hatch_level = 5 if (gen < 4) else 1
|
||||||
for baby in search.babies[self.group_]:
|
for baby in self.babies():
|
||||||
bred_moves = self.moves_
|
bred_moves = self.moves_
|
||||||
gender_rate = search.gender_rates[baby]
|
moves = search.pokemon_moves[baby][vg]
|
||||||
baby_chain = search.evolution_chains[baby]
|
if not bred_moves.issubset(moves):
|
||||||
if bred_moves.issubset(search.movepools[baby_chain]):
|
continue
|
||||||
if len(bred_moves) < 4:
|
if len(bred_moves) < 4:
|
||||||
moves = search.pokemon_moves[baby][self.version_group_]
|
for move, methods in moves.items():
|
||||||
for move, methods in moves.items():
|
if 'light-ball-pichu' in methods:
|
||||||
if 'light-ball-pichu' in methods:
|
bred_moves.add(move)
|
||||||
bred_moves.add(move)
|
cost = search.costs['per-hatch-counter'] * search.hatch_counters[baby]
|
||||||
cost = search.costs['per-hatch-counter'] * search.hatch_counters[baby]
|
yield 0, BreedAction(self.search, baby, bred_moves), PokemonNode(
|
||||||
yield 0, BreedAction(self.search, baby, bred_moves), PokemonNode(
|
search=self.search, pokemon_=baby, level=hatch_level,
|
||||||
search=self.search, pokemon_=baby, level=hatch_level,
|
version_group_=vg, moves_=bred_moves, new_level=True)
|
||||||
version_group_=vg, moves_=bred_moves, new_level=True)
|
|
||||||
return
|
|
||||||
yield
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pokemon(self):
|
def pokemon(self):
|
||||||
|
@ -913,6 +925,26 @@ class BreedNode(Node, namedtuple('BreedNode',
|
||||||
def estimate(self, g):
|
def estimate(self, g):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
class BreedNode(BaseBreedNode, namedtuple('BreedNode',
|
||||||
|
'search dummy group_ version_group_ moves_')):
|
||||||
|
def babies(self):
|
||||||
|
search = self.search
|
||||||
|
for baby in search.babies[self.group_]:
|
||||||
|
baby_chain = search.evolution_chains[baby]
|
||||||
|
if self.moves_.issubset(search.movepools[baby_chain]) and (
|
||||||
|
search.gender_rates[baby_chain] > 0):
|
||||||
|
yield baby
|
||||||
|
|
||||||
|
class GoalBreedNode(BaseBreedNode, namedtuple('InbreedNode',
|
||||||
|
'search dummy version_group_ moves_')):
|
||||||
|
def babies(self):
|
||||||
|
search = self.search
|
||||||
|
goal_family = search.goal_evolution_chain
|
||||||
|
group = search.egg_groups[goal_family][0]
|
||||||
|
for baby in search.pokemon_by_evolution_chain[goal_family]:
|
||||||
|
if baby in search.babies[group]:
|
||||||
|
yield baby
|
||||||
|
|
||||||
class GoalNode(PokemonNode):
|
class GoalNode(PokemonNode):
|
||||||
def expand(self):
|
def expand(self):
|
||||||
return ()
|
return ()
|
||||||
|
|
Loading…
Reference in a new issue