示例#1
0
        /// <summary>
        /// Generates <see cref="SeedFrame"/> nodes until the traversal is ended by an interrupt frame that matches the <see cref="prior"/>.
        /// </summary>
        /// <param name="ctr">Starting frame for the traversal.</param>
        /// <param name="current">Current lock criteria to satisfy. Used to find valid <see cref="SeedFrame"/> results to yield.</param>
        /// <param name="prior">Prior lock criteria. Used for determining when the traversal stops.</param>
        /// <returns>List of possible locks for the provided input.</returns>
        /// <remarks>
        /// An "interrupt" signals the end of the traversal.
        /// Any <see cref="SeedFrame"/> afterwards (when generated forward from the CPU Trainer) will use the interrupt rather than the previous <see cref="SeedFrame"/> that was found for the <see cref="prior"/> lock.
        /// </remarks>
        private IEnumerable <SeedFrame> GetAllLocks(int ctr, NPCLock current, NPCLock prior)
        {
            // Since the prior(next) lock is generated 7+2*n frames after, the worst case break is 7 frames after the PID.
            // Continue reversing until a sequential generation case is found.
            int start = ctr;

            // Track if we ever require the CPU Trainer Shiny Value to be a value for a shiny skip.
            // We need to un-set this flag if future frames don't pan out.
            bool forcedOT = false;

            while (true)
            {
                int p7 = ctr - 7;

                if (p7 > start)
                {
                    // check for interrupting cpu team cases
                    var  upper = Cache[p7 + 1];
                    var  lower = Cache[p7];
                    uint cid   = upper << 16 | lower;
                    var  sv    = (upper ^ lower) >> 3;
                    if (current.Shadow && sv == TSV) // shiny shadow mon, only ever true for XD.
                    {
                        // This interrupt is ignored! The result is shiny.
                    }
                    else if (prior.MatchesLock(cid)) // lock matched cpu mon
                    {
                        if (RCSV != NOT_FORCED)      // CPU shiny value is required for a previous lock
                        {
                            if (sv != RCSV)
                            {
                                if (forcedOT) // current call to this method had forced the OT; clear the forced OT before breaking.
                                {
                                    RCSV = NOT_FORCED;
                                }
                                yield break; // Since we can't skip this interrupt, we're done.
                            }
                        }
                        else // No CPU shiny value forced yet. Lets try to skip this lock by requiring the eventual OT to get this shiny.
                        {
                            RCSV     = (int)sv;
                            forcedOT = true;
                            // don't break
                        }
                    }
                }
                uint pid = Cache[ctr + 1] << 16 | Cache[ctr];
                if (current.MatchesLock(pid))
                {
                    yield return new SeedFrame {
                               FrameID = ctr + (current.Seen ? 5 : 7), PID = pid
                    }
                }
                ;

                ctr += 2;
            }
        }
示例#2
0
        /// <summary>
        /// Returns a single <see cref="SeedFrame"/> as the <see cref="current"/> lock must match precisely.
        /// </summary>
        /// <param name="ctr">Starting frame for the traversal.</param>
        /// <param name="current">Current lock criteria to satisfy. Used to find valid <see cref="SeedFrame"/> results to yield.</param>
        /// <returns></returns>
        private IEnumerable <SeedFrame> GetSingleLock(int ctr, NPCLock current)
        {
            uint pid = Cache[ctr + 1] << 16 | Cache[ctr];

            if (current.MatchesLock(pid))
            {
                yield return(new SeedFrame(pid, ctr + (current.Seen ? 5 : 7)));
            }
        }
示例#3
0
        /// <summary>
        /// Generates a list of frames the <see cref="current"/> lock data can be generated at.
        /// </summary>
        /// <param name="ctr">Starting frame for the traversal.</param>
        /// <param name="current">Current lock criteria to satisfy. Used to find valid <see cref="SeedFrame"/> results to yield.</param>
        /// <param name="prior">Prior lock criteria. Used for determining when the traversal stops.</param>
        /// <returns>List of possible locks for the provided input.</returns>
        private IEnumerable <SeedFrame> GetPossibleLocks(int ctr, NPCLock current, NPCLock?prior)
        {
            if (prior?.Shadow != false)
            {
                return(GetSingleLock(ctr, current));
            }

            return(GetAllLocks(ctr, current, prior));
        }
