From 75202c7a89a082953ed3771bcf6d32894350cdfd Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 6 Jan 2019 16:22:45 -0800 Subject: [PATCH] Misc updates reducing allocations, increasing clarity by removing some magic numbers probably can rewrite some of the evo loading/checking for even less, but good for now. --- PKHeX.Core/Legality/Core.cs | 4 +- PKHeX.Core/Legality/Evolutions/EvoCriteria.cs | 2 + .../Legality/Evolutions/EvolutionMethod.cs | 94 +++++++++++-------- .../Evolutions/EvolutionSets/EvolutionSet3.cs | 41 ++++---- .../Legality/Evolutions/EvolutionType.cs | 56 +++++++++++ PKHeX.Core/PKM/PKM.cs | 34 ++++--- PKHeX.Core/Saves/SaveFile.cs | 1 + 7 files changed, 154 insertions(+), 78 deletions(-) create mode 100644 PKHeX.Core/Legality/Evolutions/EvolutionType.cs diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index bfda4b91f..6fd4341c5 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -504,11 +504,9 @@ private static bool IsEvolvedFormChange(PKM pkm) internal static bool IsTradeEvolved(IReadOnlyList[] chain, int pkmFormat) { - return chain[pkmFormat].Any(IsTradeEvolved); + return chain[pkmFormat].Any(z => z.IsTradeRequired); } - internal static bool IsTradeEvolved(EvoCriteria z) => EvolutionMethod.TradeMethods.Contains(z.Method); - internal static bool IsEvolutionValid(PKM pkm, int minSpecies = -1, int minLevel = -1) { var curr = EvolutionChain.GetValidPreEvolutions(pkm); diff --git a/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs b/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs index 151bde0cd..85059a683 100644 --- a/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs +++ b/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs @@ -6,5 +6,7 @@ public sealed class EvoCriteria : DexLevel public bool RequiresLvlUp { get; set; } public int Form { get; set; } = -1; public int Method { get; set; } = -1; + + public bool IsTradeRequired => ((EvolutionType) Method).IsTrade(); } } diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionMethod.cs b/PKHeX.Core/Legality/Evolutions/EvolutionMethod.cs index 7746cd5f1..beb4ef28d 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionMethod.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionMethod.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using static PKHeX.Core.EvolutionType; namespace PKHeX.Core { @@ -15,14 +16,19 @@ public sealed class EvolutionMethod public int Form = -1; public int Level; - public bool RequiresLevelUp; + // Not stored in binary data + public bool RequiresLevelUp; // tracks if this method requires levelup + internal IReadOnlyCollection Banlist = Array.Empty(); - internal static readonly HashSet TradeMethods = new HashSet {5, 6, 7}; - private static readonly IReadOnlyCollection NoBanlist = Array.Empty(); internal static readonly IReadOnlyCollection BanSM = new[] {GameVersion.SN, GameVersion.MN}; - internal static readonly IReadOnlyCollection BanGG = new[] {GameVersion.GP, GameVersion.GE}; - internal IReadOnlyCollection Banlist = NoBanlist; + /// + /// Checks the for validity by comparing against the data. + /// + /// Entity to check + /// Current level + /// Option to skip some comparisons to return a 'possible' evolution. + /// public bool Valid(PKM pkm, int lvl, bool skipChecks) { RequiresLevelUp = false; @@ -32,39 +38,40 @@ public bool Valid(PKM pkm, int lvl, bool skipChecks) return false; } - if (!skipChecks && Banlist.Contains((GameVersion)pkm.Version) && pkm.IsUntraded) // sm lacks usum kantonian evos + if (!skipChecks && Banlist.Count > 0 && Banlist.Contains((GameVersion)pkm.Version) && pkm.IsUntraded) // sm lacks usum kantonian evos return false; - switch (Method) + switch ((EvolutionType)Method) { - case 8: // Use Item - case 42: + case UseItem: + case UseItemWormhole: return true; - case 17: // Male + case UseItemMale: return pkm.Gender == 0; - case 18: // Female + case UseItemFemale: return pkm.Gender == 1; - case 5: // Trade Evolution - case 6: // Trade while Holding - case 7: // Trade for Opposite Species + case Trade: + case TradeHeldItem: + case TradeSpecies: return !pkm.IsUntraded || skipChecks; - // Special Levelup Cases - case 16 when !(pkm is IContestStats s) || s.CNT_Beauty < Argument: + // Special Levelup Cases -- return false if invalid + case LevelUpBeauty when !(pkm is IContestStats s) || s.CNT_Beauty < Argument: return skipChecks; - case 23 when pkm.Gender != 0: // Gender = Male + case LevelUpMale when pkm.Gender != 0: return false; - case 24 when pkm.Gender != 1: // Gender = Female + case LevelUpFemale when pkm.Gender != 1: return false; - case 34 when pkm.Gender != 1 || pkm.AltForm != 1: // Gender = Female, out Form1 + case LevelUpFormFemale1 when pkm.Gender != 1 || pkm.AltForm != 1: return false; - case 36 when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: // Any Time on Version - case 37 when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: // Daytime on Version - case 38 when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: // Nighttime on Version + case LevelUpVersion when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: + case LevelUpVersionDay when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: + case LevelUpVersionNight when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: return skipChecks; // Version checks come in pairs, check for any pair match + // Level Up (any); above levelup cases will reach here if they weren't invalid default: if (Level == 0 && lvl < 2) return false; @@ -76,23 +83,30 @@ public bool Valid(PKM pkm, int lvl, bool skipChecks) return lvl >= Level; // Check Met Level for extra validity - switch (pkm.GenNumber) - { - case 1: // No metdata in RBY - case 2: // No metdata in GS, Crystal metdata can be reset - return true; - case 3: - case 4: - if (pkm.Format > pkm.GenNumber) // Pal Park / PokeTransfer updates Met Level - return true; - return pkm.Met_Level < lvl; + return HasMetLevelIncreased(pkm, lvl); + } + } - case 5: // Bank keeps current level - case 6: - case 7: - return lvl >= Level && (!pkm.IsNative || pkm.Met_Level < lvl); - } - return false; + private bool HasMetLevelIncreased(PKM pkm, int lvl) + { + int origin = pkm.GenNumber; + switch (origin) + { + case 1: // No metdata in RBY + case 2: // No metdata in GS, Crystal metdata can be reset + return true; + case 3: + case 4: + if (pkm.Format > origin) // Pal Park / PokeTransfer updates Met Level + return true; + return pkm.Met_Level < lvl; + + case 5: // Bank keeps current level + case 6: + case 7: + return lvl >= Level && (!pkm.IsNative || pkm.Met_Level < lvl); + + default: return false; } } @@ -107,10 +121,8 @@ public EvoCriteria GetEvoCriteria(int species, int lvl) }; } - public EvolutionMethod Copy(int species = -1) + public EvolutionMethod Copy(int species) { - if (species < 0) - species = Species; return new EvolutionMethod { Method = Method, diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs index ea21ca0da..155470ab0 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; namespace PKHeX.Core { @@ -38,33 +37,43 @@ private static EvolutionMethod GetMethod(byte[] data, int offset) case 14: /* Shedinja spawn in Nincada -> Ninjask evolution */ return new EvolutionMethod { Method = method + 1, Species = species, Level = arg, Argument = arg }; } - return null; + throw new ArgumentException(nameof(method)); } - public static List GetArray(byte[] data) + private static readonly EvolutionSet Blank = new EvolutionSet3 { PossibleEvolutions = Array.Empty() }; + + public static IReadOnlyList GetArray(byte[] data) { - EvolutionSet[] evos = new EvolutionSet[Legal.MaxSpeciesID_3 + 1]; - evos[0] = new EvolutionSet3 { PossibleEvolutions = new EvolutionMethod[0] }; - for (int i = 0; i <= Legal.MaxSpeciesIndex_3; i++) + var evos = new EvolutionSet[Legal.MaxSpeciesID_3 + 1]; + evos[0] = Blank; + for (int i = 1; i <= Legal.MaxSpeciesIndex_3; i++) { int g4species = SpeciesConverter.GetG4Species(i); if (g4species == 0) continue; - int offset = i * 40; - var m_list = new List(); - for (int j = 0; j < 5; j++) + const int maxCount = 5; + const int size = 8; + + int offset = i * (maxCount * size); + int count = 0; + for (; count < maxCount; count++) { - EvolutionMethod m = GetMethod(data, offset); - if (m != null) - m_list.Add(m); - else + if (data[offset + (count * size)] == 0) break; - offset += 8; } - evos[g4species] = new EvolutionSet3 { PossibleEvolutions = m_list.ToArray() }; + if (count == 0) + { + evos[g4species] = Blank; + continue; + } + + var set = new EvolutionMethod[count]; + for (int j = 0; j < set.Length; j++) + set[j] = GetMethod(data, offset); + evos[g4species] = new EvolutionSet3 { PossibleEvolutions = set }; } - return evos.ToList(); + return evos; } } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionType.cs b/PKHeX.Core/Legality/Evolutions/EvolutionType.cs new file mode 100644 index 000000000..5fc036822 --- /dev/null +++ b/PKHeX.Core/Legality/Evolutions/EvolutionType.cs @@ -0,0 +1,56 @@ +using static PKHeX.Core.EvolutionType; + +namespace PKHeX.Core +{ + public enum EvolutionType : byte + { + None = 0, + LevelUpFriendship = 1, + LevelUpFriendshipMorning = 2, + LevelUpFriendshipNight = 3, + LevelUp = 4, + Trade = 5, + TradeHeldItem = 6, + TradeSpecies = 7, + UseItem = 8, + LevelUpATK = 9, + LevelUpDEF = 10, + LevelUpAeqD = 11, + LevelUpECl5 = 12, + LevelUpECgeq5 = 13, + LevelUpNinjask = 14, + LevelUpShedinja = 15, + LevelUpBeauty = 16, + UseItemMale = 17, + UseItemFemale = 18, + LevelUpHeldItemDay = 19, + LevelUpHeldItemNight = 20, + LevelUpKnowMove = 21, + LevelUpWithTeammate = 22, + LevelUpMale = 23, + LevelUpFemale = 24, + LevelUpElectric = 25, + LevelUpForest = 26, + LevelUpCold = 27, + LevelUpInverted = 28, + LevelUpAffection50MoveType = 29, + LevelUpMoveType = 30, + LevelUpWeather = 31, + LevelUpMorning = 32, + LevelUpNight = 33, + LevelUpFormFemale1 = 34, + UNUSED = 35, + LevelUpVersion = 36, + LevelUpVersionDay = 37, + LevelUpVersionNight = 38, + LevelUpSummit = 39, + LevelUpDusk = 40, + LevelUpWormhole = 41, + UseItemWormhole = 42, + } + + public static class EvolutionTypeExtensions + { + public static bool IsTrade(this EvolutionType t) => t == Trade || t == TradeHeldItem || t == TradeSpecies; + } +} \ No newline at end of file diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index d2bd3b419..a50603ae3 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -640,7 +640,7 @@ public virtual bool IsGenderValid() return gender == 0; int gen = GenNumber; - if (2 >= gen || gen >= 6) + if (gen <= 2 || gen >= 6) return gender == (gender & 1); return gender == PKX.GetGenderFromPIDAndRatio(PID, gv); @@ -669,28 +669,26 @@ public void FixMoves() /// private void ReorderMoves() { - if (Move4 != 0 && Move3 == 0) - { - Move3 = Move4; - Move3_PP = Move4_PP; - Move3_PPUps = Move4_PPUps; - Move4 = 0; - } - if (Move3 != 0 && Move2 == 0) - { - Move2 = Move3; - Move2_PP = Move3_PP; - Move2_PPUps = Move3_PPUps; - Move3 = 0; - ReorderMoves(); - } - if (Move2 != 0 && Move1 == 0) + if (Move1 == 0 && Move2 != 0) { Move1 = Move2; Move1_PP = Move2_PP; Move1_PPUps = Move2_PPUps; Move2 = 0; - ReorderMoves(); + } + if (Move2 == 0 && Move3 != 0) + { + Move2 = Move3; + Move2_PP = Move3_PP; + Move2_PPUps = Move3_PPUps; + Move3 = 0; + } + if (Move3 == 0 && Move4 != 0) + { + Move3 = Move4; + Move3_PP = Move4_PP; + Move3_PPUps = Move4_PPUps; + Move4 = 0; } } diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs index 77e5cf8c6..6bf8446a3 100644 --- a/PKHeX.Core/Saves/SaveFile.cs +++ b/PKHeX.Core/Saves/SaveFile.cs @@ -71,6 +71,7 @@ protected virtual byte[] Write(bool DSV) public abstract int Generation { get; } public PersonalTable Personal { get; set; } + public bool GG => Data.Length == SaveUtil.SIZE_G7GG && GameVersion.GG.Contains(Version); public bool USUM => Data.Length == SaveUtil.SIZE_G7USUM; public bool SM => Data.Length == SaveUtil.SIZE_G7SM; public bool ORASDEMO => Data.Length == SaveUtil.SIZE_G6ORASDEMO;