Esempio n. 1
0
        private static void ParseEvolutionLevelupMove(PKM pkm, IList <CheckMoveResult> res, IReadOnlyList <int> currentMoves, LegalInfo info)
        {
            // Ignore if there is an invalid move or an empty move, this validation is only for 4 non-empty moves that are all valid, but invalid as a 4 combination
            // Ignore Mr. Mime and Sudowodoo from generations 1 to 3, they cant be evolved from Bonsly or Munchlax
            // Ignore if encounter species is the evolution species, the pokemon was not evolved by the player
            if (info.EncounterMatch.Species == pkm.Species)
            {
                return;
            }
            if (!res.All(r => r?.Valid ?? false) || currentMoves.Any(m => m == 0) || (EvolutionRestrictions.BabyEvolutionWithMove.Contains(pkm.Species) && info.Generation <= 3))
            {
                return;
            }

            var ValidMoves = MoveList.GetValidPostEvolutionMoves(pkm, pkm.Species, info.EvoChainsAllGens, GameVersion.Any);

            // Add the evolution moves to valid moves in case some of these moves could not be learned after evolving
            switch (pkm.Species)
            {
            case (int)Species.MrMime:     // Mr. Mime (Mime Jr with Mimic)
            case (int)Species.Sudowoodo:  // Sudowoodo (Bonsly with Mimic)
                ValidMoves.Add((int)Move.Mimic);
                break;

            case (int)Species.Ambipom:     // Ambipom (Aipom with Double Hit)
                ValidMoves.Add((int)Move.DoubleHit);
                break;

            case (int)Species.Lickilicky:     // Lickilicky (Lickitung with Rollout)
                ValidMoves.Add((int)Move.Rollout);
                break;

            case (int)Species.Tangrowth:   // Tangrowth (Tangela with Ancient Power)
            case (int)Species.Yanmega:     // Yanmega (Yanma with Ancient Power)
            case (int)Species.Mamoswine:   // Mamoswine (Piloswine with Ancient Power)
                ValidMoves.Add((int)Move.AncientPower);
                break;

            case (int)Species.Sylveon:     // Sylveon (Eevee with Fairy Move)
                // Add every fairy moves without checking if Eevee learn it or not; pokemon moves are determined legal before this function
                ValidMoves.AddRange(EvolutionRestrictions.FairyMoves);
                break;

            case (int)Species.Tsareena:     // Tsareena (Steenee with Stomp)
                ValidMoves.Add((int)Move.Stomp);
                break;
            }

            if (currentMoves.Any(m => ValidMoves.Contains(m)))
            {
                return;
            }

            for (int m = 0; m < 4; m++)
            {
                res[m] = new CheckMoveResult(res[m], Invalid, string.Format(LMoveEvoFCombination_0, SpeciesStrings[pkm.Species]), CurrentMove);
            }
        }
Esempio n. 2
0
        private static void ParseEvolutionLevelupMove(PKM pkm, IList <CheckMoveResult> res, int[] moves, LegalInfo info)
        {
            // Ignore if there is an invalid move or an empty move, this validation is only for 4 non-empty moves that are all valid, but invalid as a 4 combination
            // Ignore Mr. Mime and Sudowodoo from generations 1 to 3, they cant be evolved from Bonsly or Munchlax
            // Ignore if encounter species is the evolution species, the pokemon was not evolved by the player
            if (info.EncounterMatch.Species == pkm.Species)
            {
                return;
            }
            if (!res.All(r => r?.Valid ?? false) || moves.Any(m => m == 0) || (Legal.BabyEvolutionWithMove.Contains(pkm.Species) && info.Generation <= 3))
            {
                return;
            }

            var ValidMoves = Legal.GetValidPostEvolutionMoves(pkm, pkm.Species, info.EvoChainsAllGens, GameVersion.Any);

            // Add the evolution moves to valid moves in case some of these moves could not be learned after evolving
            switch (pkm.Species)
            {
            case 122:     // Mr. Mime (Mime Jr with Mimic)
            case 185:     // Sudowoodo (Bonsly with Mimic)
                ValidMoves.Add(102);
                break;

            case 424:     // Ambipom (Aipom with Double Hit)
                ValidMoves.Add(458);
                break;

            case 463:     // Lickilicky (Lickitung with Rollout)
                ValidMoves.Add(205);
                break;

            case 465:     // Tangrowth (Tangela with Ancient Power)
            case 469:     // Yanmega (Yamma with Ancient Power)
            case 473:     // Mamoswine (Piloswine with Ancient Power)
                ValidMoves.Add(246);
                break;

            case 700:     // Sylveon (Eevee with Fairy Move)
                // Add every fairy moves without cheking if eevee learn it or not, pokemon moves are determined legal before this function
                ValidMoves.AddRange(Legal.FairyMoves);
                break;

            case 763:     // Tsareena (Steenee with Stomp)
                ValidMoves.Add(023);
                break;
            }

            if (moves.Any(m => ValidMoves.Contains(m)))
            {
                return;
            }

            for (int m = 0; m < 4; m++)
            {
                res[m] = new CheckMoveResult(res[m], Severity.Invalid, string.Format(LMoveEvoFCombination_0, SpeciesStrings[pkm.Species]), CheckIdentifier.Move);
            }
        }
