You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

314 lines
14 KiB

import sqlite3
import os
from collections import defaultdict
class EfficiencyOriginDexPlanner:
def __init__(self, db_path):
self.conn = sqlite3.connect(db_path)
self.conn.row_factory = sqlite3.Row
def get_all_data(self):
cursor = self.conn.cursor()
cursor.execute("SELECT * FROM games ORDER BY generation, id")
games = cursor.fetchall()
cursor.execute("SELECT * FROM pokemon_forms ORDER BY generation, national_dex")
pokemon_forms = cursor.fetchall()
cursor.execute("SELECT * FROM encounters")
encounters = cursor.fetchall()
cursor.execute("SELECT * FROM evolution_chains")
evolutions = cursor.fetchall()
return games, pokemon_forms, encounters, evolutions
def build_data_structures(self):
games, pokemon_forms, encounters, evolutions = self.get_all_data()
pokemon_by_gen = defaultdict(list)
game_by_gen = defaultdict(list)
encounter_data = defaultdict(list)
evolution_map = defaultdict(list)
for game in games:
game_by_gen[game['generation']].append(game)
for pokemon in pokemon_forms:
pokemon_by_gen[pokemon['generation']].append(pokemon)
for encounter in encounters:
encounter_data[encounter['game_id']].append(encounter)
for evolution in evolutions:
evolution_map[evolution['from_pfic']].append(evolution['to_pfic'])
return pokemon_by_gen, game_by_gen, encounter_data, evolution_map
def generate_efficient_plan(self, generation_groups):
pokemon_by_gen, game_by_gen, encounter_data, evolution_map = self.build_data_structures()
plan = []
caught_pokemon = set()
for group in generation_groups:
group_plan = self.plan_for_group(group, pokemon_by_gen, game_by_gen, encounter_data, evolution_map, caught_pokemon)
plan.extend(group_plan)
return plan
def plan_for_group(self, generations, pokemon_by_gen, game_by_gen, encounter_data, evolution_map, caught_pokemon):
group_plan = []
needed_pokemon = set()
games_in_group = []
for gen in generations:
needed_pokemon.update(pokemon['PFIC'] for pokemon in pokemon_by_gen[gen])
games_in_group.extend(game_by_gen[gen])
print(f"Initial needed_pokemon count: {len(needed_pokemon)}")
print(f"Games in group: {[game['name'] for game in games_in_group]}")
# Check for new evolutions of already caught Pokémon
new_evolutions = set()
for pfic in caught_pokemon:
if pfic in evolution_map:
for evolved_pfic in evolution_map[pfic]:
if self.get_pokemon_generation(evolved_pfic) in generations and evolved_pfic not in caught_pokemon:
new_evolutions.add(pfic)
needed_pokemon.add(evolved_pfic)
print(f"Needed pokemon after adding new evolutions: {len(needed_pokemon)}")
# Create a dictionary to store the Pokémon available in each game, including evolutions
game_pokemon = {}
for game in games_in_group:
game_pokemon[game['id']] = set()
for encounter in encounter_data[game['id']]:
game_pokemon[game['id']].add(encounter['pfic'])
# Add all possible evolutions
current_pfic = encounter['pfic']
while current_pfic in evolution_map:
for evolved_pfic in evolution_map[current_pfic]:
if self.get_pokemon_generation(evolved_pfic) in generations:
game_pokemon[game['id']].add(evolved_pfic)
current_pfic = evolved_pfic
break
else:
break
selected_games = []
remaining_pokemon = needed_pokemon.copy()
while remaining_pokemon:
# Add debugging information
print("\nDebug: Game selection process")
for game in games_in_group:
pokemon_covered = remaining_pokemon & game_pokemon[game['id']]
print(f" {game['name']}: {len(pokemon_covered)} Pokemon covered")
print(f" First 15 Pokemon: {[self.get_pokemon_name(pfic) for pfic in list(pokemon_covered)[:15]]}")
best_game = max(games_in_group, key=lambda g: len(remaining_pokemon & game_pokemon[g['id']]))
pokemon_covered = remaining_pokemon & game_pokemon[best_game['id']]
print(f"\nBest game: {best_game['name']}, Pokemon covered: {len(pokemon_covered)}")
print(f"First 10 Pokemon covered by {best_game['name']}: {[self.get_pokemon_name(pfic) for pfic in list(pokemon_covered)[:10]]}")
if not pokemon_covered:
print("No more Pokémon can be covered. Breaking loop.")
break
selected_games.append(best_game)
remaining_pokemon -= pokemon_covered
# Check if we can remove any previously selected games
for game in selected_games[:-1]:
if all(pokemon in game_pokemon[best_game['id']] for pokemon in game_pokemon[game['id']] & needed_pokemon):
selected_games.remove(game)
print(f"Removed {game['name']} as it's covered by {best_game['name']}")
print(f"Selected games: {[game['name'] for game in selected_games]}")
for game in selected_games:
game_plan = self.plan_for_game(game, needed_pokemon, encounter_data, evolution_map, caught_pokemon, set(generations), new_evolutions)
if game_plan:
group_plan.extend(game_plan)
if not group_plan:
print("Warning: No games were selected or no Pokémon were planned to be caught.")
return group_plan
def plan_for_game(self, game, needed_pokemon, encounter_data, evolution_map, caught_pokemon, target_generations, new_evolutions):
game_plan = []
to_catch = defaultdict(int)
to_evolve = defaultdict(list)
to_breed = defaultdict(list)
planned_evolutions = defaultdict(int)
processed_chains = set()
# First, handle new evolutions for already caught Pokémon
for pfic in new_evolutions:
evolution_chains, visit_counts, baby_forms = self.get_evolution_chains(pfic, evolution_map, target_generations)
new_evolutions_count = sum(1 for chain in evolution_chains for pokemon in chain if pokemon not in caught_pokemon)
if new_evolutions_count > 0:
if any(encounter['pfic'] == pfic for encounter in encounter_data[game['id']]):
to_catch[pfic] += new_evolutions_count - planned_evolutions[pfic]
planned_evolutions[pfic] += new_evolutions_count
for chain in evolution_chains:
if len(chain) > 1:
for i in range(len(chain) - 1):
from_pfic, to_pfic = chain[i], chain[i+1]
if to_pfic not in caught_pokemon:
to_evolve[from_pfic].append(to_pfic)
caught_pokemon.add(to_pfic)
needed_pokemon.discard(to_pfic)
# Then proceed with the regular planning
for encounter in encounter_data[game['id']]:
if encounter['pfic'] in needed_pokemon and encounter['pfic'] not in caught_pokemon:
evolution_chains, visit_counts, baby_forms = self.get_evolution_chains(encounter['pfic'], evolution_map, target_generations)
base_form = evolution_chains[0][0]
if base_form not in caught_pokemon:
chain_key = tuple(sorted(set(pokemon for chain in evolution_chains for pokemon in chain)))
if chain_key not in processed_chains:
processed_chains.add(chain_key)
num_to_catch = max(0, visit_counts[base_form] - planned_evolutions[base_form])
if num_to_catch > 0:
to_catch[encounter['pfic']] += num_to_catch
planned_evolutions[base_form] += num_to_catch
for chain in evolution_chains:
if len(chain) > 1:
for i in range(len(chain) - 1):
from_pfic, to_pfic = chain[i], chain[i+1]
if from_pfic not in baby_forms:
if not self.is_final_evolution(to_pfic, evolution_map) or (self.is_final_evolution(to_pfic, evolution_map) and not self.is_in_to_evolve(to_pfic, to_evolve)):
to_evolve[from_pfic].append(to_pfic)
else:
to_catch[encounter['pfic']] += -1
planned_evolutions[base_form] += -1
if from_pfic in baby_forms and from_pfic not in encounter_data[game['id']]:
if to_pfic not in to_breed or from_pfic not in to_breed[to_pfic]:
to_breed[to_pfic].append(from_pfic)
caught_pokemon.update(pfic for chain in evolution_chains for pfic in chain)
needed_pokemon.difference_update(pfic for chain in evolution_chains for pfic in chain)
if to_catch or to_evolve or to_breed:
game_plan.append(f"Play {game['name']}:")
if to_catch:
game_plan.append(" Catch:")
for pfic, count in to_catch.items():
game_plan.append(f" - {self.get_pokemon_name(pfic)}: {count} time(s)")
if to_evolve:
game_plan.append(" Evolve:")
for from_pfic, to_pfics in to_evolve.items():
for to_pfic in to_pfics:
game_plan.append(f" - {self.get_pokemon_name(from_pfic)} into {self.get_pokemon_name(to_pfic)}")
if to_breed:
game_plan.append(" Breed:")
for parent_pfic, baby_pfics in to_breed.items():
for baby_pfic in baby_pfics:
game_plan.append(f" - {self.get_pokemon_name(parent_pfic)} to get {self.get_pokemon_name(baby_pfic)}")
return game_plan
def plan_evolutions(self, evolution_chains, evolution_map, caught_pokemon):
chains, visit_counts = self.get_evolution_chains(evolution_chains[0][0], evolution_map)
evolution_plan = []
needed_counts = defaultdict(int)
# Count how many of each Pokémon we need based on visit counts
for pfic, count in visit_counts.items():
if pfic not in caught_pokemon:
needed_counts[pfic] = count
# Plan evolutions
for chain in chains:
for i in range(len(chain) - 1):
from_pfic, to_pfic = chain[i], chain[i+1]
if needed_counts[to_pfic] > 0:
evolution_plan.append((from_pfic, to_pfic))
needed_counts[to_pfic] -= 1
needed_counts[from_pfic] -= 1
return evolution_plan, needed_counts
def get_evolution_chains(self, pfic, evolution_map, target_generations):
visited = defaultdict(int)
unique_paths = set()
baby_forms = set()
def dfs(current_pfic, path):
path_tuple = tuple(path)
if path_tuple in unique_paths:
return
unique_paths.add(path_tuple)
for pfic in path:
visited[pfic] += 1
if self.is_baby_pokemon(pfic):
baby_forms.add(pfic)
if current_pfic in evolution_map:
for next_pfic in evolution_map[current_pfic]:
if self.get_pokemon_generation(next_pfic) in target_generations:
dfs(next_pfic, path + [next_pfic])
dfs(pfic, [pfic])
chains = [list(path) for path in unique_paths]
# Adjust visit counts for baby Pokémon
for baby in baby_forms:
visited[baby] = 1
return chains, visited, baby_forms
def get_pokemon_name(self, pfic):
cursor = self.conn.cursor()
cursor.execute("SELECT name, form_name FROM pokemon_forms WHERE PFIC = ?", (pfic,))
result = cursor.fetchone()
if result['form_name']:
return f"{result['name']} ({result['form_name']})"
return result['name']
def display_plan(self, generation_groups, output_file='efficiency_plan.txt'):
plan = self.generate_efficient_plan(generation_groups)
# Print to console
#for step in plan:
# print(step)
# Write to file
with open(output_file, 'w', encoding='utf-8') as f:
for step in plan:
f.write(f"{step}\n")
print(f"\nPlan has been written to {os.path.abspath(output_file)}")
def is_baby_pokemon(self, pfic):
cursor = self.conn.cursor()
cursor.execute("SELECT is_baby_form FROM pokemon_forms WHERE PFIC = ?", (pfic,))
result = cursor.fetchone()
return result['is_baby_form'] if result else False
def get_pokemon_generation(self, pfic):
cursor = self.conn.cursor()
cursor.execute("SELECT generation FROM pokemon_forms WHERE PFIC = ?", (pfic,))
result = cursor.fetchone()
return result['generation'] if result else None
def is_final_evolution(self, pfic, evolution_map):
return pfic not in evolution_map
def is_in_to_evolve(self, pfic, to_evolve):
return any(pfic in to_pfics for to_pfics in to_evolve.values())
# Example usage
planner = EfficiencyOriginDexPlanner('pokemon_forms.db')
planner.display_plan([[1, 2], [3, 4, 5, 6], [7], [8], [9]])