Example #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));
            }
        }
Example #2
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);
        }
        /// <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);
            }
        }
Example #4
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));
            }
        }
Example #5
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));
 }
        private static IEnumerable <Frame> RefineFrames3(IEnumerable <Frame> frames, FrameGenerator info)
        {
            var list = new List <Frame>();

            foreach (var f in frames)
            {
                // Current Seed of the frame is the Level Calc
                var prev = info.RNG.Prev(f.Seed); // ESV
                var rand = prev >> 16;
                {
                    f.ESV = rand;
                    yield return(f);
                }

                if (f.Lead != LeadRequired.None || !info.AllowLeads) // Emerald
                {
                    continue;
                }

                // Generate frames for other slots after the regular slots
                list.Add(f);
            }
            foreach (var f in list)
            {
                // Level Modifiers between ESV and Nature
                var prev = info.RNG.Prev(f.Seed); // Level
                prev = info.RNG.Prev(prev);       // Level Proc
                var p16 = prev >> 16;

                yield return(info.GetFrame(prev, LeadRequired.Intimidate, p16));

                yield return(info.GetFrame(prev, LeadRequired.VitalSpirit, p16));

                // Slot Modifiers before ESV
                var force = (info.DPPt ? p16 >> 15 : p16 & 1) == 1;
                if (!force)
                {
                    continue;
                }

                var rand = f.Seed >> 16;
                yield return(info.GetFrame(prev, LeadRequired.Static, rand));

                yield return(info.GetFrame(prev, LeadRequired.MagnetPull, rand));
            }
        }
Example #7
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));
        }
Example #8
0
        private static IEnumerable <Frame> RefineFrames3(IEnumerable <Frame> frames, FrameGenerator info)
        {
            // ESV
            // Level
            // Nature
            // Current Seed of the frame is the Level Calc (frame before nature)
            var list = new List <Frame>();

            foreach (var f in frames)
            {
                bool noLead = !info.AllowLeads && f.Lead != LeadRequired.None;
                if (noLead)
                {
                    continue;
                }

                var prev = info.RNG.Prev(f.Seed); // ESV
                var rand = prev >> 16;
                f.RandESV    = rand;
                f.RandLevel  = f.Seed >> 16;
                f.OriginSeed = info.RNG.Prev(prev);
                if (f.Lead != LeadRequired.CuteCharm) // needs proc checking
                {
                    yield return(f);
                }

                // Generate frames for other slots after the regular slots
                if (info.AllowLeads && (f.Lead == LeadRequired.CuteCharm || f.Lead == LeadRequired.None))
                {
                    list.Add(f);
                }
            }
            foreach (var f in list)
            {
                var leadframes = GenerateLeadSpecificFrames3(f, info);
                foreach (var frame in leadframes)
                {
                    yield return(frame);
                }
            }
        }
Example #9
0
        public static IEnumerable <SeedInfo> getSeedsUntilNature(PIDIV pidiv, FrameGenerator info)
        {
            bool reverse = pidiv.Type.IsReversedPID();
            bool charm3  = false;

            var seed = pidiv.OriginSeed;

            yield return(new SeedInfo {
                Seed = seed
            });

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

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

                var pid = reverse ? a << 16 | b : b << 16 | a;

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

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

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

                yield return(new SeedInfo {
                    Seed = s1, Charm3 = charm3
                });
            }
        }
Example #10
0
        private static IEnumerable <Frame> RefineFrames4(IEnumerable <Frame> frames, FrameGenerator info)
        {
            var list = new List <Frame>();

            foreach (var f in frames)
            {
                // Current Seed of the frame is the ESV.
                var rand = f.Seed >> 16;
                f.RandESV    = rand;
                f.RandLevel  = rand; // unused
                f.OriginSeed = info.RNG.Prev(f.Seed);
                yield return(f);

                // Create a copy for level; shift ESV and origin back
                var esv       = f.OriginSeed >> 16;
                var origin    = info.RNG.Prev(f.OriginSeed);
                var withLevel = info.GetFrame(f.Seed, f.Lead | LeadRequired.UsesLevelCall, esv, f.RandLevel, origin);
                yield return(withLevel);

                if (f.Lead != LeadRequired.None)
                {
                    continue;
                }

                // Generate frames for other slots after the regular slots
                list.Add(f);
            }
            foreach (var f in list)
            {
                var leadframes = GenerateLeadSpecificFrames4(f, info);
                foreach (var frame in leadframes)
                {
                    yield return(frame);
                }
            }
        }
