From 24b55b7b79afba85d0c9f0db8ecef3f12a7cd7b3 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 1 May 2017 23:41:19 -0700 Subject: [PATCH] Add gen3 roamer pidiv detection add shiny lock for spiky eared pichu fix wurmple ECPID comparison (only continue if ALL are wurmple) slightly speed up comparison of LCRNG spreads, may be worth applying same approach to others. --- PKHeX/Legality/Checks.cs | 2 +- PKHeX/Legality/RNG/MethodFinder.cs | 127 +++++++++++++++++++++-------- PKHeX/Legality/RNG/PIDType.cs | 2 + PKHeX/Legality/Tables4.cs | 2 +- 4 files changed, 96 insertions(+), 37 deletions(-) diff --git a/PKHeX/Legality/Checks.cs b/PKHeX/Legality/Checks.cs index 0063b0e85..7d84d5fd0 100644 --- a/PKHeX/Legality/Checks.cs +++ b/PKHeX/Legality/Checks.cs @@ -166,7 +166,7 @@ namespace PKHeX.Core } // Check if Wurmple was the origin (only Egg and Wild Encounter) - bool wasWurmple = pkm.WasEgg || (Type == typeof (EncounterSlot[]) && ((EncounterSlot[])EncounterMatch).Any(slot => slot.Species == 265)); + bool wasWurmple = pkm.WasEgg || (Type == typeof (EncounterSlot[]) && ((EncounterSlot[])EncounterMatch).All(slot => slot.Species == 265)); if (!wasWurmple) return; diff --git a/PKHeX/Legality/RNG/MethodFinder.cs b/PKHeX/Legality/RNG/MethodFinder.cs index 8ed37005f..0622dcd77 100644 --- a/PKHeX/Legality/RNG/MethodFinder.cs +++ b/PKHeX/Legality/RNG/MethodFinder.cs @@ -38,6 +38,8 @@ namespace PKHeX.Core return pidiv; // Special cases + if (getLCRNGRoamerMatch(top, bot, IVs, out pidiv)) + return pidiv; if (getChannelMatch(top, bot, IVs, out pidiv)) return pidiv; if (getMG4Match(pid, IVs, out pidiv)) @@ -61,6 +63,8 @@ namespace PKHeX.Core private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv) { var reg = getSeedsFromPID(RNG.LCRNG, top, bot); + var iv1 = getIVChunk(IVs, 0); + var iv2 = getIVChunk(IVs, 3); foreach (var seed in reg) { // A and B are already used by PID @@ -68,25 +72,39 @@ namespace PKHeX.Core // Method 1/2/4 can use 3 different RNG frames var C = RNG.LCRNG.Next(B); - var D = RNG.LCRNG.Next(C); - - if (getIVs(C >> 16, D >> 16).SequenceEqual(IVs)) // ABCD + var ivC = C >> 16 & 0x7FFF; + if (iv1 == ivC) { - pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1}; - return true; + var D = RNG.LCRNG.Next(C); + var ivD = D >> 16 & 0x7FFF; + if (iv2 == ivD) // ABCD + { + pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1}; + return true; + } + + var E = RNG.LCRNG.Next(D); + var ivE = E >> 16 & 0x7FFF; + if (iv2 == ivE) // ABCE + { + pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4}; + return true; + } } - - var E = RNG.LCRNG.Next(D); - if (getIVs(D >> 16, E >> 16).SequenceEqual(IVs)) // ABDE + else { - pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2}; - return true; - } + var D = RNG.LCRNG.Next(C); + var ivD = D >> 16 & 0x7FFF; + if (iv1 != ivD) + continue; - if (getIVs(C >> 16, E >> 16).SequenceEqual(IVs)) // ABCE - { - pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4}; - return true; + var E = RNG.LCRNG.Next(D); + var ivE = E >> 16 & 0x7FFF; + if (iv2 == ivE) // ABDE + { + pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2}; + return true; + } } } pidiv = null; @@ -96,6 +114,8 @@ namespace PKHeX.Core { // this is an exact copy of LCRNG 1,2,4 matching, except the PID has its halves switched (BACD, BADE, BACE) var reg = getSeedsFromPID(RNG.LCRNG, bot, top); // reversed! + var iv1 = getIVChunk(IVs, 0); + var iv2 = getIVChunk(IVs, 3); foreach (var seed in reg) { // A and B are already used by PID @@ -103,30 +123,67 @@ namespace PKHeX.Core // Method 1/2/4 can use 3 different RNG frames var C = RNG.LCRNG.Next(B); - var D = RNG.LCRNG.Next(C); - - if (getIVs(C >> 16, D >> 16).SequenceEqual(IVs)) // BACD + var ivC = C >> 16 & 0x7FFF; + if (iv1 == ivC) { - pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Unown }; - return true; - } + var D = RNG.LCRNG.Next(C); + var ivD = D >> 16 & 0x7FFF; + if (iv2 == ivD) // BACD + { + pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Unown}; + return true; + } - var E = RNG.LCRNG.Next(D); - if (getIVs(D >> 16, E >> 16).SequenceEqual(IVs)) // BADE - { - pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2_Unown }; - return true; + var E = RNG.LCRNG.Next(D); + var ivE = E >> 16 & 0x7FFF; + if (iv2 == ivE) // BACE + { + pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4_Unown}; + return true; + } } + else + { + var D = RNG.LCRNG.Next(C); + var ivD = D >> 16 & 0x7FFF; + if (iv1 != ivD) + continue; - if (getIVs(C >> 16, E >> 16).SequenceEqual(IVs)) // BACE - { - pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4_Unown }; - return true; + var E = RNG.LCRNG.Next(D); + var ivE = E >> 16 & 0x7FFF; + if (iv2 != ivE) // BADE + { + pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2_Unown}; + return true; + } } } pidiv = null; return false; } + private static bool getLCRNGRoamerMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv) + { + var iv2 = getIVChunk(IVs, 3); + if (iv2 != 0 || IVs[2] != 0) + { + pidiv = null; + return false; + } + var iv1 = getIVChunk(IVs, 0); + var reg = getSeedsFromPID(RNG.LCRNG, top, bot); + foreach (var seed in reg) + { + // Only the first two IVs are kept + var ivC = RNG.LCRNG.Advance(seed, 3) >> 16 & 0x03FF; + if (iv1 != ivC) + continue; + + pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Roamer}; + return true; + } + pidiv = null; + return false; + } private static bool getXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv) { var xdc = getSeedsFromPID(RNG.XDRNG, bot, top); @@ -280,8 +337,8 @@ namespace PKHeX.Core var B = seed; var A = RNG.LCRNG.Prev(B); - var PID = A & 0xFFFF0000 | (B >> 16); - bool isShiny = (pk.TID ^ pk.SID ^ (PID >> 16) ^ (PID & 0xFFFF)) < 8; + var PID = A & 0xFFFF0000 | B >> 16; + bool isShiny = (pk.TID ^ pk.SID ^ PID >> 16 ^ PID & 0xFFFF) < 8; bool forceShiny = false; if (PID != pid) { @@ -306,12 +363,12 @@ namespace PKHeX.Core continue; forceShiny = true; } - if (!forceShiny && ((PID + 8) & 0xFFFFFFF8) != pid) + if (!forceShiny && (PID + 8 & 0xFFFFFFF8) != pid) continue; } var s = RNG.LCRNG.Prev(A); - // Check for Restricted generation pattern + // Check for prior Restricted seed var sn = s; for (int i = 0; i < 3; i++, sn = RNG.LCRNG.Prev(sn)) { @@ -321,7 +378,7 @@ namespace PKHeX.Core pidiv = new PIDIV {OriginSeed = sn, RNG = RNG.LCRNG, Type = type}; return true; } - + // no restricted seed found, thus unrestricted var t = forceShiny ? PIDType.BACD_U_S : isShiny ? PIDType.BACD_U_A : PIDType.BACD_U; pidiv = new PIDIV {OriginSeed = s, RNG = RNG.LCRNG, Type = t}; return true; diff --git a/PKHeX/Legality/RNG/PIDType.cs b/PKHeX/Legality/RNG/PIDType.cs index d7e199d05..1aeaf4483 100644 --- a/PKHeX/Legality/RNG/PIDType.cs +++ b/PKHeX/Legality/RNG/PIDType.cs @@ -17,6 +17,8 @@ Method_2_Unown, /// Method H4_Unown (FRLG) Method_4_Unown, + /// Method 1 Roamer (Gen3) + Method_1_Roamer, /// /// Event Reversed Order PID restricted to 16bit Origin Seed diff --git a/PKHeX/Legality/Tables4.cs b/PKHeX/Legality/Tables4.cs index 413b7a727..1572cf7e6 100644 --- a/PKHeX/Legality/Tables4.cs +++ b/PKHeX/Legality/Tables4.cs @@ -723,7 +723,7 @@ namespace PKHeX.Core new EncounterStatic { Species = 143, Level = 50, Location = 159, }, //Snorlax @ Route 11 new EncounterStatic { Species = 143, Level = 50, Location = 160, }, //Snorlax @ Route 12 new EncounterStatic { Species = 185, Level = 20, Location = 184, }, //Sudowoodo @ Route 36, Encounter does not have type - new EncounterStaticTyped { Species = 172, Level = 30, Location = 214, Gender = 1, Form = 1, Moves = new[]{344,270,207,220}, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, //Spiky-eared Pichu @ Ilex forest + new EncounterStaticTyped { Species = 172, Level = 30, Location = 214, Gender = 1, Form = 1, Moves = new[]{344,270,207,220}, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Shiny = false }, //Spiky-eared Pichu @ Ilex forest //Stationary Lengerdary new EncounterStaticTyped { Species = 144, Level = 50, Location = 203, TypeEncounter = EncounterType.Cave_HallOfOrigin }, //Articuno @ Seafoam Islands new EncounterStatic { Species = 145, Level = 50, Location = 158, }, //Zapdos @ Route 10