Esempio n. 3
0
        private static CheckMoveResult[] ParseMoves(PKM pkm, MoveParseSource source, LegalInfo info)
        {
            var res = new CheckMoveResult[4];

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

            // Special considerations!
            const int NoMinGeneration = 0;
            int       minGeneration   = NoMinGeneration;

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

            // Check empty moves and relearn moves before generation specific moves
            for (int m = 0; m < 4; m++)
            {
                var move = source.CurrentMoves[m];
                if (move == 0)
                {
                    res[m] = new CheckMoveResult(None, pkm.Format, Valid, LMoveSourceEmpty, CurrentMove);
                }
                else if (minGeneration == NoMinGeneration && info.EncounterMoves.Relearn.Contains(move))
                {
                    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 = Array.FindAll(generations, z => z < info.EncounterMoves.LevelUpMoves.Length);
            }
            if (minGeneration != NoMinGeneration)
            {
                generations = Array.FindAll(generations, z => z >= minGeneration);
            }

            if (generations.Length != 0)
            {
                int lastgen = generations[^ 1];
Esempio n. 4
0
 private static CheckMoveResult[] ParseMovesSketch(PKM pkm, int[] Moves)
 {
     CheckMoveResult[] res = new CheckMoveResult[4];
     for (int i = 0; i < 4; i++)
     {
         res[i] = Legal.InvalidSketch.Contains(Moves[i])
             ? new CheckMoveResult(MoveSource.Unknown, pkm.Format, Severity.Invalid, V166, CheckIdentifier.Move)
             : new CheckMoveResult(MoveSource.Sketch, pkm.Format, CheckIdentifier.Move);
     }
     return(res);
 }
Esempio n. 5
0
 private static void FlagEmptySlotsBeforeIndex(IReadOnlyList <int> moves, CheckMoveResult[] res, int i)
 {
     for (int k = i - 1; k >= 0; k--)
     {
         if (moves[k] != 0)
         {
             return;
         }
         res[k] = new CheckMoveResult(res[k], Invalid, LMoveSourceEmpty);
     }
 }
Esempio n. 6
0
 private static void FlagDuplicateMovesAfterIndex(IReadOnlyList <int> moves, CheckMoveResult[] res, int i, int move)
 {
     for (int j = i + 1; j < 4; j++)
     {
         if (moves[j] != move)
         {
             continue;
         }
         res[i] = new CheckMoveResult(res[i], Invalid, LMoveSourceDuplicate);
         return;
     }
 }
Esempio n. 7
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];
Esempio n. 8
0
        private static CheckMoveResult[] ParseMovesSketch(PKM pkm, IReadOnlyList <int> currentMoves)
        {
            var res = new CheckMoveResult[4];

            for (int i = 0; i < 4; i++)
            {
                res[i] = Legal.InvalidSketch.Contains(currentMoves[i])
                    ? new CheckMoveResult(Unknown, pkm.Format, Invalid, LMoveSourceInvalidSketch, Move)
                    : new CheckMoveResult(Sketch, pkm.Format, Move);
            }

            return(res);
        }
Esempio n. 9
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);
        }
Esempio n. 10
0
        /// <summary>
        /// Verifies the current moves of the <see cref="pkm"/> data based on the provided <see cref="info"/>.
        /// </summary>
        /// <param name="pkm">Data to check</param>
        /// <param name="info">Encounter conditions and legality info</param>
        /// <returns>Validity of the <see cref="PKM.Moves"/></returns>
        public static CheckMoveResult[] VerifyMoves(PKM pkm, LegalInfo info)
        {
            var currentMoves = pkm.Moves;
            var res          = ParseMovesForEncounters(pkm, info, currentMoves);

            // Duplicate Moves Check
            VerifyNoEmptyDuplicates(currentMoves, res);
            if (currentMoves[0] == 0) // Can't have an empty move slot for the first move.
            {
                res[0] = new CheckMoveResult(res[0], Invalid, LMoveSourceEmpty, Move);
            }

            return(res);
        }
