示例#1
0
        private void VerifyMiscG1Types(LegalityAnalysis data, PK1 pk1)
        {
            var Type_A = pk1.Type_A;
            var Type_B = pk1.Type_B;

            if (pk1.Species == (int)Species.Porygon)
            {
                // Can have any type combination of any species by using Conversion.
                if (!GBRestrictions.TypeIDExists(Type_A))
                {
                    data.AddLine(GetInvalid(LG1TypePorygonFail1));
                }
                if (!GBRestrictions.TypeIDExists(Type_B))
                {
                    data.AddLine(GetInvalid(LG1TypePorygonFail2));
                }
                else // Both match a type, ensure a gen1 species has this combo
                {
                    var TypesAB_Match = PersonalTable.RB.IsValidTypeCombination(Type_A, Type_B);
                    var result        = TypesAB_Match ? GetValid(LG1TypeMatchPorygon) : GetInvalid(LG1TypePorygonFail);
                    data.AddLine(result);
                }
            }
            else // Types must match species types
            {
                var Type_A_Match = Type_A == PersonalTable.RB[pk1.Species].Type1;
                var Type_B_Match = Type_B == PersonalTable.RB[pk1.Species].Type2;

                var first  = Type_A_Match ? GetValid(LG1TypeMatch1) : GetInvalid(LG1Type1Fail);
                var second = Type_B_Match ? GetValid(LG1TypeMatch2) : GetInvalid(LG1Type2Fail);
                data.AddLine(first);
                data.AddLine(second);
            }
        }
示例#2
0
        private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, IReadOnlyList <int> currentMoves, LegalInfo info)
        {
            var res          = new CheckMoveResult[4];
            var G1Encounter  = info.EncounterMatch;
            var InitialMoves = Array.Empty <int>();
            var SpecialMoves = GetSpecialMoves(info.EncounterMatch);
            var games        = info.EncounterMatch.Generation == 1 ? GBRestrictions.GetGen1Versions(info) : GBRestrictions.GetGen2Versions(info, pkm.Korean);

            foreach (var ver in games)
            {
                var VerInitialMoves = MoveLevelUp.GetEncounterMoves(G1Encounter.Species, 0, G1Encounter.LevelMin, ver);
                if (VerInitialMoves.Intersect(InitialMoves).Count() == VerInitialMoves.Length)
                {
                    return(res);
                }

                var source = new MoveParseSource
                {
                    CurrentMoves  = currentMoves,
                    SpecialSource = SpecialMoves,
                    Base          = VerInitialMoves,
                };
                res = ParseMoves(pkm, source, info);
                if (res.All(r => r.Valid))
                {
                    return(res);
                }
                InitialMoves = VerInitialMoves;
            }
            return(res);
        }
示例#3
0
        private static void ParseEvolutionsIncompatibleMoves(PKM pkm, IList <CheckMoveResult> res, IReadOnlyList <int> moves, IReadOnlyList <int> tmhm)
        {
            GBRestrictions.GetIncompatibleEvolutionMoves(pkm, moves, tmhm,
                                                         out var prevSpeciesID,
                                                         out var incompatPrev,
                                                         out var incompatCurr);

            if (prevSpeciesID == 0)
            {
                return;
            }

            var prev = SpeciesStrings[prevSpeciesID];
            var curr = SpeciesStrings[pkm.Species];

            for (int m = 0; m < 4; m++)
            {
                if (incompatCurr.Contains(moves[m]))
                {
                    res[m] = new CheckMoveResult(res[m], Invalid, string.Format(LMoveEvoFLower, curr, prev), Move);
                }
                if (incompatPrev.Contains(moves[m]))
                {
                    res[m] = new CheckMoveResult(res[m], Invalid, string.Format(LMoveEvoFHigher, curr, prev), Move);
                }
            }
        }
示例#4
0
        private static IEnumerable <IEncounterable> GenerateFilteredEncounters12(PKM pkm)
        {
            // If the current data indicates that it must have originated from Crystal, only yield encounter data from Crystal.
            bool crystal = (pkm is ICaughtData2 pk2 && pk2.CaughtData != 0) || (pkm.Format >= 7 && pkm.OT_Gender == 1);

            if (crystal)
            {
                return(GenerateRawEncounters12(pkm, GameVersion.C));
            }

            var visited = GBRestrictions.GetTradebackStatusInitial(pkm);

            switch (visited)
            {
            case TradebackType.Gen1_NotTradeback:
                return(GenerateRawEncounters12(pkm, GameVersion.RBY));

            case TradebackType.Gen2_NotTradeback:
                return(GenerateRawEncounters12(pkm, GameVersion.GSC));

            default:
                if (pkm.Korean)
                {
                    return(GenerateFilteredEncounters12BothKorean(pkm));
                }
                return(GenerateFilteredEncounters12Both(pkm));
            }
        }
