示例#1
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 = PIDIV.Pokewalker;
        return(true);
    }
        /// <summary>
        /// Gets the Search Criteria parameters necessary for generating <see cref="SeedInfo"/> and <see cref="Frame"/> objects.
        /// </summary>
        /// <param name="pidiv">Info used to determine the <see cref="FrameType"/>.</param>
        /// <param name="pk"><see cref="PKM"/> object containing various accessible information required for the encounter.</param>
        /// <returns>Object containing search criteria to be passed by reference to search/filter methods.</returns>
        public FrameGenerator(PIDIV pidiv, PKM pk)
        {
            var ver = (GameVersion)pk.Version;

            switch (ver)
            {
            // Method H
            case GameVersion.R:
            case GameVersion.S:
            case GameVersion.FR:
            case GameVersion.LG:
            case GameVersion.E:
                DPPt      = false;
                FrameType = FrameType.MethodH;
                RNG       = pidiv.RNG;
                Safari3   = pk.Ball == 5 && !pk.FRLG;

                if (ver != GameVersion.E)
                {
                    return;
                }

                AllowLeads = true;

                // Cute Charm waits for gender too!
                var  gender   = pk.Gender;
                bool gendered = gender != 2;
                if (!gendered)
                {
                    return;
                }

                var gr = pk.PersonalInfo.Gender;
                Gendered   = true;
                GenderLow  = GetGenderMinMax(gender, gr, false);
                GenderHigh = GetGenderMinMax(gender, gr, true);
                return;

            // Method J
            case GameVersion.D:
            case GameVersion.P:
            case GameVersion.Pt:
                DPPt       = true;
                AllowLeads = true;
                FrameType  = FrameType.MethodJ;
                RNG        = pidiv.RNG;
                return;

            // Method K
            case GameVersion.HG:
            case GameVersion.SS:
                DPPt       = false;
                AllowLeads = true;
                FrameType  = FrameType.MethodK;
                RNG        = pidiv.RNG;
                return;
            }
        }
示例#3
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));
 }
示例#4
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);
 }
示例#5
0
    private static bool GetXDRNGMatch(PKM pk, uint top, uint bot, ReadOnlySpan <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(CXD, RNG.XDRNG.Prev(A));
                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(CXDAnti, RNG.XDRNG.Prev(A));
                    return(true);
                }

                p2  = RNG.XDRNG.Prev(p1);
                p1  = RNG.XDRNG.Prev(p2);
                psv = (p2 ^ p1) >> 19;
            }while (psv == tsv);
        }
        return(GetNonMatch(out pidiv));
    }
示例#6
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));
    }
示例#7
0
 /// <summary>
 /// Checks if the PIDIV can originate from
 /// </summary>
 /// <param name="possibleTeams"></param>
 /// <param name="info"></param>
 /// <returns></returns>
 private static bool GetCanOriginateFrom(TeamLock[] possibleTeams, PIDIV info, bool XD, out uint origin)
 {
     foreach (var team in possibleTeams)
     {
         var result = LockFinder.FindLockSeed(info.OriginSeed, team.Locks, XD, out origin);
         if (result)
         {
             return(true);
         }
     }
     origin = 0;
     return(false);
 }
示例#8
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));
    }
示例#9
0
    public static bool IsAllShadowLockValid(EncounterStaticShadow s, PIDIV pv, PKM pk)
    {
        if (s.Version == GameVersion.XD && pk.IsShiny)
        {
            return(false); // no xd shiny shadow mons
        }
        var teams = s.Locks;

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

        var tsv = s.Version == GameVersion.XD ? (pk.TID ^ pk.SID) >> 3 : -1; // no xd shiny shadow mons

        return(IsAllShadowLockValid(pv, teams, tsv));
    }
示例#10
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));
    }
示例#11
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 pk

        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));
    }
示例#12
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));
    }
示例#13
0
    private static bool GetMG4Match(uint pid, ReadOnlySpan <uint> IVs, out PIDIV pidiv)
    {
        uint mg4Rev = RNG.ARNG.Prev(pid);
        var  mg4    = GetSeedsFromPID(RNG.LCRNG, mg4Rev >> 16, mg4Rev & 0xFFFF);

        foreach (var seed in mg4)
        {
            var B = RNG.LCRNG.Advance(seed, 2);
            var C = RNG.LCRNG.Next(B);
            var D = RNG.LCRNG.Next(C);
            if (!IVsMatch(C >> 16, D >> 16, IVs))
            {
                continue;
            }

            pidiv = new PIDIV(G4MGAntiShiny, seed);
            return(true);
        }
        return(GetNonMatch(out pidiv));
    }
示例#14
0
    private static bool GetLCRNGRoamerMatch(uint top, uint bot, ReadOnlySpan <uint> IVs, out PIDIV pidiv)
    {
        if (IVs[2] != 0 || IVs[3] != 0 || IVs[4] != 0 || IVs[5] != 0 || IVs[1] > 7)
        {
            return(GetNonMatch(out pidiv));
        }
        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(Method_1_Roamer, seed);
            return(true);
        }
        return(GetNonMatch(out pidiv));
    }
示例#15
0
    private static bool GetColoStarterMatch(PKM pk, uint top, uint bot, ReadOnlySpan <uint> IVs, out PIDIV pidiv)
    {
        if (pk.Version != (int)GameVersion.CXD || pk.Species is not((int)Species.Espeon or(int) Species.Umbreon))
        {
            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(CXD_ColoStarter, origin);
            return(true);
        }
        return(GetNonMatch(out pidiv));
    }