Esempio n. 11
0
        private static CheckMoveResult[] ParseMovesSketch(PKM pkm, IReadOnlyList <int> currentMoves)
        {
            var res = new CheckMoveResult[4];

            for (int i = 0; i < 4; i++)
            {
                var move = currentMoves[i];
                res[i] = Legal.InvalidSketch.Contains(move) || (pkm.Format is 6 && move is (int)Move.ThousandArrows or(int) Move.ThousandWaves)
                    ? new CheckMoveResult(Unknown, pkm.Format, Invalid, LMoveSourceInvalidSketch, CurrentMove)
                    : new CheckMoveResult(Sketch, pkm.Format, CurrentMove);
            }

            return(res);
        }
Esempio n. 12
0
        public static CheckMoveResult[] VerifyMoves(PKM pkm, LegalInfo info)
        {
            int[] Moves = pkm.Moves;
            var   res   = ParseMovesForEncounters(pkm, info, Moves);

            // Duplicate Moves Check
            VerifyNoEmptyDuplicates(Moves, res);
            if (Moves[0] == 0) // Can't have an empty moveslot for the first move.
            {
                res[0] = new CheckMoveResult(res[0], Severity.Invalid, V167, CheckIdentifier.Move);
            }

            return(res);
        }
Esempio n. 13
0
        private static void FlagIncompatibleTransferMove(PKM pkm, IList <CheckMoveResult> Moves, int move, int gen)
        {
            int index = Array.IndexOf(pkm.Moves, move);

            if (index < 0)
            {
                return; // doesn't have move
            }
            var chk = Moves[index];

            if (chk.Generation == gen) // not obtained from a future gen
            {
                Moves[index] = new CheckMoveResult(chk.Source, chk.Generation, Severity.Invalid, LTransferMove, CheckIdentifier.Move);
            }
        }
Esempio n. 14
0
        private static void ParseEggMovesInherited(PKM pkm, CheckMoveResult[] res, int gen, LearnInfo learnInfo)
        {
            var moves = learnInfo.Source.CurrentMoves;

            // Check higher-level moves after all the moves but just before egg moves to differentiate it from normal level up moves
            // Also check if the base egg moves is a non tradeback move
            for (int m = 0; m < 4; m++)
            {
                var r = res[m];
                if (IsCheckValid(r)) // already validated
                {
                    if (gen == 2 && r.Generation != 1)
                    {
                        continue;
                    }
                }

                int move = moves[m];
                if (move == 0)
                {
                    continue;
                }
                if (!learnInfo.Source.EggLevelUpSource.Contains(move)) // Check if contains level-up egg moves from parents
                {
                    continue;
                }

                if (learnInfo.IsGen2Pkm && learnInfo.Gen1Moves.Count != 0 && move > Legal.MaxMoveID_1)
                {
                    res[m] = new CheckMoveResult(InheritLevelUp, gen, Invalid, LG1MoveTradeback, Move);
                    learnInfo.MixedGen12NonTradeback = true;
                }
                else
                {
                    res[m] = new CheckMoveResult(InheritLevelUp, gen, Valid, LMoveEggLevelUp, Move);
                }
                learnInfo.LevelUpEggMoves.Add(m);
                if (gen == 2 && learnInfo.Gen1Moves.Contains(m))
                {
                    learnInfo.Gen1Moves.Remove(m);
                }
            }

            if (gen <= 2 && learnInfo.Gen1Moves.Count == 0)
            {
                pkm.TradebackStatus = TradebackType.Any;
            }
        }
Esempio n. 15
0
        private static void ParseRedYellowIncompatibleMoves(PKM pkm, IList <CheckMoveResult> res, int[] moves)
        {
            var incompatible = GetIncompatibleRBYMoves(pkm, moves);

            if (incompatible.Count == 0)
            {
                return;
            }
            for (int m = 0; m < 4; m++)
            {
                if (incompatible.Contains(moves[m]))
                {
                    res[m] = new CheckMoveResult(res[m], Severity.Invalid, V363, CheckIdentifier.Move);
                }
            }
        }
Esempio n. 16
0
        private static void ParseRedYellowIncompatibleMoves(PKM pkm, IList <CheckMoveResult> res, IReadOnlyList <int> currentMoves)
        {
            var incompatible = GetIncompatibleRBYMoves(pkm, currentMoves);

            if (incompatible.Count == 0)
            {
                return;
            }
            for (int m = 0; m < 4; m++)
            {
                if (incompatible.Contains(currentMoves[m]))
                {
                    res[m] = new CheckMoveResult(res[m], Invalid, LG1MoveLearnSameLevel, Move);
                }
            }
        }