Example #11
0
        private static LockInfo VerifyPIDCriteria(uint pid, FrameGenerator info)
        {
            // Nature locks are always a given
            var nval = pid % 25;

            if (nval != info.Nature)
            {
                return(LockInfo.Nature);
            }

            if (!info.Gendered)
            {
                return(LockInfo.Pass);
            }

            var gender = pid & 0xFF;

            if (info.GenderLow > gender || gender > info.GenderHigh)
            {
                return(LockInfo.Gender);
            }

            return(LockInfo.Pass);
        }
Example #12
0
        private static IEnumerable <Frame> GetRefinedSeeds(IEnumerable <Frame> frames, FrameGenerator info, PIDIV pidiv)
        {
            var refined = RefineFrames(frames, info);

            if (pidiv.Type == PIDType.CuteCharm && info.FrameType != FrameType.MethodH) // only permit cute charm successful frames
            {
                return(refined.Where(z => (z.Lead & ~LeadRequired.UsesLevelCall) == LeadRequired.CuteCharm));
            }
            return(refined);
        }
Example #13
0
        private static IEnumerable <Frame> GenerateLeadSpecificFrames3(Frame f, FrameGenerator info)
        {
            // Check leads -- none in list if leads are not allowed
            // Certain leads inject a RNG call
            // 3 different rand places
            LeadRequired lead;
            var          prev0 = f.Seed;                // 0
            var          prev1 = info.RNG.Prev(f.Seed); // -1
            var          prev2 = info.RNG.Prev(prev1);  // -2
            var          prev3 = info.RNG.Prev(prev2);  // -3

            // Rand call raw values
            var p0 = prev0 >> 16;
            var p1 = prev1 >> 16;
            var p2 = prev2 >> 16;

            // Cute Charm
            // -2 ESV
            // -1 Level
            //  0 CC Proc (Random() % 3 != 0)
            //  1 Nature
            if (info.Gendered)
            {
                bool cc = p0 % 3 != 0;
                if (f.Lead == LeadRequired.CuteCharm) // 100% required for frame base
                {
                    if (cc)
                    {
                        yield return(info.GetFrame(prev2, LeadRequired.CuteCharm, p2, p1, prev3));
                    }
                    yield break;
                }
                lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail;
                yield return(info.GetFrame(prev2, lead, p2, p1, prev3));
            }
            if (f.Lead == LeadRequired.CuteCharm)
            {
                yield break;
            }

            // Pressure, Hustle, Vital Spirit = Force Maximum Level from slot
            // -2 ESV
            // -1 Level
            //  0 LevelMax proc (Random() & 1)
            //  1 Nature
            bool max = p0 % 2 == 1;

            lead = max ? LeadRequired.PressureHustleSpirit : LeadRequired.PressureHustleSpiritFail;
            yield return(info.GetFrame(prev2, lead, p2, p1, prev3));

            // Keen Eye, Intimidate (Not compatible with Sweet Scent)
            // -2 ESV
            // -1 Level
            //  0 Level Adequate Check !(Random() % 2 == 1) rejects --  rand%2==1 is adequate
            //  1 Nature
            // Note: if this check fails, the encounter generation routine is aborted.
            if (max) // same result as above, no need to recalculate
            {
                lead = LeadRequired.IntimidateKeenEye;
                yield return(info.GetFrame(prev2, lead, p2, p1, prev3));
            }

            // Static or Magnet Pull
            // -2 SlotProc (Random % 2 == 0)
            // -1 ESV (select slot)
            //  0 Level
            //  1 Nature
            bool force = p2 % 2 == 0;

            if (force)
            {
                // Since a failed proc is indistinguishable from the default frame calls, only generate if it succeeds.
                lead = LeadRequired.StaticMagnet;
                yield return(info.GetFrame(prev2, lead, p1, p0, prev3));
            }
        }
Example #14
0
 private static IEnumerable <Frame> RefineFrames(IEnumerable <Frame> frames, FrameGenerator info)
 {
     return(info.FrameType == FrameType.MethodH
         ? RefineFrames3(frames, info)
         : RefineFrames4(frames, info));
 }
