diff --git a/DBEditor/plan2.py b/DBEditor/plan2.py index 909ce04..647b3f9 100644 --- a/DBEditor/plan2.py +++ b/DBEditor/plan2.py @@ -103,12 +103,26 @@ class EfficiencyOriginDexPlanner: # Add debugging information print("\nDebug: Game selection process") for game in games_in_group: - pokemon_covered = remaining_pokemon & game_pokemon[game['id']] + exclusive_groups = self.get_exclusive_groups(game['id']) + pokemon_covered = set() + + for pfic in remaining_pokemon & game_pokemon[game['id']]: + is_exclusive = False + for group in exclusive_groups.values(): + if any(ge['pfic'] == pfic for ge in group): + is_exclusive = True + # If it's exclusive, only add it if no other Pokémon from its group is already covered + if not any(other_ge['pfic'] in pokemon_covered for other_ge in group): + pokemon_covered.add(pfic) + break + if not is_exclusive: + pokemon_covered.add(pfic) + 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']] + best_game = max(games_in_group, key=lambda g: len(self.get_covered_pokemon(g, remaining_pokemon, game_pokemon[g['id']]))) + pokemon_covered = self.get_covered_pokemon(best_game, 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]]}") @@ -121,7 +135,8 @@ class EfficiencyOriginDexPlanner: # 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): + if all(pokemon in self.get_covered_pokemon(best_game, needed_pokemon, game_pokemon[best_game['id']]) + for pokemon in self.get_covered_pokemon(game, needed_pokemon, game_pokemon[game['id']])): selected_games.remove(game) print(f"Removed {game['name']} as it's covered by {best_game['name']}") @@ -131,6 +146,23 @@ class EfficiencyOriginDexPlanner: 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) + + # Update game_pokemon to remove exclusive encounters that weren't used + exclusive_groups = self.get_exclusive_groups(game['id']) + used_exclusive_groups = set() + for step in game_plan: + if step.startswith(" Catch:"): + pfic = step.split(":")[1].strip().split(" ")[0] + for group_id, group_encounters in exclusive_groups.items(): + if any(ge['pfic'] == pfic for ge in group_encounters): + used_exclusive_groups.add(group_id) + break + + for group_id, group_encounters in exclusive_groups.items(): + if group_id not in used_exclusive_groups: + for ge in group_encounters: + if ge['pfic'] in game_pokemon[game['id']]: + game_pokemon[game['id']].remove(ge['pfic']) if not group_plan: print("Warning: No games were selected or no Pokémon were planned to be caught.") @@ -145,6 +177,9 @@ class EfficiencyOriginDexPlanner: planned_evolutions = defaultdict(int) processed_chains = set() + exclusive_groups = self.get_exclusive_groups(game['id']) + used_exclusive_groups = 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) @@ -168,6 +203,26 @@ class EfficiencyOriginDexPlanner: # 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: + # Check if this encounter is part of an exclusive group + skip_encounter = False + for group_id, group_encounters in exclusive_groups.items(): + if group_id in used_exclusive_groups: + if any(ge['encounter_id'] == encounter['id'] for ge in group_encounters): + skip_encounter = True + break + else: + for group_encounter in group_encounters: + if group_encounter['encounter_id'] == encounter['id']: + if not group_encounter['starter']: + used_exclusive_groups.add(group_id) + break + else: + continue + break + + if skip_encounter: + continue + evolution_chains, visit_counts, baby_forms = self.get_evolution_chains(encounter['pfic'], evolution_map, target_generations) base_form = evolution_chains[0][0] @@ -199,6 +254,17 @@ class EfficiencyOriginDexPlanner: 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) + # Remove encounters from exclusive groups that weren't used + for group_id, group_encounters in exclusive_groups.items(): + if group_id not in used_exclusive_groups: + for group_encounter in group_encounters: + if group_encounter['pfic'] in to_catch: + del to_catch[group_encounter['pfic']] + if group_encounter['pfic'] in to_evolve: + del to_evolve[group_encounter['pfic']] + if group_encounter['pfic'] in to_breed: + del to_breed[group_encounter['pfic']] + if to_catch or to_evolve or to_breed: game_plan.append(f"Play {game['name']}:") if to_catch: @@ -309,6 +375,42 @@ class EfficiencyOriginDexPlanner: def is_in_to_evolve(self, pfic, to_evolve): return any(pfic in to_pfics for to_pfics in to_evolve.values()) + def get_exclusive_groups(self, game_id): + cursor = self.conn.cursor() + cursor.execute(''' + SELECT eeg.group_id, e.id as encounter_id, e.pfic, e.starter + FROM encounter_exclusive_groups eeg + JOIN encounters e ON eeg.encounter_id = e.id + JOIN exclusive_encounter_groups eeg2 ON eeg.group_id = eeg2.id + WHERE eeg2.game_id = ? + ''', (game_id,)) + groups = defaultdict(list) + for row in cursor.fetchall(): + groups[row['group_id']].append({ + 'encounter_id': row['encounter_id'], + 'pfic': row['pfic'], + 'starter': row['starter'] + }) + return groups + + def get_covered_pokemon(self, game, needed_pokemon, available_pokemon): + exclusive_groups = self.get_exclusive_groups(game['id']) + pokemon_covered = set() + + for pfic in needed_pokemon & available_pokemon: + is_exclusive = False + for group in exclusive_groups.values(): + if any(ge['pfic'] == pfic for ge in group): + is_exclusive = True + # If it's exclusive, only add it if no other Pokémon from its group is already covered + if not any(other_ge['pfic'] in pokemon_covered for other_ge in group): + pokemon_covered.add(pfic) + break + if not is_exclusive: + pokemon_covered.add(pfic) + + return pokemon_covered + # Example usage planner = EfficiencyOriginDexPlanner('pokemon_forms.db') planner.display_plan([[1, 2], [3, 4, 5, 6], [7], [8], [9]]) diff --git a/efficiency_plan.txt b/efficiency_plan.txt index b7c63ff..490a1c9 100644 --- a/efficiency_plan.txt +++ b/efficiency_plan.txt @@ -196,12 +196,12 @@ Play Crystal: - Zubat (Male) into Golbat (Male) - Oddish into Gloom (Female) - Oddish into Gloom (Male) - - Oddish into Gloom (Female) - Oddish into Gloom (Male) - Oddish into Gloom (Male) - - Gloom (Female) into Vileplume (Female) - - Gloom (Male) into Vileplume (Male) + - Oddish into Gloom (Female) - Gloom (Male) into Bellossom + - Gloom (Male) into Vileplume (Male) + - Gloom (Female) into Vileplume (Female) - Paras into Parasect - Venonat into Venomoth - Diglett into Dugtrio @@ -212,9 +212,9 @@ Play Crystal: - Poliwag into Poliwhirl - Poliwag into Poliwhirl - Poliwag into Poliwhirl + - Poliwhirl into Politoed (Female) - Poliwhirl into Poliwrath - Poliwhirl into Politoed (Male) - - Poliwhirl into Politoed (Female) - Abra into Kadabra (Male) - Abra into Kadabra (Male) - Abra into Kadabra (Female) @@ -243,10 +243,10 @@ Play Crystal: - Gastly into Haunter - Gastly into Haunter - Haunter into Gengar - - Onix into Steelix (Male) - Onix into Steelix (Female) - - Drowzee into Hypno (Female) + - Onix into Steelix (Male) - Drowzee into Hypno (Male) + - Drowzee into Hypno (Female) - Krabby into Kingler - Voltorb into Electrode - Exeggcute into Exeggutor @@ -265,10 +265,10 @@ Play Crystal: - Scyther (Male) into Scizor (Male) - Magikarp (Female) into Gyarados (Female) - Magikarp (Male) into Gyarados (Male) + - Eevee (Female) into Jolteon - Eevee (Female) into Flareon - - Eevee (Female) into Vaporeon - Eevee (Female) into Espeon - - Eevee (Female) into Jolteon + - Eevee (Female) into Vaporeon - Eevee (Female) into Umbreon - Porygon into Porygon2 - Dratini into Dragonair @@ -291,8 +291,8 @@ Play Crystal: - Ledyba (Male) into Ledian (Male) - Spinarak into Ariados - Chinchou into Lanturn - - Natu into Xatu (Male) - Natu into Xatu (Female) + - Natu into Xatu (Male) - Marill into Azumarill - Hoppip into Skiploom - Hoppip into Skiploom @@ -302,11 +302,11 @@ Play Crystal: - Wooper (Male) into Quagsire (Male) - Pineco into Forretress - Snubbull into Granbull - - Teddiursa into Ursaring (Male) - Teddiursa into Ursaring (Female) + - Teddiursa into Ursaring (Male) - Slugma into Magcargo - - Swinub into Piloswine (Female) - Swinub into Piloswine (Male) + - Swinub into Piloswine (Female) - Houndour into Houndoom (Male) - Houndour into Houndoom (Female) - Phanpy into Donphan (Male) @@ -315,13 +315,13 @@ Play Crystal: - Larvitar into Pupitar - Pupitar into Tyranitar Breed: - - Pikachu (Male) to get Pichu - Pikachu (Female) to get Pichu + - Pikachu (Male) to get Pichu - Clefairy to get Cleffa - Jigglypuff to get Igglybuff - Togetic to get Togepi - - Hitmontop to get Tyrogue - Hitmonchan to get Tyrogue + - Hitmontop to get Tyrogue - Hitmonlee to get Tyrogue - Jynx to get Smoochum - Electabuzz to get Elekid @@ -334,7 +334,6 @@ Play Yellow: - Vulpix: 2 time(s) - Mankey: 2 time(s) - Omanyte: 2 time(s) - - Kabuto: 2 time(s) - Aerodactyl: 1 time(s) - Articuno: 1 time(s) - Zapdos: 1 time(s) @@ -344,8 +343,8 @@ Play Yellow: - Bulbasaur into Ivysaur - Bulbasaur into Ivysaur - Bulbasaur into Ivysaur - - Ivysaur into Venusaur (Female) - Ivysaur into Venusaur (Male) + - Ivysaur into Venusaur (Female) - Charmander into Charmeleon - Charmander into Charmeleon - Charmeleon into Charizard @@ -355,7 +354,6 @@ Play Yellow: - Vulpix into Ninetales - Mankey into Primeape - Omanyte into Omastar - - Kabuto into Kabutops Play Gold: Catch: - Mareep: 3 time(s) @@ -368,20 +366,25 @@ Play Gold: - Flaaffy into Ampharos - Remoraid into Octillery (Female) - Remoraid into Octillery (Male) +Play Red: + Catch: + - Kabuto: 2 time(s) + Evolve: + - Kabuto into Kabutops Play Black 2: Catch: - - Aipom (Female): 1 time(s) + - Lickitung: 1 time(s) - Gligar (Female): 1 time(s) - - Murkrow (Female): 1 time(s) - - Tangela: 2 time(s) + - Eevee (Male): 3 time(s) + - Piloswine (Male): 1 time(s) - Yanma: 1 time(s) - - Lickitung: 1 time(s) + - Tangela: 2 time(s) + - Aipom (Female): 1 time(s) + - Murkrow (Male): 1 time(s) - Magneton: 1 time(s) - - Piloswine (Female): 1 time(s) - Sneasel (Female): 1 time(s) - Sneasel (Male): 1 time(s) - - Piloswine (Male): 1 time(s) - - Eevee (Female): 3 time(s) + - Piloswine (Female): 1 time(s) - Aipom (Male): 1 time(s) - Lotad: 4 time(s) - Seedot: 5 time(s) @@ -550,33 +553,33 @@ Play Black 2: - Zekrom: 1 time(s) - Kyurem: 1 time(s) Evolve: - - Aipom (Female) into Ambipom (Female) + - Lickitung into Lickilicky - Gligar (Female) into Gliscor - - Murkrow (Female) into Honchkrow - - Tangela into Tangrowth (Male) - - Tangela into Tangrowth (Female) + - Eevee (Male) into Glaceon + - Eevee (Male) into Leafeon + - Eevee (Male) into Sylveon + - Piloswine (Male) into Mamoswine (Male) - Yanma into Yanmega - - Lickitung into Lickilicky + - Tangela into Tangrowth (Female) + - Tangela into Tangrowth (Male) + - Aipom (Female) into Ambipom (Female) + - Murkrow (Male) into Honchkrow - Magneton into Magnezone - - Piloswine (Female) into Mamoswine (Female) - Sneasel (Female) into Weavile (Female) - Sneasel (Male) into Weavile (Male) - - Piloswine (Male) into Mamoswine (Male) - - Eevee (Female) into Sylveon - - Eevee (Female) into Glaceon - - Eevee (Female) into Leafeon + - Piloswine (Female) into Mamoswine (Female) - Aipom (Male) into Ambipom (Male) - Lotad into Lombre - Lotad into Lombre - Lotad into Lombre - Lombre into Ludicolo (Male) - Lombre into Ludicolo (Female) - - Seedot into Nuzleaf (Female) - - Seedot into Nuzleaf (Male) - Seedot into Nuzleaf (Male) - Seedot into Nuzleaf (Female) - - Nuzleaf (Male) into Shiftry (Male) + - Seedot into Nuzleaf (Female) + - Seedot into Nuzleaf (Male) - Nuzleaf (Female) into Shiftry (Female) + - Nuzleaf (Male) into Shiftry (Male) - Taillow into Swellow - Wingull into Pelipper - Surskit into Masquerain @@ -602,8 +605,8 @@ Play Black 2: - Trapinch into Vibrava - Trapinch into Vibrava - Vibrava into Flygon - - Cacnea into Cacturne (Male) - Cacnea into Cacturne (Female) + - Cacnea into Cacturne (Male) - Swablu into Altaria - Barboach into Whiscash - Corphish into Crawdaunt @@ -616,8 +619,8 @@ Play Black 2: - Spheal into Sealeo - Spheal into Sealeo - Sealeo into Walrein - - Clamperl into Gorebyss - Clamperl into Huntail + - Clamperl into Gorebyss - Bagon into Shelgon - Bagon into Shelgon - Shelgon into Salamence @@ -740,8 +743,8 @@ Play Black 2: - Zweilous into Hydreigon - Larvesta into Volcarona Breed: - - Roselia (Female) to get Budew - Roselia (Male) to get Budew + - Roselia (Female) to get Budew - Lucario to get Riolu Play Y: Catch: @@ -815,13 +818,13 @@ Play Y: - Wurmple into Cascoon - Cascoon into Dustox (Female) - Cascoon into Dustox (Male) - - Silcoon into Beautifly (Male) - Silcoon into Beautifly (Female) + - Silcoon into Beautifly (Male) - Ralts into Kirlia - Ralts into Kirlia - Ralts into Kirlia - - Kirlia into Gardevoir - Kirlia into Gallade + - Kirlia into Gardevoir - Whismur into Loudred - Whismur into Loudred - Loudred into Exploud @@ -843,8 +846,8 @@ Play Y: - Shinx (Male) into Luxio (Male) - Shinx (Male) into Luxio (Male) - Luxio (Male) into Luxray (Male) - - Burmy (Plant Cloak) into Wormadam (Plant Cloak) - Burmy (Plant Cloak) into Mothim + - Burmy (Plant Cloak) into Wormadam (Plant Cloak) - Shellos (West Sea) into Gastrodon (West Sea) - Solosis into Duosion - Solosis into Duosion @@ -952,9 +955,9 @@ Play Alpha Sapphire: Play Platinum: Catch: - Rhydon (Female): 1 time(s) - - Magmar: 1 time(s) - Electabuzz: 1 time(s) - Rhydon (Male): 1 time(s) + - Magmar: 1 time(s) - Mawile: 1 time(s) - Gastrodon (East Sea): 1 time(s) - Snover (Female): 2 time(s) @@ -966,9 +969,9 @@ Play Platinum: - Arceus (Normal): 1 time(s) Evolve: - Rhydon (Female) into Rhyperior (Female) - - Magmar into Magmortar - Electabuzz into Electivire - Rhydon (Male) into Rhyperior (Male) + - Magmar into Magmortar - Snover (Female) into Abomasnow (Female) - Snover (Male) into Abomasnow (Male) Play Black: @@ -1205,8 +1208,8 @@ Play Sword: - Eternatus: 1 time(s) Evolve: - Sneasel (Female) into Sneasler - - Basculin (Red-Striped Form) into Basculegion (Male) - Basculin (Red-Striped Form) into Basculegion (Female) + - Basculin (Red-Striped Form) into Basculegion (Male) - Grookey into Thwackey - Grookey into Thwackey - Thwackey into Rillaboom @@ -1279,10 +1282,10 @@ Play Shield: Play Scarlet: Catch: - Dunsparce: 1 time(s) + - Bisharp: 1 time(s) - Girafarig (Female): 1 time(s) - Applin: 3 time(s) - Primeape: 1 time(s) - - Bisharp: 1 time(s) - Sprigatito: 3 time(s) - Fuecoco: 3 time(s) - Quaxly: 3 time(s) @@ -1348,11 +1351,11 @@ Play Scarlet: - Iron Leaves: 1 time(s) Evolve: - Dunsparce into Dudunsparce (Two-Segment Form) + - Bisharp into Kingambit - Girafarig (Female) into Farigiraf - Applin into Dipplin - Dipplin into Hydrapple - Primeape into Annihilape - - Bisharp into Kingambit - Sprigatito into Floragato - Sprigatito into Floragato - Floragato into Meowscarada diff --git a/pokemon_forms.db b/pokemon_forms.db index 3777079..fb25e57 100644 Binary files a/pokemon_forms.db and b/pokemon_forms.db differ