示例#5
0
        private static CheckMoveResult[] ParseMoves(PKM pkm, MoveParseSource source, LegalInfo info)
        {
            var res = new CheckMoveResult[4];

            bool AllParsed() => res.All(z => z != null);

            var required = pkm is not PK1 pk1 ? 1 : GBRestrictions.GetRequiredMoveCount(pk1, source.CurrentMoves, info, source.Base);

            // Special considerations!
            int reset = 0;

            if (pkm is IBattleVersion {
                BattleVersion : not 0
            } v)
            {
                reset = ((GameVersion)v.BattleVersion).GetGeneration();
                source.ResetSources();
            }

            // Check empty moves and relearn moves before generation specific moves
            for (int m = 0; m < 4; m++)
            {
                if (source.CurrentMoves[m] == 0)
                {
                    res[m] = new CheckMoveResult(None, pkm.Format, m < required ? Fishy : Valid, LMoveSourceEmpty, CurrentMove);
                }
                else if (reset == 0 && info.EncounterMoves.Relearn.Contains(source.CurrentMoves[m]))
                {
                    res[m] = new CheckMoveResult(Relearn, info.Generation, Valid, LMoveSourceRelearn, CurrentMove);
                }
            }

            if (AllParsed())
            {
                return(res);
            }

            // Encapsulate arguments to simplify method calls
            var moveInfo = new LearnInfo(pkm, source);

            // Check moves going backwards, marking the move valid in the most current generation when it can be learned
            int[] generations = GenerationTraversal.GetVisitedGenerationOrder(pkm, info.EncounterOriginal.Generation);
            if (pkm.Format <= 2)
            {
                generations = generations.Where(z => z < info.EncounterMoves.LevelUpMoves.Length).ToArray();
            }
            if (reset != 0)
            {
                generations = generations.Where(z => z >= reset).ToArray();
            }

            int lastgen = generations.Length == 0 ? 0 : generations[^ 1];
示例#6
0
        private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, IReadOnlyList <int> currentMoves, LegalInfo info)
        {
            var res          = new CheckMoveResult[4];
            var enc          = info.EncounterMatch;
            var level        = pkm.HasOriginalMetLocation ? pkm.Met_Level : enc.LevelMin;
            var InitialMoves = Array.Empty <int>();
            var SpecialMoves = GetSpecialMoves(enc);
            var games        = enc.Generation == 1 ? GBRestrictions.GetGen1Versions(enc) : GBRestrictions.GetGen2Versions(enc, pkm.Korean);

            foreach (var ver in games)
            {
                var VerInitialMoves = MoveLevelUp.GetEncounterMoves(enc.Species, 0, level, ver);
                if (VerInitialMoves.Intersect(InitialMoves).Count() == VerInitialMoves.Length)
                {
                    return(res);
                }

                var source = new MoveParseSource
                {
                    CurrentMoves  = currentMoves,
                    SpecialSource = SpecialMoves,
                    Base          = VerInitialMoves,
                };
                res = ParseMoves(pkm, source, info);

                // Must have a minimum count of moves, depending on the tradeback state.
                if (pkm is PK1 pk1)
                {
                    int count = GBRestrictions.GetRequiredMoveCount(pk1, source.CurrentMoves, info, source.Base);
                    if (count == 1)
                    {
                        return(res);
                    }

                    for (int m = 0; m < count; m++)
                    {
                        var move = source.CurrentMoves[m];
                        if (move == 0)
                        {
                            res[m] = new CheckMoveResult(None, pkm.Format, Invalid, LMoveSourceEmpty, CurrentMove);
                        }
                    }
                }
                if (res.All(r => r.Valid))
                {
                    return(res);
                }
                InitialMoves = VerInitialMoves;
            }
            return(res);
        }