Esempio n. 17
0
        private static void ParseEggMovesRemaining(PKM pkm, CheckMoveResult[] res, LearnInfo learnInfo)
        {
            // A pokemon could have normal egg moves and regular egg moves
            // Only if all regular egg moves are event egg moves or all event egg moves are regular egg moves
            var RegularEggMovesLearned = learnInfo.EggMovesLearned.Union(learnInfo.LevelUpEggMoves).ToList();

            if (RegularEggMovesLearned.Count != 0 && learnInfo.EventEggMoves.Count != 0)
            {
                // Moves that are egg moves or event egg moves but not both
                var IncompatibleEggMoves = RegularEggMovesLearned.Except(learnInfo.EventEggMoves).Union(learnInfo.EventEggMoves.Except(RegularEggMovesLearned)).ToList();
                if (IncompatibleEggMoves.Count == 0)
                {
                    return;
                }
                foreach (int m in IncompatibleEggMoves)
                {
                    if (learnInfo.EventEggMoves.Contains(m) && !learnInfo.EggMovesLearned.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Severity.Invalid, V337, CheckIdentifier.Move);
                    }
                    else if (!learnInfo.EventEggMoves.Contains(m) && learnInfo.EggMovesLearned.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Severity.Invalid, V336, CheckIdentifier.Move);
                    }
                    else if (!learnInfo.EventEggMoves.Contains(m) && learnInfo.LevelUpEggMoves.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Severity.Invalid, V358, CheckIdentifier.Move);
                    }
                }
            }
            // If there is no incompatibility with event egg check that there is no inherited move in gift eggs and event eggs
            else if (RegularEggMovesLearned.Count != 0 && (pkm.WasGiftEgg || pkm.WasEventEgg))
            {
                foreach (int m in RegularEggMovesLearned)
                {
                    if (learnInfo.EggMovesLearned.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Severity.Invalid, pkm.WasGiftEgg ? V377 : V341, CheckIdentifier.Move);
                    }
                    else if (learnInfo.LevelUpEggMoves.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Severity.Invalid, pkm.WasGiftEgg ? V378 : V347, CheckIdentifier.Move);
                    }
                }
            }
        }
Esempio n. 18
0
        private static void ParseEggMovesRemaining(PKM pkm, CheckMoveResult[] res, LearnInfo learnInfo)
        {
            // A pokemon could have normal egg moves and regular egg moves
            // Only if all regular egg moves are event egg moves or all event egg moves are regular egg moves
            var RegularEggMovesLearned = learnInfo.EggMovesLearned.Union(learnInfo.LevelUpEggMoves).ToList();

            if (RegularEggMovesLearned.Count != 0 && learnInfo.EventEggMoves.Count != 0)
            {
                // Moves that are egg moves or event egg moves but not both
                var IncompatibleEggMoves = RegularEggMovesLearned.Except(learnInfo.EventEggMoves).Union(learnInfo.EventEggMoves.Except(RegularEggMovesLearned)).ToList();
                if (IncompatibleEggMoves.Count == 0)
                {
                    return;
                }
                foreach (int m in IncompatibleEggMoves)
                {
                    if (learnInfo.EventEggMoves.Contains(m) && !learnInfo.EggMovesLearned.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Invalid, LMoveEggIncompatibleEvent, Move);
                    }
                    else if (!learnInfo.EventEggMoves.Contains(m) && learnInfo.EggMovesLearned.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Invalid, LMoveEggIncompatible, Move);
                    }
                    else if (!learnInfo.EventEggMoves.Contains(m) && learnInfo.LevelUpEggMoves.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Invalid, LMoveEventEggLevelUp, Move);
                    }
                }
            }
            else if (RegularEggMovesLearned.Count != 0 && (pkm.WasGiftEgg || pkm.WasEventEgg))
            {
                // Event eggs cannot inherit moves from parents; they are not bred.
                foreach (int m in RegularEggMovesLearned)
                {
                    if (learnInfo.EggMovesLearned.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Invalid, pkm.WasGiftEgg ? LMoveEggMoveGift : LMoveEggInvalidEvent, Move);
                    }
                    else if (learnInfo.LevelUpEggMoves.Contains(m))
                    {
                        res[m] = new CheckMoveResult(res[m], Invalid, pkm.WasGiftEgg ? LMoveEggInvalidEventLevelUpGift : LMoveEggInvalidEventLevelUp, Move);
                    }
                }
            }
        }