示例#4
0
        /// <summary>
        /// Returns a single <see cref="SeedFrame"/> as the <see cref="current"/> lock must match precisely.
        /// </summary>
        /// <param name="ctr">Starting frame for the traversal.</param>
        /// <param name="current">Current lock criteria to satisfy. Used to find valid <see cref="SeedFrame"/> results to yield.</param>
        /// <returns></returns>
        private IEnumerable <SeedFrame> GetSingleLock(int ctr, NPCLock current)
        {
            uint pid = Cache[ctr + 1] << 16 | Cache[ctr];

            if (current.MatchesLock(pid))
            {
                yield return(new SeedFrame(pid, ctr + (current.Seen ? 5 : 7)));
            }
            else
            {
                yield break;
            }

            // Reaching here means the single lock didn't cut it. Maybe the frame before it was an anti-shiny reroll?

            // Track if we ever require the CPU Trainer Shiny Value to be a value for a shiny skip.
            // We need to un-set this flag if future frames don't pan out.
            bool forcedOT = false;

            int start = 2;

            while (true)
            {
                var upper = Cache[start + 1];
                var lower = Cache[start];
                // uint cid = upper << 16 | lower;
                var sv = (upper ^ lower) >> 3;
                if (sv == TSV) // XD shiny checks all opponent PKM, even non-shadow.
                {
                    // Anti-shiny rerolled! This is a possible frame.
                }
                else if (RCSV != NOT_FORCED) // CPU shiny value is required for a previous lock
                {
                    if (sv != RCSV)
                    {
                        if (forcedOT) // current call to this method had forced the OT; clear the forced OT before breaking.
                        {
                            RCSV = NOT_FORCED;
                        }
                        yield break; // Since we can't skip this interrupt, we're done.
                    }
                    else // No CPU shiny value forced yet. Lets try to skip this lock by requiring the eventual OT to get this shiny.
                    {
                        RCSV     = (int)sv;
                        forcedOT = true;
                        // don't break
                    }
                }
                // Yield the final rerolled pid instead of the bad anti-shiny (metadata/validation).
                yield return(new SeedFrame(pid, start + (current.Seen ? 5 : 7)));

                start += 2;
            }
        }
示例#5
0
 private static bool MatchesLock(NPCLock k, uint PID, int Gender)
 {
     if (k.Nature != null && k.Nature != PID % 25)
     {
         return(false);
     }
     if (k.Gender != null && k.Gender != Gender)
     {
         return(false);
     }
     return(true);
 }
示例#6
0
        /// <summary>
        /// Depth-first search traversal which finds a possible origin for the <see cref="Specifications"/>.
        /// </summary>
        /// <param name="frame">Frame at which the search starts/continues at.</param>
        /// <param name="prior">Prior <see cref="NPCLock"/> data. If this is the last lock in the CPU Team, this is null.</param>
        /// <returns>True if the <see cref="Specifications"/> are valid.</returns>
        private bool FindLockSeed(int frame = 0, NPCLock prior = null)
        {
            if (Locks.Count == 0) // full team reverse-generated
            {
                return(VerifyNPC(frame));
            }

            var current = Locks.Pop();
            var locks   = GetPossibleLocks(frame, current, prior);

            foreach (var l in locks)
            {
                Team.Push(l); // possible match
                if (FindLockSeed(l.FrameID, current))
                {
                    return(true); // all locks are satisfied
                }
                Team.Pop();       // no match, remove
            }

            Locks.Push(current); // return the lock, lock is impossible
            return(false);
        }
示例#7
0
        // Recursively iterates to visit possible locks until all locks (or none) are satisfied.
        public static bool FindLockSeed(uint seed, RNG RNG, Stack <NPCLock> Locks, NPCLock prior, Stack <uint> PIDs, bool XD, out uint origin)
        {
            if (Locks.Count == 0)
            {
                return(VerifyNPC(seed, RNG, PIDs, XD, out origin));
            }

            var l = Locks.Pop();

            foreach (var poss in FindPossibleLockFrames(seed, RNG, l, prior))
            {
                PIDs.Push(poss.PID); // possible match
                if (FindLockSeed(poss.Seed, RNG, Locks, l, PIDs, XD, out origin))
                {
                    return(true); // all locks are satisfied
                }
                PIDs.Pop();       // no match, remove
            }
            Locks.Push(l);        // return the lock, lock is impossible

            origin = seed;
            return(false);
        }