示例#7
0
        /// <summary>
        /// Checks the input <see cref="PKM"/> data for legality.
        /// </summary>
        /// <param name="pk">Input data to check</param>
        /// <param name="pi">Personal info to parse with</param>
        public LegalityAnalysis(PKM pk, PersonalInfo pi)
        {
            pkm          = pk;
            PersonalInfo = pi;

            if (pkm.Format <= 2) // prior to storing GameVersion
            {
                pkm.TradebackStatus = GBRestrictions.GetTradebackStatusInitial(pkm);
            }

#if SUPPRESS
            try
#endif
            {
                Info = EncounterFinder.FindVerifiedEncounter(pkm);
                if (!pkm.IsOriginValid)
                {
                    AddLine(Severity.Invalid, LEncConditionBadSpecies, CheckIdentifier.GameOrigin);
                }
                GetParseMethod()();

                if (Parse.Count == 0) // shouldn't ever happen as at least one is yielded above.
                {
                    AddLine(Severity.Invalid, L_AError, CheckIdentifier.Misc);
                    return;
                }

                Valid = Parse.All(chk => chk.Valid) &&
                        Info.Moves.All(m => m.Valid) &&
                        Info.Relearn.All(m => m.Valid);

                if (!Valid && pkm.FatefulEncounter && Info.Relearn.Any(chk => !chk.Valid) && EncounterMatch is EncounterInvalid)
                {
                    AddLine(Severity.Indeterminate, LFatefulGiftMissing, CheckIdentifier.Fateful);
                }
                Parsed = true;
            }
#if SUPPRESS
            // We want to swallow any error from malformed input data from the user. The Valid state is all that we really need.
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                System.Diagnostics.Debug.WriteLine(e.Message);
                Info  = new LegalInfo(pkm);
                Valid = false;
                AddLine(Severity.Invalid, L_AError, CheckIdentifier.Misc);
            }
#endif
        }
示例#8
0
        /// <summary>
        /// Checks the input <see cref="PKM"/> data for legality.
        /// </summary>
        /// <param name="pk">Input data to check</param>
        /// <param name="pi">Personal info to parse with</param>
        public LegalityAnalysis(PKM pk, PersonalInfo pi)
        {
            pkm          = pk;
            PersonalInfo = pi;

            if (pkm.Format <= 2) // prior to storing GameVersion
            {
                pkm.TradebackStatus = GBRestrictions.GetTradebackStatusInitial(pkm);
            }

#if SUPPRESS
            try
#endif
            {
                Info = EncounterFinder.FindVerifiedEncounter(pkm);
                if (!pkm.IsOriginValid)
                {
                    AddLine(Severity.Invalid, LEncConditionBadSpecies, CheckIdentifier.GameOrigin);
                }
                GetParseMethod()();

                if (Parse.Count == 0) // shouldn't ever happen as at least one is yielded above.
                {
                    AddLine(Severity.Invalid, L_AError, CheckIdentifier.Misc);
                    return;
                }

                Valid = Parse.All(chk => chk.Valid) &&
                        Info.Moves.All(m => m.Valid) &&
                        Info.Relearn.All(m => m.Valid);

                if (!Valid && pkm.FatefulEncounter && Info.Relearn.Any(chk => !chk.Valid) && EncounterMatch is EncounterInvalid)
                {
                    AddLine(Severity.Indeterminate, LFatefulGiftMissing, CheckIdentifier.Fateful);
                }
                Parsed = true;
            }
#if SUPPRESS
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.Message);
                Info  = new LegalInfo(pkm);
                Valid = false;
                AddLine(Severity.Invalid, L_AError, CheckIdentifier.Misc);
            }
#endif
        }
示例#9
0
文件: Analysis.cs 项目: Zovrah/PKHeX
 private void ParsePK1()
 {
     pkm.TradebackStatus = GBRestrictions.GetTradebackStatusInitial(pkm);
     UpdateInfo();
     if (pkm.TradebackStatus == TradebackType.Any && Info.Generation != pkm.Format)
     {
         pkm.TradebackStatus = TradebackType.WasTradeback; // Example: GSC Pokemon with only possible encounters in RBY, like the legendary birds
     }
     Nickname.Verify(this);
     Level.Verify(this);
     Level.VerifyG1(this);
     Trainer.VerifyOTG1(this);
     Misc.VerifyMiscG1(this);
     if (pkm.Format == 2)
     {
         Item.Verify(this);
     }
 }
