Beispiel #1
0
        /// <summary>
        /// Yields an enumerable list of seeds until another valid PID breaks the chain.
        /// </summary>
        /// <param name="pidiv">Seed and RNG data</param>
        /// <param name="info">Verification information</param>
        /// <param name="form">Unown Form lock value</param>
        /// <returns>Seed information data, which needs to be unrolled once for the nature call.</returns>
        public static IEnumerable <SeedInfo> GetSeedsUntilUnownForm(PIDIV pidiv, FrameGenerator info, int form)
        {
            var seed = pidiv.OriginSeed;

            yield return(new SeedInfo(seed));

            var s1 = seed;
            var s2 = RNG.LCRNG.Prev(s1);

            while (true)
            {
                var a = s2 >> 16;
                var b = s1 >> 16;
                // PID is in reverse for FRLG Unown
                var pid = a << 16 | b;

                // Process Conditions
                if (PKX.GetUnownForm(pid) == form) // matches form, does it match nature?
                {
                    switch (VerifyPIDCriteria(pid, info))
                    {
                    case LockInfo.Pass:     // yes
                        yield break;
                    }
                }

                s1 = RNG.LCRNG.Prev(s2);
                s2 = RNG.LCRNG.Prev(s1);

                yield return(new SeedInfo(s1));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Yields an enumerable list of seeds until another valid PID breaks the chain.
        /// </summary>
        /// <param name="pidiv">Seed and RNG data</param>
        /// <param name="info">Verification information</param>
        /// <returns>Seed information data, which needs to be unrolled once for the nature call.</returns>
        public static IEnumerable <SeedInfo> GetSeedsUntilNature(PIDIV pidiv, FrameGenerator info)
        {
            bool charm3 = false;

            var seed = pidiv.OriginSeed;

            yield return(new SeedInfo(seed));

            var s1 = seed;
            var s2 = RNG.LCRNG.Prev(s1);

            while (true)
            {
                var a = s2 >> 16;
                var b = s1 >> 16;

                var pid = b << 16 | a;

                // Process Conditions
                switch (VerifyPIDCriteria(pid, info))
                {
                case LockInfo.Pass:
                    yield break;

                case LockInfo.Gender:
                    charm3 = true;
                    break;
                }

                s1 = RNG.LCRNG.Prev(s2);
                s2 = RNG.LCRNG.Prev(s1);

                yield return(new SeedInfo(s1, charm3));
            }
        }
Beispiel #3
0
        private static bool GetColoStarterMatch(PKM pk, uint top, uint bot, uint[] IVs, out PIDIV pidiv)
        {
            if (pk.Version != 15 || (pk.Species != 196 && pk.Species != 197))
            {
                return(GetNonMatch(out pidiv));
            }

            var iv1 = GetIVChunk(IVs, 0);
            var iv2 = GetIVChunk(IVs, 3);
            var xdc = GetSeedsFromPIDEuclid(RNG.XDRNG, top, bot);

            foreach (var seed in xdc)
            {
                uint origin = seed;
                if (!LockFinder.IsColoStarterValid(pk.Species, ref origin, pk.TID, pk.SID, pk.PID, iv1, iv2))
                {
                    continue;
                }

                pidiv = new PIDIV {
                    OriginSeed = origin, RNG = RNG.XDRNG, Type = PIDType.CXD_ColoStarter
                };
                return(true);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #4
0
        private static bool GetPokewalkerMatch(PKM pk, uint oldpid, out PIDIV pidiv)
        {
            // check surface compatibility
            var mid = oldpid & 0x00FFFF00;

            if (mid != 0 && mid != 0x00FFFF00) // not expected bits
            {
                return(GetNonMatch(out pidiv));
            }
            var nature = oldpid % 25;

            if (nature == 24) // impossible nature
            {
                return(GetNonMatch(out pidiv));
            }

            var  gender = pk.Gender;
            uint pid    = PIDGenerator.GetPokeWalkerPID(pk.TID, pk.SID, nature, gender, pk.PersonalInfo.Gender);

            if (pid != oldpid)
            {
                if (!(gender == 0 && IsAzurillEdgeCaseM(pk, nature, oldpid)))
                {
                    return(GetNonMatch(out pidiv));
                }
            }
            pidiv = new PIDIV {
                NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.Pokewalker
            };
            return(true);
        }
Beispiel #5
0
        private static bool GetLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
        {
            // 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
                var B = RNG.LCRNG.Advance(seed, 2);

                // Method 1/2/4 can use 3 different RNG frames
                var C   = RNG.LCRNG.Next(B);
                var ivC = C >> 16 & 0x7FFF;
                if (iv1 == ivC)
                {
                    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);
                    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;
                    }

                    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);
        }
        /// <summary>
        /// Checks a <see cref="PIDIV"/> to see if any encounter frames can generate the spread. Requires further filtering against matched Encounter Slots and generation patterns.
        /// </summary>
        /// <param name="pidiv">Matched <see cref="PIDIV"/> containing <see cref="PIDIV.RNG"/> info and <see cref="PIDIV.OriginSeed"/>.</param>
        /// <param name="pk"><see cref="PKM"/> object containing various accessible information required for the encounter.</param>
        /// <returns><see cref="IEnumerable{Frame}"/> to yield possible encounter details for further filtering</returns>
        public static IEnumerable <Frame> GetFrames(PIDIV pidiv, PKM pk)
        {
            FrameGenerator info = new FrameGenerator(pidiv, pk);

            if (info.FrameType == FrameType.None)
            {
                yield break;
            }

            info.Nature = pk.EncryptionConstant % 25;

            // gather possible nature determination seeds until a same-nature PID breaks the unrolling
            IEnumerable <SeedInfo> seeds = SeedInfo.GetSeedsUntilNature(pidiv, info);

            var frames = pidiv.Type == PIDType.CuteCharm
                ? FilterCuteCharm(seeds, pidiv, info)
                : FilterNatureSync(seeds, pidiv, info);

            var refined = RefineFrames(frames, info);

            foreach (var z in refined)
            {
                yield return(z);
            }
        }
Beispiel #7
0
        private static bool GetLCRNGRoamerMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
        {
            if (IVs.Skip(2).Any(iv => iv != 0) || IVs[1] > 7)
            {
                pidiv = null;
                return(false);
            }
            var iv1 = GetIVChunk(IVs, 0);
            var reg = GetSeedsFromPID(RNG.LCRNG, top, bot);

            foreach (var seed in reg)
            {
                // Only the first 8 bits are kept
                var ivC = RNG.LCRNG.Advance(seed, 3) >> 16 & 0x00FF;
                if (iv1 != ivC)
                {
                    continue;
                }

                pidiv = new PIDIV {
                    OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Roamer
                };
                return(true);
            }
            pidiv = null;
            return(false);
        }
Beispiel #8
0
        private static bool GetChainShinyMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
        {
            // 13 shiny bits
            // PIDH & 7
            // PIDL & 7
            // IVs
            var bot = GetIVChunk(IVs, 0);
            var top = GetIVChunk(IVs, 3);
            var reg = GetSeedsFromIVs(RNG.LCRNG, top, bot);

            foreach (var seed in reg)
            {
                // check the individual bits
                var s = seed;
                int i = 15;
                while (true)
                {
                    var bit = s >> 16 & 1;
                    if (bit != (pid >> i & 1))
                    {
                        break;
                    }
                    s = RNG.LCRNG.Prev(s);
                    if (--i == 2)
                    {
                        break;
                    }
                }
                if (i != 2) // bit failed
                {
                    continue;
                }
                // Shiny Bits of PID validated
                var upper = s;
                if ((upper >> 16 & 7) != (pid >> 16 & 7))
                {
                    continue;
                }
                var lower = RNG.LCRNG.Prev(upper);
                if ((lower >> 16 & 7) != (pid & 7))
                {
                    continue;
                }

                var upid = ((pid & 0xFFFF) ^ pk.TID ^ pk.SID) & 0xFFF8 | (upper >> 16) & 0x7;
                if (upid != pid >> 16)
                {
                    continue;
                }

                s     = RNG.LCRNG.Reverse(lower, 2); // unroll one final time to get the origin seed
                pidiv = new PIDIV {
                    OriginSeed = s, RNG = RNG.LCRNG, Type = PIDType.ChainShiny
                };
                return(true);
            }

            pidiv = null;
            return(false);
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        private static bool GetXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
        {
            var xdc = GetSeedsFromPIDEuclid(RNG.XDRNG, top, bot);

            foreach (var seed in xdc)
            {
                var B = RNG.XDRNG.Prev(seed);
                var A = RNG.XDRNG.Prev(B);

                if (!GetIVs(A >> 16, B >> 16).SequenceEqual(IVs))
                {
                    // check for antishiny (once), unroll 2x
                    B = RNG.XDRNG.Prev(A);
                    A = RNG.XDRNG.Prev(B);
                    if (!GetIVs(A >> 16, B >> 16).SequenceEqual(IVs))
                    {
                        continue;
                    }
                }

                pidiv = new PIDIV {
                    OriginSeed = RNG.XDRNG.Prev(A), RNG = RNG.XDRNG, Type = PIDType.CXD
                };
                return(true);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #11
0
        /// <summary>
        /// Checks a <see cref="PIDIV"/> to see if any encounter frames can generate the spread. Requires further filtering against matched Encounter Slots and generation patterns.
        /// </summary>
        /// <param name="pidiv">Matched <see cref="PIDIV"/> containing <see cref="PIDIV.RNG"/> info and <see cref="PIDIV.OriginSeed"/>.</param>
        /// <param name="pk"><see cref="PKM"/> object containing various accessible information required for the encounter.</param>
        /// <returns><see cref="IEnumerable{Frame}"/> to yield possible encounter details for further filtering</returns>
        public static IEnumerable <Frame> GetFrames(PIDIV pidiv, PKM pk)
        {
            if (pidiv.RNG == null)
            {
                return(Enumerable.Empty <Frame>());
            }
            FrameGenerator info = new FrameGenerator(pidiv, pk);

            if (info.FrameType == FrameType.None)
            {
                return(Enumerable.Empty <Frame>());
            }

            info.Nature = pk.EncryptionConstant % 25;

            // gather possible nature determination seeds until a same-nature PID breaks the unrolling
            var seeds = pk.Species == 201 && pk.FRLG // reversed await case
                ? SeedInfo.GetSeedsUntilUnownForm(pidiv, info, pk.AltForm)
                : SeedInfo.GetSeedsUntilNature(pidiv, info);

            var frames = pidiv.Type == PIDType.CuteCharm
                ? FilterCuteCharm(seeds, pidiv, info)
                : FilterNatureSync(seeds, pidiv, info);

            var refined = RefineFrames(frames, info);

            if (pk.Gen4 && pidiv.Type == PIDType.CuteCharm) // only permit cute charm successful frames
            {
                return(refined.Where(z => (z.Lead & ~LeadRequired.UsesLevelCall) == LeadRequired.CuteCharm));
            }
            return(refined);
        }
Beispiel #12
0
        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
                var B = RNG.LCRNG.Advance(seed, 2);

                // Method 1/2/4 can use 3 different RNG frames
                var C   = RNG.LCRNG.Next(B);
                var ivC = C >> 16 & 0x7FFF;
                if (iv1 == ivC)
                {
                    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);
                    }
                }
                else
                {
                    var D   = RNG.LCRNG.Next(C);
                    var ivD = D >> 16 & 0x7FFF;
                    if (iv1 != ivD)
                    {
                        continue;
                    }

                    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;
            return(false);
        }
Beispiel #13
0
        private static bool GetPokewalkerMatch(PKM pk, uint oldpid, out PIDIV pidiv)
        {
            // check surface compatibility
            var mid = oldpid & 0x00FFFF00;

            if (mid != 0 && mid != 0x00FFFF00) // not expected bits
            {
                return(GetNonMatch(out pidiv));
            }
            var nature = oldpid % 25;

            if (nature == 24) // impossible nature
            {
                return(GetNonMatch(out pidiv));
            }

            uint pid = (uint)((pk.TID ^ pk.SID) >> 8 ^ 0xFF) << 24; // the most significant byte of the PID is chosen so the Pokémon can never be shiny.

            // Ensure nature is set to required nature without affecting shininess
            pid += nature - pid % 25;

            // Ensure Gender is set to required gender without affecting other properties
            // If Gender is modified, modify the ability if appropriate
            int currentGender = pk.Gender;

            if (currentGender != 2) // either m/f
            {
                var gr        = pk.PersonalInfo.Gender;
                var pidGender = (pid & 0xFF) < gr ? 1 : 0;
                if (currentGender != pidGender)
                {
                    if (currentGender == 0) // Male
                    {
                        pid += (uint)(((gr - (pid & 0xFF)) / 25 + 1) * 25);
                        if ((nature & 1) != (pid & 1))
                        {
                            pid += 25;
                        }
                    }
                    else
                    {
                        pid -= (uint)((((pid & 0xFF) - gr) / 25 + 1) * 25);
                        if ((nature & 1) != (pid & 1))
                        {
                            pid -= 25;
                        }
                    }
                }
            }
            if (pid != oldpid)
            {
                return(GetNonMatch(out pidiv));
            }
            pidiv = new PIDIV {
                NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.Pokewalker
            };
            return(true);
        }
Beispiel #14
0
        private static bool GetXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
        {
            var xdc = GetSeedsFromPIDEuclid(RNG.XDRNG, top, bot);

            foreach (var seed in xdc)
            {
                var B = RNG.XDRNG.Prev(seed);
                var A = RNG.XDRNG.Prev(B);

                var hi = A >> 16;
                var lo = B >> 16;
                if (!IVsMatch(hi, lo, IVs))
                {
                    // check for antishiny
                    // allow 2 different TSVs to proc antishiny for XD
                    var tsv1 = (int)((hi ^ lo) >> 3);
                    var tsv2 = -1;
                    while (true)
                    {
                        B  = RNG.XDRNG.Prev(A);
                        A  = RNG.XDRNG.Prev(B);
                        hi = A >> 16;
                        lo = B >> 16;
                        if (!IVsMatch(hi, lo, IVs))
                        {
                            var anti = (int)(hi ^ lo) >> 3;
                            if (anti == tsv1)
                            {
                                continue;
                            }
                            if (anti == tsv2)
                            {
                                continue;
                            }
                            if (tsv2 >= 0) // already set
                            {
                                break;     // can't have this many shiny TSVs
                            }
                            tsv2 = anti;
                            continue;
                        }
                        pidiv = new PIDIVTSV
                        {
                            OriginSeed = RNG.XDRNG.Prev(A), RNG = RNG.XDRNG, Type = PIDType.CXDAnti,
                            TSV1       = tsv1, TSV2 = tsv2,
                        };
                        return(true);
                    }
                    continue;
                }

                pidiv = new PIDIV {
                    OriginSeed = RNG.XDRNG.Prev(A), RNG = RNG.XDRNG, Type = PIDType.CXD
                };
                return(true);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #15
0
        private static bool GetXDRNGMatch(PKM pk, uint top, uint bot, uint[] IVs, out PIDIV pidiv)
        {
            var xdc = GetSeedsFromPIDEuclid(RNG.XDRNG, top, bot);

            foreach (var seed in xdc)
            {
                var B = RNG.XDRNG.Prev(seed);
                var A = RNG.XDRNG.Prev(B);

                var hi = A >> 16;
                var lo = B >> 16;
                if (IVsMatch(hi, lo, IVs))
                {
                    pidiv = new PIDIV {
                        OriginSeed = RNG.XDRNG.Prev(A), RNG = RNGType.XDRNG, Type = PIDType.CXD
                    };
                    return(true);
                }

                // check for anti-shiny against player TSV
                var tsv = (uint)(pk.TID ^ pk.SID) >> 3;
                var psv = (top ^ bot) >> 3;
                if (psv == tsv) // already shiny, wouldn't be anti-shiny
                {
                    continue;
                }

                var p2 = seed;
                var p1 = B;
                psv = ((p2 ^ p1) >> 19);
                if (psv != tsv) // prior PID must be shiny
                {
                    continue;
                }

                do
                {
                    B  = RNG.XDRNG.Prev(A);
                    A  = RNG.XDRNG.Prev(B);
                    hi = A >> 16;
                    lo = B >> 16;
                    if (IVsMatch(hi, lo, IVs))
                    {
                        pidiv = new PIDIV {
                            OriginSeed = RNG.XDRNG.Prev(A), RNG = RNGType.XDRNG, Type = PIDType.CXDAnti
                        };
                        return(true);
                    }

                    p2  = RNG.XDRNG.Prev(p1);
                    p1  = RNG.XDRNG.Prev(p2);
                    psv = (p2 ^ p1) >> 19;
                }while (psv == tsv);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #16
0
 // gather possible nature determination seeds until a same-nature PID breaks the unrolling
 private static IEnumerable <SeedInfo> GetSeeds(PIDIV pidiv, FrameGenerator info, PKM pk)
 {
     if (pk.Species == (int)Species.Unown && pk.FRLG) // Gen3 FRLG Unown: reversed await case
     {
         return(SeedInfo.GetSeedsUntilUnownForm(pidiv, info, pk.Form));
     }
     if (pidiv.Type == PIDType.CuteCharm && info.FrameType != FrameType.MethodH) // Gen4: ambiguous seed due to gender-buffered PID
     {
         return(SeedInfo.GetSeedsUntilNature4Cute(pk));
     }
     return(SeedInfo.GetSeedsUntilNature(pidiv, info));
 }
Beispiel #17
0
        private static bool GetChannelMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv, PKM pk)
        {
            var ver = pk.Version;

            if (ver != (int)GameVersion.R && ver != (int)GameVersion.S)
            {
                pidiv = null;
                return(false);
            }

            var undo = top ^ 0x8000;

            if ((undo > 7 ? 0 : 1) != (bot ^ pk.SID ^ 40122))
            {
                top = undo;
            }
            var channel = GetSeedsFromPID(RNG.XDRNG, bot, top);

            foreach (var seed in channel)
            {
                var C = RNG.XDRNG.Advance(seed, 3); // held item
                // no checks, held item can be swapped

                var D = RNG.XDRNG.Next(C); // Version
                if ((D >> 31) + 1 != ver)  // (0-Sapphire, 1-Ruby)
                {
                    continue;
                }

                var E = RNG.XDRNG.Next(D); // OT Gender
                if (E >> 31 != pk.OT_Gender)
                {
                    continue;
                }

                if (!RNG.XDRNG.GetSequentialIVsUInt32(E).SequenceEqual(IVs))
                {
                    continue;
                }

                if (seed >> 16 != pk.SID)
                {
                    continue;
                }

                pidiv = new PIDIV {
                    OriginSeed = RNG.XDRNG.Prev(seed), RNG = RNG.XDRNG, Type = PIDType.Channel
                };
                return(true);
            }
            pidiv = null;
            return(false);
        }
Beispiel #18
0
        public static bool IsAllShadowLockValid(EncounterStaticShadow s, PIDIV pv, PKM pkm)
        {
            var teams = s.Locks;

            if (teams.Length == 0)
            {
                return(s.Version == GameVersion.COLO || !pkm.IsShiny);             // no xd shiny shadow mons
            }
            var tsv = s.Version == GameVersion.XD ? (pkm.TID ^ pkm.SID) >> 3 : -1; // no xd shiny shadow mons

            return(IsAllShadowLockValid(pv, teams, tsv));
        }
Beispiel #19
0
 public static bool IsAllShadowLockValid(PIDIV pv, IEnumerable <TeamLock> teams, int tsv = -1)
 {
     foreach (var t in teams)
     {
         var result = new TeamLockResult(t, pv.OriginSeed, tsv);
         if (result.Valid)
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #20
0
        private static bool GetChainShinyMatch(PKM pk, uint pid, ReadOnlySpan <uint> IVs, out PIDIV pidiv)
        {
            // 13 shiny bits
            // PIDH & 7
            // PIDL & 7
            // IVs
            var bot = GetIVChunk(IVs, 0);
            var top = GetIVChunk(IVs, 3);
            var reg = GetSeedsFromIVs(RNG.LCRNG, top, bot);

            foreach (var seed in reg)
            {
                // check the individual bits
                var s = seed;
                int i = 15;
                do
                {
                    var bit = s >> 16 & 1;
                    if (bit != (pid >> i & 1))
                    {
                        break;
                    }
                    s = RNG.LCRNG.Prev(s);
                }while (--i != 2);
                if (i != 2) // bit failed
                {
                    continue;
                }
                // Shiny Bits of PID validated
                var upper = s;
                if ((upper >> 16 & 7) != (pid >> 16 & 7))
                {
                    continue;
                }
                var lower = RNG.LCRNG.Prev(upper);
                if ((lower >> 16 & 7) != (pid & 7))
                {
                    continue;
                }

                var upid = (((pid & 0xFFFF) ^ pk.TID ^ pk.SID) & 0xFFF8) | ((upper >> 16) & 0x7);
                if (upid != pid >> 16)
                {
                    continue;
                }

                s     = RNG.LCRNG.Reverse(lower, 2); // unroll one final time to get the origin seed
                pidiv = new PIDIV(ChainShiny, s);
                return(true);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #21
0
        public static bool IsAllShadowLockValid(EncounterStaticShadow s, PIDIV pv, PKM pkm)
        {
            var teams = s.Locks;

            if (teams.Length == 0)
            {
                return(true);
            }

            var tsv = s.Version == GameVersion.XD ? pkm.TSV : -1; // no xd shiny shadow mons

            return(IsAllShadowLockValid(pv, teams, tsv));
        }
Beispiel #22
0
        private static bool GetCuteCharmMatch(PKM pk, uint pid, out PIDIV pidiv)
        {
            if (pid > 0xFF)
            {
                return(GetNonMatch(out pidiv));
            }

            GetCuteCharmGenderSpecies(pk, pid, out int genderValue, out int species);
            int getRatio() => PersonalTable.HGSS[species].Gender;

            switch (genderValue)
            {
            case 2: break;     // can't cute charm a genderless pkm

            case 0:            // male
                var gr = getRatio();
                if (254 <= gr) // no modification for PID
                {
                    break;
                }
                var rate   = 25 * ((gr / 25) + 1); // buffered
                var nature = pid % 25;
                if (nature + rate != pid)
                {
                    break;
                }

                pidiv = new PIDIV {
                    NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.CuteCharm
                };
                return(true);

            case 1:     // female
                if (pid >= 25)
                {
                    break;             // nope, this isn't a valid nature
                }
                if (254 <= getRatio()) // no modification for PID
                {
                    break;
                }

                pidiv = new PIDIV {
                    NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.CuteCharm
                };
                return(true);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #23
0
        private static bool GetChannelMatch(uint top, uint bot, ReadOnlySpan <uint> IVs, out PIDIV pidiv, PKM pk)
        {
            var ver = pk.Version;

            if (ver is not((int)GameVersion.R or(int) GameVersion.S))
            {
                return(GetNonMatch(out pidiv));
            }

            var undo = top ^ 0x8000;

            if ((undo > 7 ? 0 : 1) != (bot ^ pk.SID ^ 40122))
            {
                top = undo;
            }
            var channel = GetSeedsFromPIDEuclid(RNG.XDRNG, top, bot);

            foreach (var seed in channel)
            {
                var C = RNG.XDRNG.Advance(seed, 3); // held item
                // no checks, held item can be swapped

                var D = RNG.XDRNG.Next(C); // Version
                if ((D >> 31) + 1 != ver)  // (0-Sapphire, 1-Ruby)
                {
                    continue;
                }

                var E = RNG.XDRNG.Next(D); // OT Gender
                if (E >> 31 != pk.OT_Gender)
                {
                    continue;
                }

                if (!RNG.XDRNG.GetSequentialIVsUInt32(E, IVs))
                {
                    continue;
                }

                if (seed >> 16 != pk.SID)
                {
                    continue;
                }

                pidiv = new PIDIV(Channel, RNG.XDRNG.Prev(seed));
                return(true);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #24
0
        private static bool GetCuteCharmMatch(PKM pk, uint pid, out PIDIV pidiv)
        {
            if (pid > 0xFF)
            {
                return(GetNonMatch(out pidiv));
            }

            int genderValue = pk.Gender;

            switch (genderValue)
            {
            case 2: break;     // can't cute charm a genderless pkm

            case 0:            // male
                var gr = pk.PersonalInfo.Gender;
                if (254 <= gr) // no modification for PID
                {
                    break;
                }
                var rate   = pk.Gender == 1 ? 0 : 25 * (gr / 25 + 1); // buffered
                var nature = pid % 25;
                if (nature + rate != pid)
                {
                    break;
                }

                pidiv = new PIDIV {
                    NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.CuteCharm
                };
                return(true);

            case 1:     // female
                if (pid >= 25)
                {
                    break;                         // nope
                }
                if (254 <= pk.PersonalInfo.Gender) // no modification for PID
                {
                    break;
                }

                pidiv = new PIDIV {
                    NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.CuteCharm
                };
                return(true);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #25
0
        private static bool GetG5MGShinyMatch(PKM pk, uint pid, out PIDIV pidiv)
        {
            var low = pid & 0xFFFF;

            // generation 5 shiny PIDs
            if (low <= 0xFF)
            {
                var av     = (pid >> 16) & 1;
                var genPID = PIDGenerator.GetMG5ShinyPID(low, av, pk.TID, pk.SID);
                if (genPID == pid)
                {
                    pidiv = PIDIV.G5MGShiny;
                    return(true);
                }
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #26
0
        private static bool GetXDRNGMatch(PKM pk, uint top, uint bot, uint[] IVs, out PIDIV pidiv)
        {
            var xdc = GetSeedsFromPIDEuclid(RNG.XDRNG, top, bot);

            foreach (var seed in xdc)
            {
                var B = RNG.XDRNG.Prev(seed);
                var A = RNG.XDRNG.Prev(B);

                var hi = A >> 16;
                var lo = B >> 16;
                if (IVsMatch(hi, lo, IVs))
                {
                    pidiv = new PIDIV {
                        OriginSeed = RNG.XDRNG.Prev(A), RNG = RNGType.XDRNG, Type = PIDType.CXD
                    };
                    return(true);
                }

                // check for anti-shiny against player TSV
                var tsv = (pk.TID ^ pk.SID) >> 3;
                var psv = (int)((hi ^ lo) >> 3);
                if (psv != tsv)
                {
                    continue;
                }

                do
                {
                    B   = RNG.XDRNG.Prev(A);
                    A   = RNG.XDRNG.Prev(B);
                    hi  = A >> 16;
                    lo  = B >> 16;
                    psv = (int)((hi ^ lo) >> 3);
                }while (psv == tsv);

                if (IVsMatch(hi, lo, IVs))
                {
                    pidiv = new PIDIV {
                        OriginSeed = RNG.XDRNG.Prev(A), RNG = RNGType.XDRNG, Type = PIDType.CXDAnti
                    };
                    return(true);
                }
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #27
0
        private static bool GetCuteCharmMatch(PKM pk, uint pid, out PIDIV pidiv)
        {
            if (pid > 0xFF)
            {
                return(GetNonMatch(out pidiv));
            }

            (int species, int genderValue) = GetCuteCharmGenderSpecies(pk, pid, pk.Species);
            int getRatio() => PersonalTable.HGSS[species].Gender;

            switch (genderValue)
            {
            case 2: break;                               // can't cute charm a genderless pkm

            case 0:                                      // male
                var gr = getRatio();
                if (gr >= PersonalInfo.RatioMagicFemale) // no modification for PID
                {
                    break;
                }
                var rate   = 25 * ((gr / 25) + 1); // buffered
                var nature = pid % 25;
                if (nature + rate != pid)
                {
                    break;
                }

                pidiv = PIDIV.CuteCharm;
                return(true);

            case 1:     // female
                if (pid >= 25)
                {
                    break;                                       // nope, this isn't a valid nature
                }
                if (getRatio() >= PersonalInfo.RatioMagicFemale) // no modification for PID
                {
                    break;
                }

                pidiv = PIDIV.CuteCharm;
                return(true);
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #28
0
        private static bool GetG5MGShinyMatch(PKM pk, uint pid, out PIDIV pidiv)
        {
            var low = pid & 0xFFFF;

            // generation 5 shiny PIDs
            if (low <= 0xFF)
            {
                var high = pid >> 16;
                if (((pk.TID ^ pk.SID ^ low) - high & 0xFFFE) == 0)
                {
                    pidiv = new PIDIV {
                        NoSeed = true, Type = PIDType.G5MGShiny
                    };
                    return(true);
                }
            }
            return(GetNonMatch(out pidiv));
        }
Beispiel #29
0
        /// <summary>
        /// Checks a <see cref="PIDIV"/> to see if any encounter frames can generate the spread. Requires further filtering against matched Encounter Slots and generation patterns.
        /// </summary>
        /// <param name="pidiv">Matched <see cref="PIDIV"/> containing info and <see cref="PIDIV.OriginSeed"/>.</param>
        /// <param name="pk"><see cref="PKM"/> object containing various accessible information required for the encounter.</param>
        /// <returns><see cref="IEnumerable{Frame}"/> to yield possible encounter details for further filtering</returns>
        public static IEnumerable <Frame> GetFrames(PIDIV pidiv, PKM pk)
        {
            if (pk.Version == (int)GameVersion.CXD)
            {
                return(Array.Empty <Frame>());
            }

            var info = new FrameGenerator(pk)
            {
                Nature = pk.EncryptionConstant % 25
            };
            var seeds  = GetSeeds(pidiv, info, pk);
            var frames = pidiv.Type == PIDType.CuteCharm
                ? FilterCuteCharm(seeds, info)
                : FilterNatureSync(seeds, info);

            return(GetRefinedSeeds(frames, info, pidiv));
        }
Beispiel #30
0
        private static bool GetPokewalkerMatch(PKM pk, uint oldpid, out PIDIV pidiv)
        {
            var nature = oldpid % 25;

            if (nature == 24)
            {
                pidiv = null;
                return(false);
            }

            uint pid = (uint)((pk.TID ^ pk.SID) >> 8 ^ 0xFF) << 24; // the most significant byte of the PID is chosen so the Pokémon can never be shiny.

            pid += nature - pid % 25;
            uint gv = 0;

            switch (pk.Gender)
            {
            case 0:                                               // Male
                var gr = pk.PersonalInfo.Gender + 1;
                gv = (uint)(((gr - (pid & 0xFF)) / 25 + 1) * 25); // Ensures gender is set to male without affecting nature.
                break;

            case 1:                                                // Female
                var gr2 = pk.PersonalInfo.Gender;
                gv = (uint)((((pid & 0xFF) - gr2) / 25 + 1) * 25); // Ensures gender is set to female without affecting nature
                break;
            }
            pid += gv;
            if ((nature & 1) != (pid & 1)) // If ability does not match the chosen ability
            {
                pid -= 25;                 // Switches ability without affecting nature
            }
            if (pid == oldpid)
            {
                pidiv = new PIDIV {
                    NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.Pokewalker
                };
                return(true);
            }

            pidiv = null;
            return(false);
        }