Esempio n. 19
0
        private static void VerifyNoEmptyDuplicates(int[] Moves, CheckMoveResult[] res)
        {
            bool emptySlot = false;

            for (int i = 0; i < 4; i++)
            {
                if (Moves[i] == 0)
                {
                    emptySlot = true;
                }
                else if (emptySlot)
                {
                    res[i] = new CheckMoveResult(res[i], Severity.Invalid, V167, res[i].Identifier);
                }
                else if (Moves.Count(m => m == Moves[i]) > 1)
                {
                    res[i] = new CheckMoveResult(res[i], Severity.Invalid, V168, res[i].Identifier);
                }
            }
        }
Esempio n. 20
0
        private static void VerifyNoEmptyDuplicates(IReadOnlyList <int> moves, CheckMoveResult[] res)
        {
            bool emptySlot = false;

            for (int i = 0; i < 4; i++)
            {
                if (moves[i] == 0)
                {
                    emptySlot = true;
                }
                else if (emptySlot)
                {
                    res[i] = new CheckMoveResult(res[i], Invalid, LMoveSourceEmpty, res[i].Identifier);
                }
                else if (moves.Count(m => m == moves[i]) > 1)
                {
                    res[i] = new CheckMoveResult(res[i], Invalid, LMoveSourceDuplicate, res[i].Identifier);
                }
            }
        }
Esempio n. 21
0
        private static void ParseRedYellowIncompatibleMoves(PKM pkm, IList <CheckMoveResult> res, int[] moves)
        {
            // Check moves that are learned at the same level in red/blue and yellow, these are illegal because there is no move reminder
            // There are only two incompatibilites; there is no illegal combination in generation 2+.
            var incompatible = new List <int>();

            switch (pkm.Species)
            {
            // Vaporeon in Yellow learns Mist and Haze at level 42, Mist can only be larned if it levels up in the daycare
            // Vaporeon in Red/Blue learns Acid Armor at level 42 and level 47 in Yellow
            case 134 when pkm.CurrentLevel < 47 && moves.Contains(151):
                if (moves.Contains(54))
                {
                    incompatible.Add(54);
                }
                if (moves.Contains(114))
                {
                    incompatible.Add(114);
                }
                if (incompatible.Any())
                {
                    incompatible.Add(151);
                }
                break;

            // Flareon in Yellow learns Smog at level 42
            // Flareon in Red Blue learns Leer at level 42 and level 47 in Yellow
            case 136 when pkm.CurrentLevel < 47 && moves.Contains(43) && moves.Contains(123):
                incompatible.Add(43);
                incompatible.Add(123);
                break;
            }

            for (int m = 0; m < 4; m++)
            {
                if (incompatible.Contains(moves[m]))
                {
                    res[m] = new CheckMoveResult(res[m], Severity.Invalid, V363, CheckIdentifier.Move);
                }
            }
        }
Esempio n. 22
0
        private static CheckMoveResult[] ParseMovesIsEggPreRelearn(PKM pkm, int[] Moves, int[] SpecialMoves, bool allowinherited, EncounterEgg e)
        {
            CheckMoveResult[] res = new CheckMoveResult[4];

            var baseEggMoves = Legal.GetBaseEggMoves(pkm, e.Species, e.Game, pkm.GenNumber < 4 ? 5 : 1)?.ToList() ?? new List <int>();
            // Level up moves cannot be inherited if Ditto is parent, thus genderless/single gender species cannot have level up moves as an egg
            bool AllowLvlMoves     = pkm.PersonalInfo.Gender > 0 && pkm.PersonalInfo.Gender < 255 || Legal.MixedGenderBreeding.Contains(e.Species);
            var  InheritedLvlMoves = !AllowLvlMoves? new List <int>() : Legal.GetBaseEggMoves(pkm, e.Species, e.Game, 100)?.ToList() ?? new List <int>();

            InheritedLvlMoves.RemoveAll(x => baseEggMoves.Contains(x));

            var infoset = new MoveInfoSet
            {
                EggMoves       = Legal.GetEggMoves(pkm, e.Species, pkm.AltForm)?.ToList() ?? new List <int>(),
                TutorMoves     = e.Game == GameVersion.C ? Legal.GetTutorMoves(pkm, pkm.Species, pkm.AltForm, false, 2)?.ToList() : new List <int>(),
                TMHMMoves      = Legal.GetTMHM(pkm, pkm.Species, pkm.AltForm, pkm.GenNumber, e.Game, false)?.ToList(),
                LvlMoves       = InheritedLvlMoves,
                BaseMoves      = baseEggMoves,
                SpecialMoves   = SpecialMoves.Where(m => m != 0).ToList(),
                AllowInherited = allowinherited
            };

            // Only TM Hm moves from the source game of the egg, not any other games from the same generation

            if (pkm.Format > 2 || SpecialMoves.Any())
            {
                // For gen 2 is not possible to difference normal eggs from event eggs
                // If there is no special moves assume normal egg
                res = VerifyPreRelearnEggBase(pkm, Moves, infoset, e.Game);
            }
            else if (pkm.Format == 2)
            {
                infoset.SpecialMoves.Clear();
                infoset.AllowInherited = true;
                res = VerifyPreRelearnEggBase(pkm, Moves, infoset, e.Game);
            }

            return(res);
        }
