From 7f6f7a7badcc5abe0e6534f3909a9f7ecad6d151 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 1 Jul 2018 19:55:23 -0700 Subject: [PATCH] Misc simplifications reduce nesting (evo.RequiresLevelUp is checked twice, only check once and handle path) compact some methods seal some classes add a little xmldoc to exposed members --- PKHeX.Core/Legality/Evolutions/EvoCriteria.cs | 2 +- .../Legality/Evolutions/EvolutionLineage.cs | 28 +-- .../Legality/Evolutions/EvolutionMethod.cs | 2 +- .../Evolutions/EvolutionSets/EvolutionSet1.cs | 2 +- .../Evolutions/EvolutionSets/EvolutionSet2.cs | 2 +- .../Evolutions/EvolutionSets/EvolutionSet3.cs | 2 +- .../Evolutions/EvolutionSets/EvolutionSet4.cs | 2 +- .../Evolutions/EvolutionSets/EvolutionSet5.cs | 2 +- .../Evolutions/EvolutionSets/EvolutionSet6.cs | 2 +- .../Evolutions/EvolutionSets/EvolutionSet7.cs | 2 +- .../Legality/Evolutions/EvolutionTree.cs | 175 +++++++++--------- PKHeX.Core/Legality/Learnset/Learnset1.cs | 2 +- PKHeX.Core/Legality/Learnset/Learnset6.cs | 7 +- 13 files changed, 119 insertions(+), 111 deletions(-) diff --git a/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs b/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs index 76962f5cc..151bde0cd 100644 --- a/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs +++ b/PKHeX.Core/Legality/Evolutions/EvoCriteria.cs @@ -1,6 +1,6 @@ namespace PKHeX.Core { - public class EvoCriteria : DexLevel + public sealed class EvoCriteria : DexLevel { public int MinLevel { get; set; } public bool RequiresLvlUp { get; set; } diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionLineage.cs b/PKHeX.Core/Legality/Evolutions/EvolutionLineage.cs index 8a173700f..a5bfe3520 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionLineage.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionLineage.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core /// /// Informatics pertaining to a 's evolution lineage. /// - public class EvolutionLineage + public sealed class EvolutionLineage { public readonly List Chain = new List(); @@ -30,7 +30,8 @@ public void Insert(EvolutionStage evo) public List GetExplicitLineage(PKM pkm, int maxLevel, bool skipChecks, int maxSpeciesTree, int maxSpeciesOrigin, int minLevel) { int lvl = maxLevel; - List dl = new List { new EvoCriteria { Species = pkm.Species, Level = lvl, Form = pkm.AltForm } }; + var first = new EvoCriteria {Species = pkm.Species, Level = lvl, Form = pkm.AltForm}; + var dl = new List { first }; for (int i = Chain.Count - 1; i >= 0; i--) // reverse evolution! { bool oneValid = false; @@ -73,19 +74,20 @@ public List GetExplicitLineage(PKM pkm, int maxLevel, bool skipChec private static void UpdateMinValues(IReadOnlyList dl, EvolutionMethod evo) { var last = dl[dl.Count - 1]; - if (evo.Level == 0 || !evo.RequiresLevelUp) // Evolutions like elemental stones, trade, etc + if (!evo.RequiresLevelUp) { - if (!evo.RequiresLevelUp) - last.MinLevel = 1; - else - { - // Evolutions like frienship, pichu -> pikachu, eevee -> umbreon, etc - last.MinLevel = 2; + // Evolutions like elemental stones, trade, etc + last.MinLevel = 1; + return; + } + if (evo.Level == 0) + { + // Evolutions like frienship, pichu -> pikachu, eevee -> umbreon, etc + last.MinLevel = 2; - var first = dl[0]; - if (dl.Count > 1 && !first.RequiresLvlUp) - first.MinLevel = 2; // Raichu from Pikachu would have minimum level 1, but with Pichu included Raichu minimum level is 2 - } + var first = dl[0]; + if (dl.Count > 1 && !first.RequiresLvlUp) + first.MinLevel = 2; // Raichu from Pikachu would have minimum level 1, but with Pichu included Raichu minimum level is 2 } else // level up evolutions { diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionMethod.cs b/PKHeX.Core/Legality/Evolutions/EvolutionMethod.cs index 3d46a1588..aac2612b1 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionMethod.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionMethod.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core /// /// Criteria for evolving to this branch in the /// - public class EvolutionMethod + public sealed class EvolutionMethod { public int Method; public int Species; diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet1.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet1.cs index 1daa32711..ffd3775a2 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet1.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet1.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core /// /// Generation 1 Evolution Branch Entries /// - public class EvolutionSet1 : EvolutionSet + public sealed class EvolutionSet1 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, ref int offset) { diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet2.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet2.cs index 1bde693e1..d547c57cc 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet2.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet2.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core /// /// Generation 2 Evolution Branch Entries /// - public class EvolutionSet2 : EvolutionSet + public sealed class EvolutionSet2 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, ref int offset) { diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs index 57df41a28..e17f728a8 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet3.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core /// /// Generation 3 Evolution Branch Entries /// - public class EvolutionSet3 : EvolutionSet + public sealed class EvolutionSet3 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, int offset) { diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet4.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet4.cs index 2ed4270da..fc9283ab3 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet4.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet4.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core /// /// Generation 4 Evolution Branch Entries /// - public class EvolutionSet4 : EvolutionSet + public sealed class EvolutionSet4 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, int offset) { diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet5.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet5.cs index 6143aedb2..749ebba63 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet5.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet5.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core /// /// Generation 5 Evolution Branch Entries /// - public class EvolutionSet5 : EvolutionSet + public sealed class EvolutionSet5 : EvolutionSet { private static EvolutionMethod GetMethod(byte[] data, int offset) { diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet6.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet6.cs index ae18fa4ac..45ca21bca 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet6.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet6.cs @@ -6,7 +6,7 @@ namespace PKHeX.Core /// /// Generation 6 Evolution Branch Entries /// - public class EvolutionSet6 : EvolutionSet + public sealed class EvolutionSet6 : EvolutionSet { private static readonly HashSet argEvos = new HashSet {6, 8, 16, 17, 18, 19, 20, 21, 22, 29}; private const int SIZE = 6; diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet7.cs b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet7.cs index b0d59e02b..c17696f95 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet7.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionSets/EvolutionSet7.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core /// /// Generation 7 Evolution Branch Entries /// - public class EvolutionSet7 : EvolutionSet + public sealed class EvolutionSet7 : EvolutionSet { private const int SIZE = 8; public EvolutionSet7(byte[] data) diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs b/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs index e0ccac125..d11a58e0b 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs @@ -10,7 +10,7 @@ namespace PKHeX.Core /// /// Used to determine if a can evolve from prior steps in its evolution branch. /// - public class EvolutionTree + public sealed class EvolutionTree { private static readonly EvolutionTree Evolves1; private static readonly EvolutionTree Evolves2; @@ -26,118 +26,113 @@ static EvolutionTree() byte[] get(string resource) => Util.GetBinaryResource($"evos_{resource}.pkl"); byte[][] unpack(string resource) => Data.UnpackMini(get(resource), resource); - Evolves1 = new EvolutionTree(new[] { get("rby") }, GameVersion.RBY, PersonalTable.Y, Legal.MaxSpeciesID_1); - Evolves2 = new EvolutionTree(new[] { get("gsc") }, GameVersion.GSC, PersonalTable.C, Legal.MaxSpeciesID_2); - Evolves3 = new EvolutionTree(new[] { get("g3") }, GameVersion.RS, PersonalTable.RS, Legal.MaxSpeciesID_3); - Evolves4 = new EvolutionTree(new[] { get("g4") }, GameVersion.DP, PersonalTable.DP, Legal.MaxSpeciesID_4); - Evolves5 = new EvolutionTree(new[] { get("g5") }, GameVersion.BW, PersonalTable.BW, Legal.MaxSpeciesID_5); - Evolves6 = new EvolutionTree(unpack("ao"), GameVersion.ORAS, PersonalTable.AO, Legal.MaxSpeciesID_6); - Evolves7 = new EvolutionTree(unpack("uu"), GameVersion.USUM, PersonalTable.USUM, Legal.MaxSpeciesID_7_USUM); + Evolves1 = new EvolutionTree(new[] { get("rby") }, GameVersion.Gen1, PersonalTable.Y, Legal.MaxSpeciesID_1); + Evolves2 = new EvolutionTree(new[] { get("gsc") }, GameVersion.Gen2, PersonalTable.C, Legal.MaxSpeciesID_2); + Evolves3 = new EvolutionTree(new[] { get("g3") }, GameVersion.Gen3, PersonalTable.RS, Legal.MaxSpeciesID_3); + Evolves4 = new EvolutionTree(new[] { get("g4") }, GameVersion.Gen4, PersonalTable.DP, Legal.MaxSpeciesID_4); + Evolves5 = new EvolutionTree(new[] { get("g5") }, GameVersion.Gen5, PersonalTable.BW, Legal.MaxSpeciesID_5); + Evolves6 = new EvolutionTree(unpack("ao"), GameVersion.Gen6, PersonalTable.AO, Legal.MaxSpeciesID_6); + Evolves7 = new EvolutionTree(unpack("uu"), GameVersion.Gen7, PersonalTable.USUM, Legal.MaxSpeciesID_7_USUM); + + // There's always oddballs. + Evolves7.FixEvoTreeSM(); } + internal static EvolutionTree GetEvolutionTree(int generation) { switch (generation) { - case 1: - return Evolves1; - case 2: - return Evolves2; - case 3: - return Evolves3; - case 4: - return Evolves4; - case 5: - return Evolves5; - case 6: - return Evolves6; + case 1: return Evolves1; + case 2: return Evolves2; + case 3: return Evolves3; + case 4: return Evolves4; + case 5: return Evolves5; + case 6: return Evolves6; default: return Evolves7; } } - private List Entries { get; } = new List(); + private readonly IReadOnlyList Entries; private readonly EvolutionLineage[] Lineage; private readonly GameVersion Game; private readonly PersonalTable Personal; private readonly int MaxSpeciesTree; - public EvolutionTree(byte[][] data, GameVersion game, PersonalTable personal, int maxSpeciesTree) + private EvolutionTree(IReadOnlyList data, GameVersion game, PersonalTable personal, int maxSpeciesTree) { Game = game; Personal = personal; MaxSpeciesTree = maxSpeciesTree; - switch (game) - { - case GameVersion.RBY: - Entries = EvolutionSet1.GetArray(data[0], maxSpeciesTree); - break; - case GameVersion.GSC: - Entries = EvolutionSet2.GetArray(data[0], maxSpeciesTree); - break; - case GameVersion.RS: - Entries = EvolutionSet3.GetArray(data[0]); - break; - case GameVersion.DP: - Entries = EvolutionSet4.GetArray(data[0]); - break; - case GameVersion.BW: - Entries = EvolutionSet5.GetArray(data[0]); - break; - case GameVersion.ORAS: - Entries.AddRange(data.Select(d => new EvolutionSet6(d))); - break; - case GameVersion.USUM: - Entries.AddRange(data.Select(d => new EvolutionSet7(d))); - break; - } + Entries = GetEntries(data); + Lineage = CreateTree(); + } - // Create Lineages - Lineage = new EvolutionLineage[Entries.Count]; + private IReadOnlyList GetEntries(IReadOnlyList data) + { + switch (Game) + { + case GameVersion.Gen1: return EvolutionSet1.GetArray(data[0], MaxSpeciesTree); + case GameVersion.Gen2: return EvolutionSet2.GetArray(data[0], MaxSpeciesTree); + case GameVersion.Gen3: return EvolutionSet3.GetArray(data[0]); + case GameVersion.Gen4: return EvolutionSet4.GetArray(data[0]); + case GameVersion.Gen5: return EvolutionSet5.GetArray(data[0]); + case GameVersion.Gen6: return new List(data.Select(d => new EvolutionSet6(d))); + case GameVersion.Gen7: return new List(data.Select(d => new EvolutionSet7(d))); + default: throw new Exception(); + } + } + + private EvolutionLineage[] CreateTree() + { + var lineage = new EvolutionLineage[Entries.Count]; for (int i = 0; i < Entries.Count; i++) - Lineage[i] = new EvolutionLineage(); + lineage[i] = new EvolutionLineage(); if (Game == GameVersion.ORAS) - Array.Resize(ref Lineage, MaxSpeciesTree + 1); + Array.Resize(ref lineage, MaxSpeciesTree + 1); // Populate Lineages - for (int i = 1; i < Lineage.Length; i++) - { - // Iterate over all possible evolutions - var s = Entries[i]; - foreach (EvolutionMethod evo in s.PossibleEvolutions) - { - int index = GetIndex(evo); - if (index < 0) - continue; - - var sourceEvo = evo.Copy(i); - - Lineage[index].Insert(sourceEvo); - // If current entries has a pre-evolution, propagate to evolution as well - if (Lineage[i].Chain.Count > 0) - Lineage[index].Insert(Lineage[i].Chain[0]); - - if (index >= i) continue; - // If destination species evolves into something (ie a 'baby' Pokemon like Cleffa) - // Add it to the corresponding parent chains - foreach (EvolutionMethod mid in Entries[index].PossibleEvolutions) - { - int newIndex = GetIndex(mid); - if (newIndex < 0) - continue; - - Lineage[newIndex].Insert(sourceEvo); - } - } - } - FixEvoTreeManually(); + for (int i = 1; i < lineage.Length; i++) + CreateBranch(lineage, i); + return lineage; } - // There's always oddballs. - private void FixEvoTreeManually() + private void CreateBranch(IReadOnlyList lineage, int i) { - if (Game == GameVersion.USUM) - FixEvoTreeSM(); + // Iterate over all possible evolutions + foreach (var evo in Entries[i].PossibleEvolutions) + CreateLeaf(lineage, i, evo); } + + private void CreateLeaf(IReadOnlyList lineage, int i, EvolutionMethod evo) + { + int index = GetIndex(evo); + if (index < 0) + return; + + var sourceEvo = evo.Copy(i); + + lineage[index].Insert(sourceEvo); + // If current entries has a pre-evolution, propagate to evolution as well + var current = lineage[i].Chain; + if (current.Count > 0) + lineage[index].Insert(current[0]); + + if (index >= i) + return; + + // If destination species evolves into something (ie a 'baby' Pokemon like Cleffa) + // Add it to the corresponding parent chains + foreach (var method in Entries[index].PossibleEvolutions) + { + int newIndex = GetIndex(method); + if (newIndex < 0) + continue; + + lineage[newIndex].Insert(sourceEvo); + } + } + private void FixEvoTreeSM() { // Wormadam -- Copy Burmy 0 to Wormadam-1/2 @@ -201,6 +196,16 @@ private int GetIndex(EvolutionMethod evo) return Personal.GetFormeIndex(evolvesToSpecies, evolvesToForm); } + + /// + /// Gets a list of evolutions for the input by checking each evolution in the chain. + /// + /// Pokémon data to check with. + /// Maximum level to permit before the chain breaks. + /// Maximum species ID to permit within the chain. + /// Ignores an evolution's criteria, causing the returned list to have all possible evolutions. + /// Minimum level to permit before the chain breaks. + /// public List GetValidPreEvolutions(PKM pkm, int maxLevel, int maxSpeciesOrigin = -1, bool skipChecks = false, int minLevel = 1) { int index = GetIndex(pkm); diff --git a/PKHeX.Core/Legality/Learnset/Learnset1.cs b/PKHeX.Core/Legality/Learnset/Learnset1.cs index baadf63d2..3fe7dbff5 100644 --- a/PKHeX.Core/Legality/Learnset/Learnset1.cs +++ b/PKHeX.Core/Legality/Learnset/Learnset1.cs @@ -2,7 +2,7 @@ namespace PKHeX.Core { - public class Learnset1 : Learnset + public sealed class Learnset1 : Learnset { private Learnset1(byte[] data, ref int offset) { diff --git a/PKHeX.Core/Legality/Learnset/Learnset6.cs b/PKHeX.Core/Legality/Learnset/Learnset6.cs index 531a77fc1..9a71f2706 100644 --- a/PKHeX.Core/Legality/Learnset/Learnset6.cs +++ b/PKHeX.Core/Legality/Learnset/Learnset6.cs @@ -2,16 +2,17 @@ namespace PKHeX.Core { - public class Learnset6 : Learnset + public sealed class Learnset6 : Learnset { private Learnset6(byte[] data) { if (data.Length < 4 || data.Length % 4 != 0) { Count = 0; Levels = new int[0]; Moves = new int[0]; return; } - Count = data.Length / 4 - 1; + Count = (data.Length / 4) - 1; Moves = new int[Count]; Levels = new int[Count]; - using (BinaryReader br = new BinaryReader(new MemoryStream(data))) + using (var ms = new MemoryStream(data)) + using (var br = new BinaryReader(ms)) for (int i = 0; i < Count; i++) { Moves[i] = br.ReadInt16();