示例#10
0
        private void VerifyMiscG1Types(LegalityAnalysis data, PK1 pk1)
        {
            var Type_A  = pk1.Type_A;
            var Type_B  = pk1.Type_B;
            var species = pk1.Species;

            if (species == (int)Species.Porygon)
            {
                // Can have any type combination of any species by using Conversion.
                if (!GBRestrictions.TypeIDExists(Type_A))
                {
                    data.AddLine(GetInvalid(LG1TypePorygonFail1));
                }
                if (!GBRestrictions.TypeIDExists(Type_B))
                {
                    data.AddLine(GetInvalid(LG1TypePorygonFail2));
                }
                else // Both types exist, ensure a Gen1 species has this combination
                {
                    var TypesAB_Match = PersonalTable.RB.IsValidTypeCombination(Type_A, Type_B);
                    var result        = TypesAB_Match ? GetValid(LG1TypeMatchPorygon) : GetInvalid(LG1TypePorygonFail);
                    data.AddLine(result);
                }
            }
            else // Types must match species types
            {
                var pi           = PersonalTable.RB[species];
                var Type_A_Match = Type_A == pi.Type1;
                var Type_B_Match = Type_B == pi.Type2;

                var first  = Type_A_Match ? GetValid(LG1TypeMatch1) : GetInvalid(LG1Type1Fail);
                var second = Type_B_Match || (ParseSettings.AllowGBCartEra && ((species == (int)Species.Magnemite || species == (int)Species.Magneton) && Type_B == 9)) // Steel Magnemite via Stadium2
                    ? GetValid(LG1TypeMatch2) : GetInvalid(LG1Type2Fail);
                data.AddLine(first);
                data.AddLine(second);
            }
        }