Esempio n. 23
0
        private static void ParseMovesByGeneration12(PKM pkm, CheckMoveResult[] res, int[] moves, int gen, LegalInfo info, LearnInfo learnInfo)
        {
            // Mark the gen 1 exclusive moves as illegal because the pokemon also have Non tradeback egg moves.
            if (learnInfo.MixedGen12NonTradeback)
            {
                foreach (int m in learnInfo.Gen1Moves)
                {
                    res[m] = new CheckMoveResult(res[m], Severity.Invalid, V335, CheckIdentifier.Move);
                }

                foreach (int m in learnInfo.Gen2PreevoMoves)
                {
                    res[m] = new CheckMoveResult(res[m], Severity.Invalid, V412, CheckIdentifier.Move);
                }
            }

            if (gen == 1 && pkm.Format == 1 && pkm.Gen1_NotTradeback)
            {
                ParseRedYellowIncompatibleMoves(pkm, res, moves);
                ParseEvolutionsIncompatibleMoves(pkm, res, moves, info.EncounterMoves.TMHMMoves[1]);
            }
        }
Esempio n. 24
0
        private static void ParseMovesByGeneration12(PKM pkm, CheckMoveResult[] res, IReadOnlyList <int> currentMoves, int gen, LegalInfo info, LearnInfo learnInfo)
        {
            // Mark the gen 1 exclusive moves as illegal because the pokemon also have Non tradeback egg moves.
            if (learnInfo.MixedGen12NonTradeback)
            {
                foreach (int m in learnInfo.Gen1Moves)
                {
                    res[m] = new CheckMoveResult(res[m], Invalid, LG1MoveExclusive, CurrentMove);
                }

                foreach (int m in learnInfo.Gen2PreevoMoves)
                {
                    res[m] = new CheckMoveResult(res[m], Invalid, LG1TradebackPreEvoMove, CurrentMove);
                }
            }

            if (gen == 1 && pkm.Format == 1 && pkm.Gen1_NotTradeback)
            {
                ParseRedYellowIncompatibleMoves(pkm, res, currentMoves);
                ParseEvolutionsIncompatibleMoves(pkm, res, currentMoves, info.EncounterMoves.TMHMMoves[1]);
            }
        }
Esempio n. 25
0
        private static void ParseEggMovesInherited(PKM pkm, CheckMoveResult[] res, int gen, LearnInfo learnInfo)
        {
            var moves = learnInfo.Source.CurrentMoves;

            // Check higher-level moves after all the moves but just before egg moves to differentiate it from normal level up moves
            // Also check if the base egg moves is a non tradeback move
            for (int m = 0; m < 4; m++)
            {
                if (IsCheckValid(res[m])) // already validated
                {
                    continue;
                }
                if (moves[m] == 0)
                {
                    continue;
                }
                if (!learnInfo.Source.EggLevelUpSource.Contains(moves[m])) // Check if contains level-up egg moves from parents
                {
                    continue;
                }

                if (learnInfo.IsGen2Pkm && learnInfo.Gen1Moves.Count != 0 && moves[m] > Legal.MaxMoveID_1)
                {
                    res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Invalid, V334, CheckIdentifier.Move);
                    learnInfo.MixedGen12NonTradeback = true;
                }
                else
                {
                    res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Valid, V345, CheckIdentifier.Move);
                }
                learnInfo.LevelUpEggMoves.Add(m);
                if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
                {
                    pkm.TradebackStatus = TradebackType.WasTradeback;
                }
            }
        }
Esempio n. 26
0
        private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, int[] Moves, LegalInfo info)
        {
            CheckMoveResult[] res = new CheckMoveResult[4];
            var G1Encounter       = info.EncounterMatch;

            if (G1Encounter == null)
            {
                return(ParseMovesSpecialMoveset(pkm, Moves, info));
            }
            var InitialMoves = Array.Empty <int>();

            int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
            var   games        = info.EncounterMatch is IGeneration g && g.Generation == 1 ? Legal.GetGen1Versions(info) : Legal.GetGen2Versions(info);

            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  = Moves,
                    SpecialSource = SpecialMoves,
                    Base          = VerInitialMoves,
                };
                res = ParseMoves(pkm, source, info);
                if (res.All(r => r.Valid))
                {
                    return(res);
                }
                InitialMoves = VerInitialMoves;
            }
            return(res);
        }