Example #15
0
        /// <summary>
        /// Filters the input <see cref="SeedInfo"/> according to a Cute Charm frame generation pattern.
        /// </summary>
        /// <param name="seeds">Seed Information for the frame</param>
        /// <param name="pidiv">PIDIV Info for the frame</param>
        /// <param name="info">Search Info for the frame</param>
        /// <returns>Possible matches to the Cute Charm frame generation pattern</returns>
        private static IEnumerable <Frame> FilterCuteCharm(IEnumerable <SeedInfo> seeds, PIDIV pidiv, FrameGenerator info)
        {
            foreach (var seed in seeds)
            {
                var s = seed.Seed;

                var rand   = s >> 16;
                var nature = info.DPPt ? rand / 0xA3E : rand % 25;
                if (nature != info.Nature)
                {
                    continue;
                }

                var  prev      = pidiv.RNG.Prev(s);
                var  proc      = prev >> 16;
                bool charmProc = (info.DPPt ? proc / 0x5556 : proc % 3) == 0;
                if (!charmProc)
                {
                    continue;
                }

                yield return(info.GetFrame(prev, LeadRequired.CuteCharm));
            }
        }
Example #16
0
        /// <summary>
        /// Filters the input <see cref="SeedInfo"/> according to a Nature Lock frame generation pattern.
        /// </summary>
        /// <param name="seeds">Seed Information for the frame</param>
        /// <param name="pidiv">PIDIV Info for the frame</param>
        /// <param name="info">Search Info for the frame</param>
        /// <returns>Possible matches to the Nature Lock frame generation pattern</returns>
        private static IEnumerable <Frame> FilterNatureSync(IEnumerable <SeedInfo> seeds, PIDIV pidiv, FrameGenerator info)
        {
            foreach (var seed in seeds)
            {
                var  s    = seed.Seed;
                var  rand = s >> 16;
                bool sync = info.AllowLeads && !seed.Charm3 && (info.DPPt ? rand >> 15 : rand & 1) == 0;
                bool reg  = (info.DPPt ? rand / 0xA3E : rand % 25) == info.Nature;
                if (!sync && !reg) // doesn't generate nature frame
                {
                    continue;
                }

                uint prev = pidiv.RNG.Prev(s);
                if (info.AllowLeads && reg) // check for failed sync
                {
                    var failsync = (info.DPPt ? prev >> 31 : (prev >> 16) & 1) != 1;
                    if (failsync)
                    {
                        yield return(info.GetFrame(pidiv.RNG.Prev(prev), LeadRequired.SynchronizeFail));
                    }
                }
                if (sync)
                {
                    yield return(info.GetFrame(prev, LeadRequired.Synchronize));
                }
                if (reg)
                {
                    if (seed.Charm3)
                    {
                        yield return(info.GetFrame(prev, LeadRequired.CuteCharm));
                    }
                    else
                    {
                        yield return(info.GetFrame(prev, LeadRequired.None));
                    }
                }
            }
        }