示例#11
0
        private static EvoCriteria[][] GetChainAll(PKM pkm, IEncounterTemplate enc, EvoCriteria[] fullChain)
        {
            int maxgen        = ParseSettings.AllowGen1Tradeback && pkm is PK1 ? 2 : pkm.Format;
            var GensEvoChains = GetAllEmpty(maxgen + 1);

            var head        = 0; // inlined FIFO queue indexing
            var mostEvolved = fullChain[head++];

            var lvl      = (byte)pkm.CurrentLevel;
            var maxLevel = lvl;
            int pkGen    = enc.Generation;

            // Iterate generations backwards
            // Maximum level of an earlier generation (GenX) will never be greater than a later generation (GenX+Y).
            int  mingen           = pkGen >= 3 ? pkGen : GBRestrictions.GetTradebackStatusInitial(pkm) == PotentialGBOrigin.Gen2Only ? 2 : 1;
            bool noxfrDecremented = true;

            for (int g = GensEvoChains.Length - 1; g >= mingen; g--)
            {
                if (pkGen <= 2 && g == 6)
                {
                    g = 2; // skip over 6543 as it never existed in these.
                }
                if (g <= 4 && pkm.Format > 2 && pkm.Format > g && !pkm.HasOriginalMetLocation)
                {
                    // Met location was lost at this point but it also means the pokemon existed in generations 1 to 4 with maximum level equals to met level
                    var met = pkm.Met_Level;
                    if (lvl > pkm.Met_Level)
                    {
                        lvl = (byte)met;
                    }
                }

                int maxspeciesgen = g == 2 && pkm.VC1 ? MaxSpeciesID_1 : GetMaxSpeciesOrigin(g);

                // Remove future gen evolutions after a few special considerations:
                // If the pokemon origin is illegal (e.g. Gen3 Infernape) the list will be emptied -- species lineage did not exist at any evolution stage.
                while (mostEvolved.Species > maxspeciesgen)
                {
                    if (head >= fullChain.Length)
                    {
                        if (g <= 2 && pkm.VC1)
                        {
                            GensEvoChains[pkm.Format] = NONE; // invalidate here since we haven't reached the regular invalidation
                        }
                        return(GensEvoChains);
                    }
                    if (mostEvolved.RequiresLvlUp)
                    {
                        // This is a Gen3 pokemon in a Gen4 phase evolution that requires level up and then transferred to Gen5+
                        // We can deduce that it existed in Gen4 until met level,
                        // but if current level is met level we can also deduce it existed in Gen3 until maximum met level -1
                        if (g == 3 && pkm.Format > 4 && lvl == maxLevel)
                        {
                            lvl--;
                        }

                        // The same condition for Gen2 evolution of Gen1 pokemon, level of the pokemon in Gen1 games would be CurrentLevel -1 one level below Gen2 level
                        else if (g == 1 && pkm.Format == 2 && lvl == maxLevel)
                        {
                            lvl--;
                        }
                    }
                    mostEvolved = fullChain[head++];
                }

                // Alolan form evolutions, remove from gens 1-6 chains
                if (HasAlolanForm(mostEvolved.Species))
                {
                    if (g < 7 && pkm.Format >= 7 && mostEvolved.Form > 0)
                    {
                        if (head >= fullChain.Length)
                        {
                            break;
                        }
                        mostEvolved = fullChain[head++];
                    }
                }

                GensEvoChains[g] = GetEvolutionChain(pkm, enc, mostEvolved.Species, lvl);
                ref var genChain = ref GensEvoChains[g];
                if (genChain.Length == 0)
                {
                    continue;
                }

                if (g > 2 && !pkm.HasOriginalMetLocation && g >= pkGen && noxfrDecremented)
                {
                    bool isTransferred = HasMetLocationUpdatedTransfer(pkGen, g);
                    if (!isTransferred)
                    {
                        continue;
                    }

                    noxfrDecremented = g > (pkGen != 3 ? 4 : 5);

                    // Remove previous evolutions below transfer level
                    // For example a gen3 Charizard in format 7 with current level 36 and met level 36, thus could never be Charmander / Charmeleon in Gen5+.
                    // chain level for Charmander is 35, is below met level.
                    int minlvl   = GetMinLevelGeneration(pkm, g);
                    int minIndex = Array.FindIndex(genChain, e => e.LevelMax >= minlvl);
                    if (minIndex != -1)
                    {
                        genChain = genChain.AsSpan(minIndex).ToArray();
                    }
                }
                else if (g == 1)
                {
                    // Remove Gen7 pre-evolutions and chain break scenarios
                    if (pkm.VC1)
                    {
                        TrimVC1Transfer(pkm, GensEvoChains);
                    }

                    ref var lastGen = ref GensEvoChains[1];
                    var     g1      = lastGen.AsSpan();
                    // Remove Gen2 post-evolutions (Scizor, Blissey...)
                    if (g1[0].Species > MaxSpeciesID_1)
                    {
                        if (g1.Length == 1)
                        {
                            lastGen = Array.Empty <EvoCriteria>();
                            continue; // done
                        }
                        g1 = g1[1..];
示例#12
0
        private static CheckMoveResult[] ParseMoves(PKM pkm, MoveParseSource source, LegalInfo info)
        {
            var res = new CheckMoveResult[4];

            bool AllParsed() => res.All(z => z != null);

            var required = pkm.Format != 1 ? 1 : GBRestrictions.GetRequiredMoveCount(pkm, source.CurrentMoves, info, source.Base);

            // Special considerations!
            int reset = 0;

            if (pkm is IBattleVersion v && v.BattleVersion != 0)
            {
                reset = ((GameVersion)v.BattleVersion).GetGeneration();
                source.EggEventSource           = Array.Empty <int>();
                source.Base                     = Array.Empty <int>();
                source.EggLevelUpSource         = Array.Empty <int>();
                source.EggMoveSource            = Array.Empty <int>();
                source.NonTradeBackLevelUpMoves = Array.Empty <int>();
                source.SpecialSource            = Array.Empty <int>();
            }

            // Check empty moves and relearn moves before generation specific moves
            for (int m = 0; m < 4; m++)
            {
                if (source.CurrentMoves[m] == 0)
                {
                    res[m] = new CheckMoveResult(None, pkm.Format, m < required ? Fishy : Valid, LMoveSourceEmpty, Move);
                }
                else if (reset == 0 && info.EncounterMoves.Relearn.Contains(source.CurrentMoves[m]))
                {
                    res[m] = new CheckMoveResult(Relearn, info.Generation, Valid, LMoveSourceRelearn, Move)
                    {
                        Flag = true
                    }
                }
                ;
            }

            if (AllParsed())
            {
                return(res);
            }

            // Encapsulate arguments to simplify method calls
            var moveInfo = new LearnInfo(pkm, source);

            // Check moves going backwards, marking the move valid in the most current generation when it can be learned
            int[] generations = GetGenMovesCheckOrder(pkm);
            if (pkm.Format <= 2)
            {
                generations = generations.Where(z => z < info.EncounterMoves.LevelUpMoves.Length).ToArray();
            }
            if (reset != 0)
            {
                generations = generations.Where(z => z >= reset).ToArray();
            }

            int lastgen = generations.LastOrDefault();

            foreach (var gen in generations)
            {
                ParseMovesByGeneration(pkm, res, gen, info, moveInfo, lastgen);
                if (AllParsed())
                {
                    return(res);
                }
            }

            if (pkm.Species == (int)Species.Shedinja && info.Generation <= 4)
            {
                ParseShedinjaEvolveMoves(pkm, res, source.CurrentMoves, info.EvoChainsAllGens);
            }

            for (int m = 0; m < 4; m++)
            {
                if (res[m] == null)
                {
                    res[m] = new CheckMoveResult(Unknown, info.Generation, Invalid, LMoveSourceInvalid, Move);
                }
            }
            return(res);
        }
示例#13
0
        private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, IReadOnlyList <int> currentMoves, LegalInfo info)
        {
            var res          = new CheckMoveResult[4];
            var enc          = info.EncounterMatch;
            var level        = pkm.HasOriginalMetLocation ? pkm.Met_Level : enc.LevelMin;
            var InitialMoves = Array.Empty <int>();
            var SpecialMoves = GetSpecialMoves(enc);
            var games        = enc.Generation == 1 ? GBRestrictions.GetGen1Versions(enc) : GBRestrictions.GetGen2Versions(enc, pkm.Korean);

            foreach (var ver in games)
            {
                var VerInitialMoves = enc is IMoveset {
                    Moves.Count : not 0
                } x ? (int[])x.Moves : MoveLevelUp.GetEncounterMoves(enc.Species, 0, level, ver);
                if (VerInitialMoves.Intersect(InitialMoves).Count() == VerInitialMoves.Length)
                {
                    return(res);
                }

                var source = new MoveParseSource
                {
                    CurrentMoves  = currentMoves,
                    SpecialSource = SpecialMoves,
                    Base          = VerInitialMoves,
                };
                res = ParseMoves(pkm, source, info);

                // Must have a minimum count of moves, depending on the tradeback state.
                if (pkm is PK1 pk1)
                {
                    int count = GBRestrictions.GetRequiredMoveCount(pk1, source.CurrentMoves, info, source.Base);
                    if (count == 1)
                    {
                        return(res);
                    }

                    // Reverse for loop and break instead of 0..count continue -- early-breaks for the vast majority of cases.
                    // We already flag for empty interstitial moveslots.
                    for (int m = count - 1; m >= 0; m--)
                    {
                        var move = source.CurrentMoves[m];
                        if (move != 0)
                        {
                            break;
                        }

                        // There are ways to skip level up moves by leveling up more than once.
                        // https://bulbapedia.bulbagarden.net/wiki/List_of_glitches_(Generation_I)#Level-up_learnset_skipping
                        // Evolution canceling also leads to incorrect assumptions in the above used method, so just indicate them as fishy in that case.
                        // Not leveled up? Not possible to be missing the move slot.
                        var severity = enc.LevelMin == pkm.CurrentLevel ? Invalid : Fishy;
                        res[m] = new CheckMoveResult(None, pkm.Format, severity, LMoveSourceEmpty, CurrentMove);
                    }
                }
                if (res.All(r => r.Valid))
                {
                    return(res);
                }
                InitialMoves = VerInitialMoves;
            }
            return(res);
        }
示例#14
0
        private void VerifyG1TradeEvo(LegalityAnalysis data)
        {
            // Context check is only applicable to gen1/2; transferring to Gen2 is a trade.
            // Stadium 2 can transfer across game/generation boundaries without initiating a trade.
            if (ParseSettings.ActiveTrainer.Generation >= 3 || ParseSettings.AllowGBCartEra)
            {
                return;
            }

            var pkm        = data.pkm;
            var mustevolve = pkm.TradebackStatus == TradebackType.WasTradeback || (pkm.Format == 1 && !ParseSettings.IsFromActiveTrainer(pkm)) || GBRestrictions.IsTradedKadabraG1(pkm);

            if (!mustevolve)
            {
                return;
            }

            // Pokemon have been traded but it is not evolved, trade evolutions are sequential dex numbers
            var evolved   = ParseSettings.SpeciesStrings[pkm.Species + 1];
            var unevolved = ParseSettings.SpeciesStrings[pkm.Species];

            data.AddLine(GetInvalid(string.Format(LEvoTradeReqOutsider, unevolved, evolved)));
        }
示例#15
0
        private void VerifyG1TradeEvo(LegalityAnalysis data)
        {
            var pkm        = data.pkm;
            var mustevolve = pkm.TradebackStatus == TradebackType.WasTradeback || (pkm.Format == 1 && !ParseSettings.IsFromActiveTrainer(pkm)) || GBRestrictions.IsTradedKadabraG1(pkm);

            if (!mustevolve)
            {
                return;
            }
            // Pokemon have been traded but it is not evolved, trade evos are sequential dex numbers
            var unevolved = LegalityAnalysis.SpeciesStrings[pkm.Species];
            var evolved   = LegalityAnalysis.SpeciesStrings[pkm.Species + 1];

            data.AddLine(GetInvalid(string.Format(LEvoTradeReqOutsider, unevolved, evolved)));
        }
示例#16
0
 private void VerifyG1TradeEvo(LegalityAnalysis data)
 {
     if (ParseSettings.ActiveTrainer.Generation >= 3)
         return; // context check is only applicable to gen1/2; transferring to gen2 is a trade.
     var pkm = data.pkm;
     var mustevolve = pkm.TradebackStatus == TradebackType.WasTradeback || (pkm.Format == 1 && !ParseSettings.IsFromActiveTrainer(pkm)) || GBRestrictions.IsTradedKadabraG1(pkm);
     if (!mustevolve)
         return;
     // Pokemon have been traded but it is not evolved, trade evos are sequential dex numbers
     var evolved = LegalityAnalysis.SpeciesStrings[pkm.Species + 1];
     var unevolved = LegalityAnalysis.SpeciesStrings[pkm.Species];
     data.AddLine(GetInvalid(string.Format(LEvoTradeReqOutsider, unevolved, evolved)));
 }
示例#17
0
        private static CheckMoveResult[] ParseMoves(PKM pkm, MoveParseSource source, LegalInfo info)
        {
            CheckMoveResult[] res = new CheckMoveResult[4];
            bool AllParsed() => res.All(r => r != null);

            var required = pkm.Format != 1 ? 1 : GBRestrictions.GetRequiredMoveCount(pkm, source.CurrentMoves, info, source.Base);

            // Check empty moves and relearn moves before generation specific moves
            for (int m = 0; m < 4; m++)
            {
                if (source.CurrentMoves[m] == 0)
                {
                    res[m] = new CheckMoveResult(MoveSource.None, pkm.Format, m < required ? Severity.Fishy : Severity.Valid, LMoveSourceEmpty, CheckIdentifier.Move);
                }
                else if (info.EncounterMoves.Relearn.Contains(source.CurrentMoves[m]))
                {
                    res[m] = new CheckMoveResult(MoveSource.Relearn, info.Generation, Severity.Valid, LMoveSourceRelearn, CheckIdentifier.Move)
                    {
                        Flag = true
                    }
                }
                ;
            }

            if (AllParsed())
            {
                return(res);
            }

            // Encapsulate arguments to simplify method calls
            var moveInfo = new LearnInfo(pkm)
            {
                Source = source
            };

            // Check moves going backwards, marking the move valid in the most current generation when it can be learned
            int[] generations = GetGenMovesCheckOrder(pkm);
            if (pkm.Format <= 2)
            {
                generations = generations.Where(z => z < info.EncounterMoves.LevelUpMoves.Length).ToArray();
            }

            int lastgen = generations.LastOrDefault();

            foreach (var gen in generations)
            {
                ParseMovesByGeneration(pkm, res, gen, info, moveInfo, lastgen);
                if (AllParsed())
                {
                    return(res);
                }
            }

            if (pkm.Species == 292 && info.Generation <= 4)
            {
                ParseShedinjaEvolveMoves(pkm, res, source.CurrentMoves);
            }

            for (int m = 0; m < 4; m++)
            {
                if (res[m] == null)
                {
                    res[m] = new CheckMoveResult(MoveSource.Unknown, info.Generation, Severity.Invalid, LMoveSourceInvalid, CheckIdentifier.Move);
                }
            }
            return(res);
        }