示例#8
0
        private static IEnumerable <SeedFrame> GetComplexLockFrame(FrameCache cache, int ctr, NPCLock l, NPCLock prior)
        {
            // Since the prior(next) lock is generated 7+2*n frames after, the worst case break is 7 frames after the PID.
            // Continue reversing until a sequential generation case is found.

            // Check

            int start = ctr;

            while (true)
            {
                int p7 = ctr - 7;

                if (p7 > start)
                {
                    uint cid = cache[p7 + 1] << 16 | cache[p7];
                    if (MatchesLock(prior, cid, PKX.GetGenderFromPID(prior.Species, cid)))
                    {
                        yield break;
                    }
                }
                uint pid = cache[ctr + 1] << 16 | cache[ctr];
                if (MatchesLock(l, pid, PKX.GetGenderFromPID(l.Species, pid)))
                {
                    yield return new SeedFrame {
                               FrameID = ctr + 6, PID = pid
                    }
                }
                ;

                ctr += 2;
            }
        }
示例#9
0
        private static IEnumerable <SeedFrame> GetSingleLockFrame(FrameCache cache, int ctr, NPCLock l)
        {
            uint pid = cache[ctr + 1] << 16 | cache[ctr];

            if (MatchesLock(l, pid, PKX.GetGenderFromPID(l.Species, pid)))
            {
                yield return new SeedFrame {
                           FrameID = ctr + 6, PID = pid
                }
            }
            ;
        }
示例#10
0
        private static IEnumerable <SeedFrame> FindPossibleLockFrames(FrameCache cache, int ctr, NPCLock l, NPCLock prior)
        {
            if (prior == null || prior.Shadow)
            {
                return(GetSingleLockFrame(cache, ctr, l));
            }

            return(GetComplexLockFrame(cache, ctr, l, prior));
        }
示例#11
0
        // Recursively iterates to visit possible locks until all locks (or none) are satisfied.
        private static bool FindLockSeed(FrameCache cache, int ctr, Stack <NPCLock> Locks, NPCLock prior, Stack <uint> PIDs, bool XD, out int originFrame)
        {
            if (Locks.Count == 0)
            {
                return(VerifyNPC(cache, ctr, PIDs, XD, out originFrame));
            }

            var l = Locks.Pop();

            foreach (var poss in FindPossibleLockFrames(cache, ctr, l, prior))
            {
                PIDs.Push(poss.PID); // possible match
                if (FindLockSeed(cache, poss.FrameID, Locks, l, PIDs, XD, out originFrame))
                {
                    return(true); // all locks are satisfied
                }
                PIDs.Pop();       // no match, remove
            }

            Locks.Push(l); // return the lock, lock is impossible
            originFrame = 0;
            return(false);
        }
示例#12
0
        // Restriction Checking
        private static IEnumerable <SeedPID> FindPossibleLockFrames(uint seed, RNG RNG, NPCLock l, NPCLock prior)
        {
            // todo: check for premature breaks
            do
            {
                // todo: generate PKM for checking
                uint pid    = 0;
                int  gender = 0;
                int  abil   = 0;
                uint origin = 0; // possible to defer calc to yield?

                if (prior == null)
                {
                    if (MatchesLock(l, pid, gender, abil))
                    {
                        yield return new SeedPID {
                                   Seed = origin, PID = pid
                        }
                    }
                    ;
                    yield break;
                }
                if (MatchesLock(prior, pid, gender, abil))
                {
                    yield break; // prior lock breaks our chain!
                }
                if (MatchesLock(l, pid, gender, abil))
                {
                    yield return new SeedPID {
                               Seed = origin, PID = pid
                    }
                }
                ;
            } while (true);
        }
示例#13
0
        private static IEnumerable <SeedFrame> GetSingleLockFrame(FrameCache cache, int ctr, NPCLock l)
        {
            uint pid = cache[ctr + 1] << 16 | cache[ctr];

            if (l.MatchesLock(pid))
            {
                yield return new SeedFrame {
                           FrameID = ctr + 6, PID = pid
                }
            }
            ;
        }