Esempio n. 27
0
        private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, int[] Moves, LegalInfo info)
        {
            CheckMoveResult[] res = new CheckMoveResult[4];
            var G1Encounter       = info.EncounterMatch;

            if (G1Encounter == null)
            {
                return(ParseMovesSpecialMoveset(pkm, Moves, info));
            }
            var InitialMoves = new int[0];

            int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
            IEnumerable <GameVersion> games = (info.EncounterMatch as IGeneration)?.Generation == 1 ? Legal.GetGen1Versions(info) : Legal.GetGen2Versions(info);

            foreach (GameVersion ver in games)
            {
                var VerInitialMoves = Legal.GetInitialMovesGBEncounter(G1Encounter.Species, G1Encounter.LevelMin, ver).ToArray();
                if (VerInitialMoves.SequenceEqual(InitialMoves))
                {
                    return(res);
                }

                var source = new MoveParseSource
                {
                    CurrentMoves  = Moves,
                    SpecialSource = SpecialMoves,
                    Base          = VerInitialMoves,
                };
                res = ParseMoves(pkm, source, info);
                if (res.All(r => r.Valid))
                {
                    return(res);
                }
                InitialMoves = VerInitialMoves;
            }
            return(res);
        }
Esempio n. 28
0
        private static void ParseRedYellowIncompatibleMoves(PKM pkm, IList <CheckMoveResult> res, int[] moves)
        {
            var incompatible = new List <int>();

            if (pkm.Species == 134 && pkm.CurrentLevel < 47 && moves.Contains(151))
            {
                // Vaporeon in Yellow learn Mist and Haze at level 42, Mist only if level up in day-care
                // Vaporeon in Red Blue learn Acid Armor at level 42 and level 47 in Yellow
                if (moves.Contains(54))
                {
                    incompatible.Add(54);
                }
                if (moves.Contains(114))
                {
                    incompatible.Add(114);
                }
                if (incompatible.Any())
                {
                    incompatible.Add(151);
                }
            }
            if (pkm.Species == 136 && pkm.CurrentLevel < 47 && moves.Contains(43) && moves.Contains(123))
            {
                // Flareon in Yellow learn Smog at level 42
                // Flareon in Red Blue learn Leer at level 42 and level 47 in Yellow
                incompatible.Add(43);
                incompatible.Add(123);
            }
            for (int m = 0; m < 4; m++)
            {
                if (incompatible.Contains(moves[m]))
                {
                    res[m] = new CheckMoveResult(res[m], Severity.Invalid, V363, CheckIdentifier.Move);
                }
            }
        }