示例#16
0
 /// <summary>
 /// Checks if the PIDIV can originate from
 /// </summary>
 private static bool GetCanOriginateFrom(TeamLock[] possibleTeams, PIDIV info)
 {
     return(LockFinder.IsAllShadowLockValid(info, possibleTeams));
 }
示例#17
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);
    }
示例#18
0
 private static bool GetModified8BitMatch(PKM pk, uint pid, out PIDIV pidiv)
 {
     return(pk.Gen4
         ? (pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv)) || GetG5MGShinyMatch(pk, pid, out pidiv)
         : GetG5MGShinyMatch(pk, pid, out pidiv) || (pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv)));
 }
示例#19
0
    private static bool GetModifiedPIDMatch(PKM pk, uint pid, ReadOnlySpan <uint> IVs, out PIDIV pidiv)
    {
        if (pk.IsShiny)
        {
            if (GetChainShinyMatch(pk, pid, IVs, out pidiv))
            {
                return(true);
            }
            if (GetModified8BitMatch(pk, pid, out pidiv))
            {
                return(true);
            }
        }
        else
        {
            if (pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv))
            {
                return(true);
            }
        }

        return(GetPokewalkerMatch(pk, pid, out pidiv));
    }
示例#20
0
 private static bool GetNonMatch(out PIDIV pidiv)
 {
     pidiv = PIDIV.None;
     return(false);
 }
示例#21
0
    private static bool GetLCRNGMatch(uint top, uint bot, ReadOnlySpan <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(Method_1, seed);
                    return(true);
                }

                var E   = RNG.LCRNG.Next(D);
                var ivE = E >> 16 & 0x7FFF;
                if (iv2 == ivE) // ABCE
                {
                    pidiv = new PIDIV(Method_4, seed);
                    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(Method_2, seed);
                    return(true);
                }
            }
        }
        reg = GetSeedsFromPIDSkip(RNG.LCRNG, top, bot);
        foreach (var seed in reg)
        {
            // A and B are already used by PID
            var C = RNG.LCRNG.Advance(seed, 3);

            // Method 3
            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)
            {
                continue;
            }
            pidiv = new PIDIV(Method_3, seed);
            return(true);
        }
        return(GetNonMatch(out pidiv));
    }
示例#22
0
    private static bool GetBACDMatch(PKM pk, uint pid, ReadOnlySpan <uint> IVs, out PIDIV pidiv)
    {
        var     bot  = GetIVChunk(IVs, 0);
        var     top  = GetIVChunk(IVs, 3);
        var     reg  = GetSeedsFromIVs(RNG.LCRNG, top, bot);
        PIDType type = BACD_U;

        foreach (var seed in reg)
        {
            var B   = seed;
            var A   = RNG.LCRNG.Prev(B);
            var low = B >> 16;

            var PID = (A & 0xFFFF0000) | low;
            if (PID != pid)
            {
                uint idxor   = (uint)(pk.TID ^ pk.SID);
                bool isShiny = (idxor ^ PID >> 16 ^ (PID & 0xFFFF)) < 8;
                if (!isShiny)
                {
                    if (!pk.IsShiny) // check for nyx antishiny
                    {
                        if (!IsBACD_U_AX(idxor, pid, low, A, ref type))
                        {
                            continue;
                        }
                    }
                    else // check for force shiny pk
                    {
                        if (!IsBACD_U_S(idxor, pid, low, ref A, ref type))
                        {
                            continue;
                        }
                    }
                }
                else if (!IsBACD_U_AX(idxor, pid, low, A, ref type))
                {
                    if ((PID + 8 & 0xFFFFFFF8) != pid)
                    {
                        continue;
                    }
                    type = BACD_U_A;
                }
            }
            var s = RNG.LCRNG.Prev(A);

            // Check for prior Restricted seed
            var sn = s;
            for (int i = 0; i < 3; i++, sn = RNG.LCRNG.Prev(sn))
            {
                if ((sn & 0xFFFF0000) != 0)
                {
                    continue;
                }
                // shift from unrestricted enum val to restricted enum val
                pidiv = new PIDIV(--type, sn);
                return(true);
            }
            // no restricted seed found, thus unrestricted
            pidiv = new PIDIV(type, s);
            return(true);
        }
        return(GetNonMatch(out pidiv));
    }
示例#23
0
    private static bool GetLCRNGUnownMatch(uint top, uint bot, ReadOnlySpan <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(Method_1_Unown, seed);
                    return(true);
                }

                var E   = RNG.LCRNG.Next(D);
                var ivE = E >> 16 & 0x7FFF;
                if (iv2 == ivE) // BACE
                {
                    pidiv = new PIDIV(Method_4_Unown, seed);
                    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(Method_2_Unown, seed);
                    return(true);
                }
            }
        }
        reg = GetSeedsFromPIDSkip(RNG.LCRNG, bot, top); // reversed!
        foreach (var seed in reg)
        {
            // A and B are already used by PID
            var C = RNG.LCRNG.Advance(seed, 3);

            // Method 3
            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)
            {
                continue;
            }
            pidiv = new PIDIV(Method_3_Unown, seed);
            return(true);
        }
        return(GetNonMatch(out pidiv));
    }