From 5476b86a11d58f6d4dce61c94557e711616bf104 Mon Sep 17 00:00:00 2001 From: Kurt Date: Fri, 30 Jun 2017 00:37:17 -0700 Subject: [PATCH] Misc performance tweaks Switch encounter slot generator to yield style to not require the entire method to finish iterating Although the pressure slot may be best-matching, it isn't the typical match. Defer pressure slot clone to the end (defers the orderby calculation) There's probably a better way to do the pre-work (gen 5+ only operate off one encounterarea... usually. Past Gens end up repeating the same work for each area tested slot matching runs slightly faster now due to the deferred execution --- PKHeX.Core/Legality/Core.cs | 2 +- .../Legality/Encounters/EncounterGenerator.cs | 92 ++++++++++--------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index 04401b7d8..bbbfc50c4 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -2157,7 +2157,7 @@ internal static int GetMinLevelEncounter(PKM pkm) if (pkm.Format == 3 && pkm.WasEgg) // Only for gen 3 pokemon in format 3, after transfer to gen 4 it should return transfer level return 5; - if (pkm.Format == 4 && pkm.GenNumber == 4 && pkm.WasEgg) + if (pkm.Format == 4 && pkm.GenNumber == 4 && pkm.WasEgg) // Only for gen 4 pokemon in format 4, after transfer to gen 5 it should return transfer level return 1; return pkm.HasOriginalMetLocation ? pkm.Met_Level : GetMaxLevelGeneration(pkm); diff --git a/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs b/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs index e87d62030..423ccf663 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterGenerator.cs @@ -457,16 +457,19 @@ private static IEnumerable GetStatic(PKM pkm, IEnumerable GetRawEncounterSlots(PKM pkm, GameVersion gameSource = GameVersion.Any) + private static IEnumerable GetRawEncounterSlots(PKM pkm, int lvl, GameVersion gameSource = GameVersion.Any) { - return GetEncounterAreas(pkm, gameSource).SelectMany(area => GetValidEncounterSlots(pkm, area, DexNav: pkm.AO, gameSource: gameSource)); + return GetEncounterAreas(pkm, gameSource).SelectMany(area => GetValidEncounterSlots(pkm, area, DexNav: pkm.AO, lvl: lvl, gameSource: gameSource)); } private static IEnumerable GetValidWildEncounters(PKM pkm, GameVersion gameSource = GameVersion.Any) { if (gameSource == GameVersion.Any) gameSource = (GameVersion)pkm.Version; - var s = GetRawEncounterSlots(pkm, gameSource); + int lvl = GetMinLevelEncounter(pkm); + if (lvl <= 0) + yield break; + var s = GetRawEncounterSlots(pkm, lvl, gameSource); bool IsSafariBall = pkm.Ball == 5; bool IsSportsBall = pkm.Ball == 0x18; bool IsHidden = pkm.AbilityNumber == 4; // hidden Ability @@ -516,18 +519,23 @@ private static IEnumerable GetValidFriendSafari(PKM pkm) }; } } - private static IEnumerable GetValidEncounterSlots(PKM pkm, EncounterArea loc, bool DexNav, bool ignoreLevel = false, GameVersion gameSource = GameVersion.Any) + private static IEnumerable GetValidEncounterSlots(PKM pkm, EncounterArea loc, bool DexNav, int lvl = -1, bool ignoreLevel = false, GameVersion gameSource = GameVersion.Any) { - int fluteBoost = pkm.Format < 3 ? 0 : 4; + if (lvl < 0) + lvl = GetMinLevelEncounter(pkm); + if (lvl <= 0) + yield break; + + int gen = pkm.GenNumber; + int fluteBoost = gen < 3 ? 0 : 4; const int dexnavBoost = 30; int df = DexNav ? fluteBoost : 0; int dn = DexNav ? fluteBoost + dexnavBoost : 0; - List slotdata = new List(); var maxspeciesorigin = -1; if (gameSource == GameVersion.RBY) maxspeciesorigin = MaxSpeciesID_1; - if (GameVersion.GSC.Contains(gameSource)) maxspeciesorigin = MaxSpeciesID_2; + else if (GameVersion.GSC.Contains(gameSource)) maxspeciesorigin = MaxSpeciesID_2; // Get Valid levels IEnumerable vs = GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin, lvl: ignoreLevel ? 100 : -1, skipChecks: ignoreLevel); @@ -538,7 +546,7 @@ private static IEnumerable GetValidEncounterSlots(PKM pkm, Encoun // Pure gen 1, slots can be filter by catch rate if ((pkm.Species == 25 || pkm.Species == 26) && pk1.Catch_Rate == 163) // Yellow Pikachu, is not a wild encounter - return slotdata; + yield break; if ((pkm.Species == 64 || pkm.Species == 65) && pk1.Catch_Rate == 96) // Yellow Kadabra, ignore Abra encounters vs = vs.Where(s => s.Species == 64); @@ -552,14 +560,8 @@ private static IEnumerable GetValidEncounterSlots(PKM pkm, Encoun } } - int lvl = GetMinLevelEncounter(pkm); - if (lvl <= 0) - return slotdata; - int gen = pkm.GenNumber; - - // Get slots where pokemon can exist - bool ignoreSlotLevel = ignoreLevel; - IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && (ignoreSlotLevel || evo.Level >= slot.LevelMin - df))); + // Get slots where pokemon can exist with respect to the evolution chain + IEnumerable slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && (ignoreLevel || evo.Level >= slot.LevelMin - df))); List encounterSlots; if (ignoreLevel) @@ -571,48 +573,41 @@ private static IEnumerable GetValidEncounterSlots(PKM pkm, Encoun if (gen <= 2) { - if (IsRGBKadabra) - //Red Kadabra slots : Level 49 and 51 in RGB, but level 20 and 27 in Yellow + if (IsRGBKadabra) //Red Kadabra slots : Level 49 and 51 in RGB, but level 20 and 27 in Yellow encounterSlots = encounterSlots.Where(slot => slot.LevelMin >= 49).ToList(); - // For gen 1 and 2 return Minimum level slot - // Minimum level is needed to check available moves, because there is no move reminder in gen 1, - // There are moves in the level up table that cant be legally obtained - EncounterSlot slotMin = encounterSlots.OrderBy(slot => slot.LevelMin).FirstOrDefault(); - if (slotMin != null) - slotdata.Add(slotMin); - return slotdata; + foreach (var s in encounterSlots.OrderBy(slot => slot.LevelMin)) + yield return s; + yield break; } // Pressure Slot EncounterSlot slotMax = encounterSlots.OrderByDescending(slot => slot.LevelMax).FirstOrDefault(); - if (slotMax != null) - { - slotMax = slotMax.Clone(); - slotMax.Permissions.Pressure = true; - slotMax.Form = pkm.AltForm; - } if (gen >= 6 && !DexNav) { - // Filter for Form Specific - slotdata.AddRange(WildForms.Contains(pkm.Species) + var slotdata = WildForms.Contains(pkm.Species) ? encounterSlots.Where(slot => slot.Form == pkm.AltForm) - : encounterSlots); + : encounterSlots; + + foreach (var z in slotdata) + yield return z; + + // Filter for Form Specific if (slotMax != null) - slotdata.Add(slotMax); - return slotdata; + yield return getPressureSlot(slotMax); + yield break; } - List eslots = encounterSlots.Where(slot => !WildForms.Contains(pkm.Species) || slot.Form == pkm.AltForm).ToList(); + IEnumerable formMatchSlots = encounterSlots.Where(slot => !WildForms.Contains(pkm.Species) || slot.Form == pkm.AltForm); if (gen <= 5) { - slotdata.AddRange(eslots); - return slotdata; + foreach (var z in formMatchSlots) + yield return z; + yield break; } - if (slotMax != null) - eslots.Add(slotMax); - foreach (EncounterSlot s in eslots) + + foreach (EncounterSlot s in formMatchSlots) { bool nav = s.Permissions.AllowDexNav && (pkm.RelearnMove1 != 0 || pkm.AbilityNumber == 4); EncounterSlot slot = s.Clone(); @@ -624,9 +619,18 @@ private static IEnumerable GetValidEncounterSlots(PKM pkm, Encoun slot.Permissions.BlackFlute = true; if (slot.LevelMax != lvl && slot.Permissions.AllowDexNav) slot.Permissions.DexNav = true; - slotdata.Add(slot); + yield return slot; + } + if (slotMax != null) + yield return getPressureSlot(slotMax); + + EncounterSlot getPressureSlot(EncounterSlot s) + { + var max = s.Clone(); + max.Permissions.Pressure = true; + max.Form = pkm.AltForm; + return max; } - return slotdata; } private static IEnumerable GetEncounterSlots(PKM pkm, int lvl = -1, GameVersion gameSource = GameVersion.Any)