Esempio n. 29
0
        /* Similar to verifyRelearnEgg but in pre relearn generation is the moves what should match the expected order but only if the pokemon is inside an egg */
        private static CheckMoveResult[] VerifyPreRelearnEggBase(PKM pkm, int[] Moves, EggInfoSource infoset)
        {
            CheckMoveResult[] res = new CheckMoveResult[4];
            var gen = pkm.GenNumber;
            // Obtain level1 moves
            var reqBase = GetRequiredBaseMoveCount(Moves, infoset);

            var em = string.Empty;

            // Check if the required amount of Base Egg Moves are present.
            for (int i = 0; i < reqBase; i++)
            {
                if (infoset.Base.Contains(Moves[i]))
                {
                    res[i] = new CheckMoveResult(MoveSource.Initial, gen, Severity.Valid, V179, CheckIdentifier.Move);
                    continue;
                }

                // mark remaining base egg moves missing
                for (int z = i; z < reqBase; z++)
                {
                    res[z] = new CheckMoveResult(MoveSource.Initial, gen, Severity.Invalid, V180, CheckIdentifier.Move);
                }

                // provide the list of suggested base moves for the last required slot
                em = string.Join(", ", GetMoveNames(infoset.Base));
                break;
            }

            int moveoffset = reqBase;
            int endSpecial = moveoffset + infoset.Special.Count;

            // Check also if the required amount of Special Egg Moves are present, ir are after base moves
            for (int i = moveoffset; i < endSpecial; i++)
            {
                if (infoset.Special.Contains(Moves[i]))
                {
                    res[i] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Valid, V333, CheckIdentifier.Move);
                    continue;
                }

                // Not in special moves, mark remaining special egg moves missing
                for (int z = i; z < endSpecial; z++)
                {
                    res[z] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Invalid, V342, CheckIdentifier.Move);
                }

                // provide the list of suggested base moves and species moves for the last required slot
                if (string.IsNullOrEmpty(em))
                {
                    em = string.Join(", ", GetMoveNames(infoset.Base));
                }
                em += ", ";
                em += string.Join(", ", GetMoveNames(infoset.Special));
                break;
            }

            if (!string.IsNullOrEmpty(em))
            {
                res[reqBase > 0 ? reqBase - 1 : 0].Comment = string.Format(Environment.NewLine + V343, em);
            }

            // Inherited moves appear after the required base moves.
            var AllowInheritedSeverity = infoset.AllowInherited ? Severity.Valid : Severity.Invalid;

            for (int i = reqBase + infoset.Special.Count; i < 4; i++)
            {
                if (Moves[i] == 0) // empty
                {
                    res[i] = new CheckMoveResult(MoveSource.None, gen, Severity.Valid, V167, CheckIdentifier.Move);
                }
                else if (infoset.Egg.Contains(Moves[i])) // inherited egg move
                {
                    res[i] = new CheckMoveResult(MoveSource.EggMove, gen, AllowInheritedSeverity, infoset.AllowInherited ? V344 : V341, CheckIdentifier.Move);
                }
                else if (infoset.LevelUp.Contains(Moves[i])) // inherited lvl moves
                {
                    res[i] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, AllowInheritedSeverity, infoset.AllowInherited ? V345 : V347, CheckIdentifier.Move);
                }
                else if (infoset.TMHM.Contains(Moves[i])) // inherited TMHM moves
                {
                    res[i] = new CheckMoveResult(MoveSource.TMHM, gen, AllowInheritedSeverity, infoset.AllowInherited ? V349 : V350, CheckIdentifier.Move);
                }
                else if (infoset.Tutor.Contains(Moves[i])) // inherited tutor moves
                {
                    res[i] = new CheckMoveResult(MoveSource.Tutor, gen, AllowInheritedSeverity, infoset.AllowInherited ? V346 : V348, CheckIdentifier.Move);
                }
                else // not inheritable, flag
                {
                    res[i] = new CheckMoveResult(MoveSource.Unknown, gen, Severity.Invalid, V340, CheckIdentifier.Move);
                }
            }

            return(res);
        }
Esempio n. 30
0
        private static void ParseShedinjaEvolveMoves(PKM pkm, IList <CheckMoveResult> res, int[] moves)
        {
            var ShedinjaEvoMovesLearned = new List <int>();

            for (int gen = Math.Min(pkm.Format, 4); gen >= 3; gen--)
            {
                var  ninjaskMoves = Legal.GetShedinjaEvolveMoves(pkm, generation: gen);
                bool native       = gen == pkm.Format;
                for (int m = 0; m < 4; m++)
                {
                    if (IsCheckValid(res[m])) // already validated
                    {
                        continue;
                    }

                    if (!ninjaskMoves.Contains(moves[m]))
                    {
                        continue;
                    }

                    res[m] = new CheckMoveResult(MoveSource.ShedinjaEvo, gen, Severity.Valid, native ? V355 : string.Format(V356, gen), CheckIdentifier.Move);
                    ShedinjaEvoMovesLearned.Add(m);
                }
            }

            if (ShedinjaEvoMovesLearned.Count == 0)
            {
                return;
            }
            if (ShedinjaEvoMovesLearned.Count > 1)
            {
                // Can't have more than one Ninjask exclusive move on Shedinja
                foreach (int m in ShedinjaEvoMovesLearned)
                {
                    res[m] = new CheckMoveResult(res[m], Severity.Invalid, V357, CheckIdentifier.Move);
                }
                return;
            }

            // Double check that the Ninjask move level isn't less than any Nincada move level
            int move   = ShedinjaEvoMovesLearned[0];
            int g      = res[move].Generation;
            int levelJ = Legal.GetShedinjaMoveLevel(291, moves[move], g);

            for (int m = 0; m < 4; m++)
            {
                if (m != move)
                {
                    continue;
                }
                if (res[m].Source != MoveSource.LevelUp)
                {
                    continue;
                }
                int levelS = Legal.GetShedinjaMoveLevel(292, moves[m], res[m].Generation);
                if (levelS > 0)
                {
                    continue;
                }

                int levelN = Legal.GetShedinjaMoveLevel(290, moves[m], res[m].Generation);
                if (levelN > levelJ)
                {
                    res[m] = new CheckMoveResult(res[m], Severity.Invalid, string.Format(V366, SpeciesStrings[290], SpeciesStrings[291]), CheckIdentifier.Move);
                }
            }
        }