mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Prettify output
This commit is contained in:
parent
237830d523
commit
054421d93d
1 changed files with 170 additions and 44 deletions
|
@ -116,6 +116,8 @@ class MovesetSearch(object):
|
|||
|
||||
self.find_duplicate_versions()
|
||||
|
||||
self.output_objects = dict()
|
||||
|
||||
kwargs = dict()
|
||||
if debug:
|
||||
self._astar_debug_notify_counter = 0
|
||||
|
@ -525,6 +527,33 @@ class MovesetSearch(object):
|
|||
else:
|
||||
raise self.error
|
||||
|
||||
def get_by_id(self, table, id):
|
||||
key = table, 'id', id
|
||||
try:
|
||||
return self.output_objects[key]
|
||||
except KeyError:
|
||||
o = self.output_objects[key] = util.get(self.session, table, id=id)
|
||||
return o
|
||||
|
||||
def get_by_identifier(self, table, ident):
|
||||
key = table, 'identifier', ident
|
||||
try:
|
||||
return self.output_objects[key]
|
||||
except KeyError:
|
||||
o = self.output_objects[key] = util.get(self.session,
|
||||
table, identifier=ident)
|
||||
return o
|
||||
|
||||
def get_list(self, table, ids):
|
||||
key = table, 'list', ids
|
||||
try:
|
||||
return self.output_objects[key]
|
||||
except KeyError:
|
||||
o = self.output_objects[key] = sorted(
|
||||
(util.get(self.session, table, id=id) for id in ids),
|
||||
key=lambda x: x.identifier)
|
||||
return o
|
||||
|
||||
###
|
||||
### Costs
|
||||
###
|
||||
|
@ -566,31 +595,92 @@ default_costs = {
|
|||
'per-level': 1, # Prefer less grinding. This is for all lv-ups but the final “grow”
|
||||
}
|
||||
|
||||
###
|
||||
### Result objects
|
||||
###
|
||||
|
||||
class Facade(object):
|
||||
@property
|
||||
def pokemon(self):
|
||||
return self.search.get_by_id(tables.Pokemon, self.pokemon_)
|
||||
|
||||
@property
|
||||
def version_group(self):
|
||||
return self.search.get_by_id(tables.VersionGroup, self.version_group_)
|
||||
|
||||
@property
|
||||
def versions(self):
|
||||
return self.version_group.versions
|
||||
|
||||
@property
|
||||
def move(self):
|
||||
return self.search.get_by_id(tables.Move, self.move_)
|
||||
|
||||
@property
|
||||
def moves(self):
|
||||
return self.search.get_list(tables.Move, self.moves_)
|
||||
|
||||
@property
|
||||
def move_method(self):
|
||||
return self.search.get_by_identifier(tables.PokemonMoveMethod,
|
||||
self.move_method_)
|
||||
|
||||
@property
|
||||
def evolution_trigger(self):
|
||||
return self.search.get_by_identifier(tables.EvolutionTrigger,
|
||||
self.evolution_trigger_)
|
||||
|
||||
###
|
||||
### Search space transitions
|
||||
###
|
||||
|
||||
class Action(object):
|
||||
class Action(Facade):
|
||||
pass
|
||||
|
||||
class StartAction(Action, namedtuple('StartAcion', 'pokemon version_group')):
|
||||
class StartAction(Action, namedtuple('StartAcion', 'search pokemon_ version_group_')):
|
||||
keyword = 'start'
|
||||
|
||||
class LearnAction(Action, namedtuple('LearnAction', 'move method')):
|
||||
def __str__(self):
|
||||
vers = ' or '.join(v.name for v in self.versions)
|
||||
return "Start with {0.pokemon.name} in {1}".format(self, vers)
|
||||
|
||||
class LearnAction(Action, namedtuple('LearnAction', 'search move_ move_method_')):
|
||||
keyword = 'start'
|
||||
|
||||
class ForgetAction(Action, namedtuple('ForgetAction', 'move')):
|
||||
def __str__(self):
|
||||
return "Learn {0.move.name} by {0.move_method.name}".format(self)
|
||||
|
||||
class RelearnAction(Action, namedtuple('RelearnAction', 'search move_')):
|
||||
keyword = 'start'
|
||||
|
||||
def __str__(self):
|
||||
return "Relearn {0.move.name}".format(self)
|
||||
|
||||
class ForgetAction(Action, namedtuple('ForgetAction', 'search move_')):
|
||||
keyword = 'forget'
|
||||
|
||||
class TradeAction(Action, namedtuple('TradeAction', 'version_group')):
|
||||
def __str__(self):
|
||||
return "Forget {0.move.name}".format(self)
|
||||
|
||||
class TradeAction(Action, namedtuple('TradeAction', 'search version_group_')):
|
||||
keyword = 'trade'
|
||||
|
||||
class EvolutionAction(Action, namedtuple('EvolutionAction', 'pokemon trigger')):
|
||||
def __str__(self):
|
||||
vers = ' or '.join(v.name for v in self.versions)
|
||||
return "Trade to {1}".format(self, vers)
|
||||
|
||||
class EvolutionAction(Action, namedtuple('EvolutionAction', 'search pokemon_ evolution_trigger_')):
|
||||
keyword = 'evolution'
|
||||
|
||||
class GrowAction(Action, namedtuple('GrowAction', 'level')):
|
||||
def __str__(self):
|
||||
return "Evolve to {0.pokemon.name} by {0.evolution_trigger.name}".format(self)
|
||||
|
||||
class GrowAction(Action, namedtuple('GrowAction', 'search level')):
|
||||
keyword = 'grow'
|
||||
|
||||
def __str__(self):
|
||||
return "Grow to level {0.level}".format(self)
|
||||
|
||||
###
|
||||
### Search space nodes
|
||||
###
|
||||
|
@ -602,18 +692,26 @@ class InitialNode(Node, namedtuple('InitialNode', 'search')):
|
|||
egg_groups = search.egg_groups[search.evolution_chains[pokemon]]
|
||||
if any(search.breeds_required[group] for group in egg_groups):
|
||||
for version_group in version_groups:
|
||||
yield 0, StartAction(pokemon, version_group), PokemonNode(
|
||||
search, pokemon, 0, version_group, frozenset(), False)
|
||||
action = StartAction(search, pokemon, version_group)
|
||||
node = PokemonNode(search, pokemon, 0, version_group,
|
||||
frozenset(), False)
|
||||
yield 0, action, node
|
||||
|
||||
class PokemonNode(Node, Facade, namedtuple('PokemonNode',
|
||||
'search pokemon_ level version_group_ moves_ new_level')):
|
||||
|
||||
def __str__(self):
|
||||
return "lv.{level:3}{s} {pokemon_:<5} in {version_group_:3} with {moves}".format(
|
||||
s='*' if self.new_level else ' ',
|
||||
moves=sorted(self.moves_),
|
||||
**self._asdict())
|
||||
|
||||
class PokemonNode(Node, namedtuple('PokemonNode',
|
||||
'search pokemon level version_group moves new_level')):
|
||||
def expand(self):
|
||||
#print 'expand', self
|
||||
if not self.moves:
|
||||
if not self.moves_:
|
||||
# Learn something first
|
||||
# (other expand_* may rely on there being a move)
|
||||
return self.expand_learn()
|
||||
elif len(self.moves) < 4:
|
||||
elif len(self.moves_) < 4:
|
||||
expand_moves = self.expand_learn
|
||||
else:
|
||||
expand_moves = self.expand_forget
|
||||
|
@ -626,9 +724,9 @@ class PokemonNode(Node, namedtuple('PokemonNode',
|
|||
|
||||
def expand_learn(self):
|
||||
search = self.search
|
||||
moves = search.pokemon_moves[self.pokemon][self.version_group]
|
||||
moves = search.pokemon_moves[self.pokemon_][self.version_group_]
|
||||
for move, methods in moves.items():
|
||||
if move in self.moves:
|
||||
if move in self.moves_:
|
||||
continue
|
||||
for method, levels_costs in methods.items():
|
||||
if method == 'level-up':
|
||||
|
@ -641,7 +739,9 @@ class PokemonNode(Node, namedtuple('PokemonNode',
|
|||
level=level, new_level=True)
|
||||
else:
|
||||
yield self._learn(move, 'relearn',
|
||||
search.costs['relearn'], new_level=False)
|
||||
search.costs['relearn'],
|
||||
action=RelearnAction(self.search, move),
|
||||
new_level=False)
|
||||
elif method in 'machine tutor'.split():
|
||||
for level, cost in levels_costs:
|
||||
yield self._learn(move, method, cost, new_level=False)
|
||||
|
@ -658,51 +758,49 @@ class PokemonNode(Node, namedtuple('PokemonNode',
|
|||
else:
|
||||
raise ValueError('Unknown move method %s' % method)
|
||||
|
||||
def _learn(self, move, method, cost, **kwargs):
|
||||
kwargs['moves'] = self.moves.union([move])
|
||||
return cost, LearnAction(move, method), self._replace(**kwargs)
|
||||
def _learn(self, move, method, cost, action=None, **kwargs):
|
||||
kwargs['moves_'] = self.moves_.union([move])
|
||||
if action is None:
|
||||
action = LearnAction(self.search, move, method)
|
||||
return cost, action, self._replace(
|
||||
**kwargs)
|
||||
|
||||
def expand_forget(self):
|
||||
cost = self.search.costs['forget']
|
||||
for move in self.moves:
|
||||
yield cost, ForgetAction(move), self._replace(
|
||||
moves=self.moves.difference([move]), new_level=False)
|
||||
for move in self.moves_:
|
||||
yield cost, ForgetAction(self.search, move), self._replace(
|
||||
moves_=self.moves_.difference([move]), new_level=False)
|
||||
|
||||
def expand_trade(self):
|
||||
search = self.search
|
||||
target_vgs = set(search.pokemon_moves[self.pokemon])
|
||||
target_vgs = set(search.pokemon_moves[self.pokemon_])
|
||||
target_vgs.add(search.goal_version_group)
|
||||
target_vgs.discard(self.version_group_)
|
||||
for version_group in target_vgs:
|
||||
cost = search.trade_cost(self.version_group, version_group,
|
||||
*(search.move_generations[m] for m in self.moves)
|
||||
cost = search.trade_cost(self.version_group_, version_group,
|
||||
*(search.move_generations[m] for m in self.moves_)
|
||||
)
|
||||
if cost is not None:
|
||||
yield cost, TradeAction(version_group), self._replace(
|
||||
version_group=version_group, new_level=False)
|
||||
yield cost, TradeAction(search, version_group), self._replace(
|
||||
version_group_=version_group, new_level=False)
|
||||
|
||||
def expand_grow(self):
|
||||
search = self.search
|
||||
if (self.pokemon == search.goal_pokemon and
|
||||
self.version_group == search.goal_version_group and
|
||||
self.moves == search.goal_moves and
|
||||
if (self.pokemon_ == search.goal_pokemon and
|
||||
self.version_group_ == search.goal_version_group and
|
||||
self.moves_ == search.goal_moves and
|
||||
self.level <= search.goal_level):
|
||||
kwargs = self._asdict()
|
||||
kwargs['level'] = search.goal_level
|
||||
kwargs['new_level'] = True
|
||||
yield 0, GrowAction(search.goal_level), GoalNode(**kwargs)
|
||||
yield 0, GrowAction(search, search.goal_level), GoalNode(**kwargs)
|
||||
|
||||
def expand_evolutions(self):
|
||||
search = self.search
|
||||
for trigger, move, level, child in search.evolutions[self.pokemon]:
|
||||
kwargs = dict(pokemon=child)
|
||||
for trigger, move, level, child in search.evolutions[self.pokemon_]:
|
||||
kwargs = dict(pokemon_=child)
|
||||
cost = search.costs['evolution']
|
||||
if trigger in 'level-up use-item'.split():
|
||||
pass
|
||||
elif trigger == 'trade':
|
||||
kwargs['new_level'] = False
|
||||
else:
|
||||
raise ValueError('Unknown evolution trigger %s' % trigger)
|
||||
if move and move not in self.moves:
|
||||
if move and move not in self.moves_:
|
||||
continue
|
||||
if level:
|
||||
if level > self.level:
|
||||
|
@ -712,8 +810,17 @@ class PokemonNode(Node, namedtuple('PokemonNode',
|
|||
pass
|
||||
else:
|
||||
cost += search.costs['evolution-delayed']
|
||||
replace = self._replace
|
||||
yield cost, EvolutionAction(child, trigger), replace(**kwargs)
|
||||
if trigger in 'level-up use-item'.split():
|
||||
pass
|
||||
elif trigger == 'trade':
|
||||
kwargs['new_level'] = False
|
||||
elif trigger == 'shed':
|
||||
# XXX: Shedinja!!
|
||||
pass
|
||||
else:
|
||||
raise ValueError('Unknown evolution trigger %s' % trigger)
|
||||
yield cost, EvolutionAction(search, child, trigger), self._replace(
|
||||
**kwargs)
|
||||
|
||||
class GoalNode(PokemonNode):
|
||||
def expand(self):
|
||||
|
@ -797,9 +904,28 @@ def main(argv):
|
|||
if args.debug:
|
||||
print 'Setup done'
|
||||
|
||||
template = "{cost:4} {action:50.50} {pokemon:10}{level:>3}{nl:1}{versions:2} {moves}"
|
||||
first_result = True
|
||||
for result in search:
|
||||
print
|
||||
print result
|
||||
if first_result:
|
||||
if search.output_objects:
|
||||
print '**warning: search looked up output objects**'
|
||||
first_result = False
|
||||
print template.format(cost='Cost', action='Action', pokemon='Pokemon',
|
||||
level='Lv.', nl='V', versions='er',
|
||||
moves=''.join(m.name[0].lower() for m in moves))
|
||||
for cost, action, node in reversed(list(result)):
|
||||
print template.format(
|
||||
cost=cost,
|
||||
action=action,
|
||||
pokemon=node.pokemon.name,
|
||||
nl='.' if node.new_level else ' ',
|
||||
level=node.level,
|
||||
versions=''.join(v.name[0] for v in node.versions),
|
||||
moves=''.join('.' if m in node.moves else ' ' for m in moves) +
|
||||
''.join(m.name[0].lower() for m in node.moves if m not in moves),
|
||||
)
|
||||
|
||||
print
|
||||
|
||||
|
|
Loading…
Reference in a new issue