Example #17
0
        private static IEnumerable <Frame> GenerateLeadSpecificFrames4(Frame f, FrameGenerator info)
        {
            LeadRequired lead;
            var          prev0 = f.Seed;                // 0
            var          prev1 = info.RNG.Prev(f.Seed); // -1
            var          prev2 = info.RNG.Prev(prev1);  // -2
            var          prev3 = info.RNG.Prev(prev2);  // -3

            // Rand call raw values
            var p0 = prev0 >> 16;
            var p1 = prev1 >> 16;
            var p2 = prev2 >> 16;

            // Cute Charm
            // -2 ESV
            // -1 Level (Optional)
            //  0 CC Proc (Random() % 3 != 0)
            //  1 Nature
            if (info.Gendered)
            {
                bool cc = (info.DPPt ? p0 / 0x5556 : p0 % 3) != 0;
                if (f.Lead == LeadRequired.CuteCharm) // 100% required for frame base
                {
                    if (!cc)
                    {
                        yield break;
                    }
                    yield return(info.GetFrame(prev2, LeadRequired.CuteCharm, p1, p1, prev2));

                    yield return(info.GetFrame(prev2, LeadRequired.CuteCharm | LeadRequired.UsesLevelCall, p2, p1, prev3));

                    yield break;
                }
                lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail;
                yield return(info.GetFrame(prev2, lead, p1, p1, prev2));

                yield return(info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3));
            }
            if (f.Lead == LeadRequired.CuteCharm)
            {
                yield break;
            }

            // Pressure, Hustle, Vital Spirit = Force Maximum Level from slot
            // -2 ESV
            // -1 Level (Optional)
            //  0 LevelMax proc (Random() & 1)
            //  1 Nature
            bool max = (info.DPPt ? p0 >> 15 : p0 & 1) == 1;

            lead = max ? LeadRequired.PressureHustleSpirit : LeadRequired.PressureHustleSpiritFail;
            yield return(info.GetFrame(prev2, lead, p1, p1, prev2));

            yield return(info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3));

            // Keen Eye, Intimidate (Not compatible with Sweet Scent)
            // -2 ESV
            // -1 Level (Optional)
            //  0 Level Adequate Check !(Random() % 2 == 1) rejects --  rand%2==1 is adequate
            //  1 Nature
            // Note: if this check fails, the encounter generation routine is aborted.
            if (max) // same result as above, no need to recalculate
            {
                lead = LeadRequired.IntimidateKeenEye;
                yield return(info.GetFrame(prev2, lead, p1, p1, prev2));

                yield return(info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3));
            }

            // Static or Magnet Pull
            // -2 SlotProc (Random % 2 == 0)
            // -1 ESV (select slot)
            //  0 Level (Optional)
            //  1 Nature
            var force1 = (info.DPPt ? p1 >> 15 : p1 & 1) == 1;

            lead = force1 ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail;
            yield return(info.GetFrame(prev2, lead, p0, p0, prev3));

            var force2 = (info.DPPt ? p2 >> 15 : p2 & 1) == 1;

            lead = (force2 ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail) | LeadRequired.UsesLevelCall;
            yield return(info.GetFrame(prev2, lead, p1, p0, prev3));
        }
Example #18
0
        /// <summary>
        /// Filters the input <see cref="SeedInfo"/> according to a Nature Lock frame generation pattern.
        /// </summary>
        /// <param name="seeds">Seed Information for the frame</param>
        /// <param name="pidiv">PIDIV Info for the frame</param>
        /// <param name="info">Search Info for the frame</param>
        /// <returns>Possible matches to the Nature Lock frame generation pattern</returns>
        private static IEnumerable <Frame> FilterNatureSync(IEnumerable <SeedInfo> seeds, PIDIV pidiv, FrameGenerator info)
        {
            foreach (var seed in seeds)
            {
                var s = seed.Seed;

                if (info.Safari3)
                {
                    // successful pokeblock activation
                    bool result = IsValidPokeBlockNature(s, info.Nature, out uint blockSeed);
                    if (result)
                    {
                        yield return(info.GetFrame(blockSeed, seed.Charm3 ? LeadRequired.CuteCharm : LeadRequired.None));
                    }

                    // if no pokeblocks present (or failed call), fall out of the safari specific code and generate via the other scenarios
                }

                var  rand = s >> 16;
                bool sync = info.AllowLeads && !seed.Charm3 && (info.DPPt ? rand >> 15 : rand & 1) == 0;
                bool reg  = (info.DPPt ? rand / 0xA3E : rand % 25) == info.Nature;
                if (!sync && !reg) // doesn't generate nature frame
                {
                    continue;
                }

                uint prev = pidiv.RNG.Prev(s);
                if (info.AllowLeads && reg) // check for failed sync
                {
                    var failsync = (info.DPPt ? prev >> 31 : (prev >> 16) & 1) != 1;
                    if (failsync)
                    {
                        yield return(info.GetFrame(pidiv.RNG.Prev(prev), LeadRequired.SynchronizeFail));
                    }
                }
                if (sync)
                {
                    yield return(info.GetFrame(prev, LeadRequired.Synchronize));
                }
                if (reg)
                {
                    if (seed.Charm3)
                    {
                        yield return(info.GetFrame(prev, LeadRequired.CuteCharm));
                    }
                    else
                    {
                        if (info.Safari3)
                        {
                            prev = pidiv.RNG.Prev(prev); // wasted RNG call
                        }
                        yield return(info.GetFrame(prev, LeadRequired.None));
                    }
                }
            }
        }