Beispiel #1
0
        private static int[] GetSuggestedMoves(PKM pkm, IReadOnlyList <IReadOnlyList <EvoCriteria> > evoChains, MoveSourceType types, IEncounterTemplate enc)
        {
            if (pkm.IsEgg && pkm.Format <= 5) // pre relearn
            {
                return(MoveList.GetBaseEggMoves(pkm, pkm.Species, 0, (GameVersion)pkm.Version, pkm.CurrentLevel));
            }

            if (types != MoveSourceType.None)
            {
                return(GetValidMoves(pkm, evoChains, types).Skip(1).ToArray()); // skip move 0
            }
            // try to give current moves
            if (enc.Generation <= 2)
            {
                var lvl = pkm.Format >= 7 ? pkm.Met_Level : pkm.CurrentLevel;
                var ver = enc.Version;
                return(MoveLevelUp.GetEncounterMoves(enc.Species, 0, lvl, ver));
            }

            if (pkm.Species == enc.Species)
            {
                return(MoveLevelUp.GetEncounterMoves(pkm.Species, pkm.Form, pkm.CurrentLevel, (GameVersion)pkm.Version));
            }

            return(GetValidMoves(pkm, evoChains, types).Skip(1).ToArray()); // skip move 0
        }
Beispiel #2
0
        private static IEnumerable <int> GetValidMoves(PKM pkm, GameVersion version, IReadOnlyList <IReadOnlyList <EvoCriteria> > evoChains, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true)
        {
            var r = new List <int> {
                0
            };

            if (Relearn && pkm.Format >= 6)
            {
                r.AddRange(pkm.RelearnMoves);
            }

            int start = pkm.GenNumber;

            if (start < 0)
            {
                start = pkm.Format; // be generous instead of returning nothing
            }
            if (pkm is IBattleVersion b)
            {
                start = b.GetMinGeneration();
            }

            for (int generation = start; generation <= pkm.Format; generation++)
            {
                var chain = evoChains[generation];
                if (chain.Count == 0)
                {
                    continue;
                }
                r.AddRange(MoveList.GetValidMoves(pkm, version, chain, generation, minLvLG1: minLvLG1, minLvLG2: minLvLG2, LVL: LVL, Relearn: false, Tutor: Tutor, Machine: Machine, MoveReminder: MoveReminder, RemoveTransferHM: RemoveTransferHM));
            }

            return(r.Distinct());
        }
Beispiel #3
0
        private static IEnumerable <int> GetMovesForGeneration(PKM pk, IReadOnlyList <EvoCriteria> dl, int generation)
        {
            IEnumerable <int> moves = MoveList.GetValidMoves(pk, dl, generation);

            if (pk.Format >= 8)
            {
                // Shared Egg Moves via daycare
                // Any egg move can be obtained
                var evo    = dl[dl.Count - 1];
                var shared = MoveEgg.GetEggMoves(8, evo.Species, evo.Form, GameVersion.SW);
                if (shared.Length != 0)
                {
                    moves = moves.Concat(shared);
                }
            }
            if (pk.Species == (int)Species.Shedinja)
            {
                // Leveling up Nincada in Gen3/4 levels up, evolves to Ninjask, applies moves for Ninjask, then spawns Shedinja with the current moveset.
                // Future games spawn the Shedinja before doing Ninjask moves, so this is a special case.
                // Can't get more than the evolved-at level move; >=2 special moves will get caught by the legality checker later.
                if (generation == 3)
                {
                    return(moves.Concat(Legal.LevelUpE[(int)Species.Ninjask].GetMoves(100, 20)));
                }
                if (generation == 4)
                {
                    return(moves.Concat(Legal.LevelUpPt[(int)Species.Ninjask].GetMoves(100, 20)));
                }
            }
            return(moves);
        }
Beispiel #4
0
        public EggInfoSource(PKM pkm, EncounterEgg e)
        {
            // Eggs with special moves cannot inherit levelup moves as the current moves are predefined.
            AllowInherited = e.Species != 489 && e.Species != 490;

            // Level up moves can only be inherited if ditto is not the mother.
            bool AllowLevelUp = Legal.GetCanInheritMoves(e.Species);

            Base = MoveList.GetBaseEggMoves(pkm, e.Species, e.Form, e.Version, e.Level);

            Egg     = MoveEgg.GetEggMoves(pkm, e.Species, e.Form, e.Version);
            LevelUp = AllowLevelUp
                ? MoveList.GetBaseEggMoves(pkm, e.Species, e.Form, e.Version, 100).Except(Base).ToList()
                : (IReadOnlyList <int>)Array.Empty <int>();
            Tutor = e.Version == GameVersion.C
                ? MoveTutor.GetTutorMoves(pkm, e.Species, 0, false, 2).ToList()
                : (IReadOnlyList <int>)Array.Empty <int>();

            // Only TM/HM moves from the source game of the egg, not any other games from the same generation
            TMHM = MoveTechnicalMachine.GetTMHM(pkm, pkm.Species, pkm.AltForm, e.Generation, e.Version).ToList();

            // Non-Base moves that can magically appear in the regular movepool
            bool volt = (e.Generation > 3 || e.Version == GameVersion.E) && Legal.LightBall.Contains(pkm.Species);

            if (volt)
            {
                Egg = Egg.ToList(); // array->list
                Egg.Add(344);       // Volt Tackle
            }
        }
Beispiel #5
0
        private static IEnumerable <int> GetValidMoves(PKM pkm, GameVersion version, IReadOnlyList <IReadOnlyList <EvoCriteria> > evoChains, int minLvLG1 = 1, int minLvLG2 = 1, MoveSourceType types = MoveSourceType.Reminder, bool RemoveTransferHM = true)
        {
            var r = new List <int> {
                0
            };

            if (types.HasFlagFast(MoveSourceType.RelearnMoves) && pkm.Format >= 6)
            {
                r.AddRange(pkm.RelearnMoves);
            }

            int start = pkm.Generation;

            if (start < 0)
            {
                start = pkm.Format; // be generous instead of returning nothing
            }
            if (pkm is IBattleVersion b)
            {
                start = Math.Max(0, b.GetMinGeneration());
            }

            for (int generation = start; generation <= pkm.Format; generation++)
            {
                var chain = evoChains[generation];
                if (chain.Count == 0)
                {
                    continue;
                }
                r.AddRange(MoveList.GetValidMoves(pkm, version, chain, generation, minLvLG1: minLvLG1, minLvLG2: minLvLG2, types: types, RemoveTransferHM: RemoveTransferHM));
            }

            return(r.Distinct());
        }
        private static IEnumerable <int> GetMovesForGeneration(PKM pk, IReadOnlyList <EvoCriteria> chain, int generation)
        {
            IEnumerable <int> moves = MoveList.GetValidMoves(pk, chain, generation);

            if (generation <= 2)
            {
                moves = moves.Concat(MoveList.GetValidMoves(pk, chain, generation, MoveSourceType.LevelUp));
            }
            if (pk.Format >= 8)
            {
                // Shared Egg Moves via daycare
                // Any egg move can be obtained
                moves = moves.Concat(MoveEgg.GetSharedEggMoves(pk, generation));

                // TR moves -- default logic checks the TR flags, so we need to add all possible ones here.
                if (!(pk.BDSP || pk.LA))
                {
                    moves = moves.Concat(MoveTechnicalMachine.GetAllPossibleRecords(pk.Species, pk.Form));
                }
            }
            if (pk.Species == (int)Species.Shedinja)
            {
                // Leveling up Nincada in Gen3/4 levels up, evolves to Ninjask, applies moves for Ninjask, then spawns Shedinja with the current moveset.
                // Future games spawn the Shedinja before doing Ninjask moves, so this is a special case.
                // Can't get more than the evolved-at level move; >=2 special moves will get caught by the legality checker later.
                return(generation switch
                {
                    3 => moves.Concat(Legal.LevelUpE [(int)Species.Ninjask].GetMoves(100, 20)),
                    4 => moves.Concat(Legal.LevelUpPt[(int)Species.Ninjask].GetMoves(100, 20)),
                    _ => moves,
                });
Beispiel #7
0
        internal static int[] GetSuggestedMoves(PKM pkm, IReadOnlyList <EvoCriteria>[] evoChains, bool tm, bool tutor, bool reminder, IEncounterable enc)
        {
            if (pkm.IsEgg && pkm.Format <= 5) // pre relearn
            {
                return(MoveList.GetBaseEggMoves(pkm, pkm.Species, 0, (GameVersion)pkm.Version, pkm.CurrentLevel));
            }

            if (!tm && !tutor && !reminder)
            {
                // try to give current moves
                if (enc.Generation <= 2)
                {
                    var lvl = pkm.Format >= 7 ? pkm.Met_Level : pkm.CurrentLevel;
                    var ver = enc.Version;
                    return(MoveLevelUp.GetEncounterMoves(enc.Species, 0, lvl, ver));
                }

                if (pkm.Species == enc.Species)
                {
                    return(MoveLevelUp.GetEncounterMoves(pkm.Species, pkm.AltForm, pkm.CurrentLevel, (GameVersion)pkm.Version));
                }
            }

            return(GetValidMoves(pkm, evoChains, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray()); // skip move 0
        }
Beispiel #8
0
        private static CheckMoveResult[] ParseMovesWasEggPreRelearn(PKM pkm, IReadOnlyList <int> currentMoves, LegalInfo info, EncounterEgg e)
        {
            // Level up moves could not be inherited if Ditto is parent,
            // that means genderless species and male only species (except Nidoran-M and Volbeat; they breed with Nidoran-F and Illumise) could not have level up moves as an egg
            var pi           = pkm.PersonalInfo;
            var AllowLevelUp = !pi.Genderless && !(pi.OnlyMale && Breeding.MixedGenderBreeding.Contains(e.Species));
            int BaseLevel    = AllowLevelUp ? 100 : e.LevelMin;
            var LevelUp      = MoveList.GetBaseEggMoves(pkm, e.Species, e.Form, e.Version, BaseLevel);

            var TradebackPreevo      = pkm.Format == 2 && e.Species > 151;
            var NonTradebackLvlMoves = TradebackPreevo
                ? MoveList.GetExclusivePreEvolutionMoves(pkm, e.Species, info.EvoChainsAllGens[2], 2, e.Version).Where(m => m > Legal.MaxMoveID_1).ToArray()
                : Array.Empty <int>();

            var Egg = MoveEgg.GetEggMoves(pkm.PersonalInfo, e.Species, e.Form, e.Version, e.Generation);

            if (info.Generation < 3 && pkm.Format >= 7 && pkm.VC1)
            {
                Egg = Array.FindAll(Egg, m => m <= Legal.MaxMoveID_1);
            }

            var specialMoves = e.CanHaveVoltTackle ? new[] { (int)Move.VoltTackle } : Array.Empty <int>(); // Volt Tackle for bred Pichu line

            var source = new MoveParseSource
            {
                CurrentMoves             = currentMoves,
                SpecialSource            = specialMoves,
                NonTradeBackLevelUpMoves = NonTradebackLvlMoves,

                EggLevelUpSource = LevelUp,
                EggMoveSource    = Egg,
            };

            return(ParseMoves(pkm, source, info));
        }
Beispiel #9
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) || (Legal.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(102);
                break;

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

            case (int)Species.Lickilicky:     // Lickilicky (Lickitung with Rollout)
                ValidMoves.Add(205);
                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(246);
                break;

            case (int)Species.Sylveon:     // 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 (int)Species.Tsareena:     // Tsareena (Steenee with Stomp)
                ValidMoves.Add(023);
                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]), Move);
            }
        }
Beispiel #10
0
        private static IEnumerable <int> AllSuggestedRelearnMoves(this LegalityAnalysis analysis)
        {
            if (!analysis.Parsed)
            {
                return(new int[4]);
            }
            var pkm = analysis.pkm;
            var enc = analysis.EncounterMatch;

            return(MoveList.GetValidRelearn(pkm, enc.Species, enc.Form, (GameVersion)pkm.Version).ToArray());
        }
Beispiel #11
0
        public ValidEncounterMoves(PKM pkm, LevelUpRestriction restrict, IEncounterable encounter)
        {
            var level = MoveList.GetValidMovesAllGens(pkm, restrict.EvolutionChains, minLvLG1: restrict.MinimumLevelGen1, minLvLG2: restrict.MinimumLevelGen2, Tutor: false, Machine: false, RemoveTransferHM: false);

            if (level[encounter.Generation] is List <int> x)
            {
                AddEdgeCaseMoves(x, encounter, pkm);
            }

            LevelUpMoves = level;
            TMHMMoves    = MoveList.GetValidMovesAllGens(pkm, restrict.EvolutionChains, LVL: false, Tutor: false, MoveReminder: false, RemoveTransferHM: false);
            TutorMoves   = MoveList.GetValidMovesAllGens(pkm, restrict.EvolutionChains, LVL: false, Machine: false, MoveReminder: false, RemoveTransferHM: false);
        }
Beispiel #12
0
        private static void UpdateGen2LevelUpMoves(PKM pkm, ValidEncounterMoves EncounterMoves, int defaultLvlG2, int generation, LegalInfo info)
        {
            if (generation >= 3)
            {
                return;
            }
            var lvlG2 = info.EncounterMatch.LevelMin + 1;

            if (lvlG2 == defaultLvlG2)
            {
                return;
            }
            EncounterMoves.LevelUpMoves[2] = MoveList.GetValidMoves(pkm, info.EvoChainsAllGens[2], generation: 2, minLvLG2: defaultLvlG2, LVL: true, Tutor: false, Machine: false, MoveReminder: false).ToList();
        }
Beispiel #13
0
        private static void UpdateGen2LevelUpMoves(PKM pkm, ValidEncounterMoves EncounterMoves, int defaultLvlG2, int generation, LegalInfo info)
        {
            if (generation >= 3)
            {
                return;
            }
            var lvlG2 = info.EncounterMatch.LevelMin + 1;

            if (lvlG2 == defaultLvlG2)
            {
                return;
            }
            EncounterMoves.LevelUpMoves[2] = MoveList.GetValidMoves(pkm, info.EvoChainsAllGens[2], generation: 2, minLvLG2: defaultLvlG2, types: MoveSourceType.LevelUp).ToList();
        }
Beispiel #14
0
        public ValidEncounterMoves(PKM pkm, IEncounterTemplate encounter, IReadOnlyList <EvoCriteria>[] chains)
        {
            var level = MoveList.GetValidMovesAllGens(pkm, chains, types: MoveSourceType.Encounter, RemoveTransferHM: false);

            int gen = encounter.Generation;

            if ((uint)gen < level.Length && level[gen] is List <int> x)
            {
                AddEdgeCaseMoves(x, encounter, pkm);
            }

            LevelUpMoves = level;
            TMHMMoves    = MoveList.GetValidMovesAllGens(pkm, chains, types: MoveSourceType.AllMachines);
            TutorMoves   = MoveList.GetValidMovesAllGens(pkm, chains, types: MoveSourceType.AllTutors);
        }
Beispiel #15
0
        public ValidEncounterMoves(PKM pkm, LevelUpRestriction restrict, IEncounterable encounter)
        {
            var level = MoveList.GetValidMovesAllGens(pkm, restrict.EvolutionChains, minLvLG1: restrict.MinimumLevelGen1, minLvLG2: restrict.MinimumLevelGen2, types: MoveSourceType.Encounter, RemoveTransferHM: false);

            int gen = encounter.Generation;

            if ((uint)gen < level.Length && level[gen] is List <int> x)
            {
                AddEdgeCaseMoves(x, encounter, pkm);
            }

            LevelUpMoves = level;
            TMHMMoves    = MoveList.GetValidMovesAllGens(pkm, restrict.EvolutionChains, types: MoveSourceType.AllMachines);
            TutorMoves   = MoveList.GetValidMovesAllGens(pkm, restrict.EvolutionChains, types: MoveSourceType.AllTutors);
        }
Beispiel #16
0
        private int[] GetCurrentEggMoves(PKM pk, GameVersion version)
        {
            var moves = MoveEgg.GetEggMoves(pk, Species, Form, version);

            if (moves.Length == 0)
            {
                return(MoveLevelUp.GetEncounterMoves(pk, Level, version));
            }
            if (moves.Length >= 4 || pk.Format < 6)
            {
                return(moves);
            }

            // Sprinkle in some default level up moves
            var lvl = MoveList.GetBaseEggMoves(pk, Species, Form, version, Level);

            return(lvl.Concat(moves).ToArray());
        }
Beispiel #17
0
        private static void ParseShedinjaEvolveMoves(PKM pkm, IList <CheckMoveResult> res, IReadOnlyList <int> currentMoves, IReadOnlyList <IReadOnlyList <EvoCriteria> > evos)
        {
            var ShedinjaEvoMovesLearned = new List <int>();
            var format = pkm.Format;

            for (int gen = Math.Min(format, 4); gen >= 3; gen--)
            {
                if (evos[gen].Count != 2)
                {
                    continue; // Was not evolved in this generation
                }
                if (gen == 4 && pkm.Ball != 4)
                {
                    continue; // Was definitively evolved in Gen3
                }
                var  maxLevel     = pkm.CurrentLevel;
                var  ninjaskMoves = MoveList.GetShedinjaEvolveMoves(pkm, gen, maxLevel);
                bool native       = gen == format;
                for (int m = 0; m < 4; m++)
                {
                    if (IsCheckValid(res[m])) // already validated
                    {
                        continue;
                    }

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

                    var msg = native ? LMoveNincadaEvo : string.Format(LMoveNincadaEvoF_0, gen);
                    res[m] = new CheckMoveResult(ShedinjaEvo, gen, Valid, msg, 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], Invalid, LMoveNincada, 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 = MoveList.GetShedinjaMoveLevel((int)Species.Ninjask, currentMoves[move], g);

            for (int m = 0; m < 4; m++)
            {
                if (m != move)
                {
                    continue;
                }
                if (res[m].Source != LevelUp)
                {
                    continue;
                }
                int levelS = MoveList.GetShedinjaMoveLevel((int)Species.Shedinja, currentMoves[m], res[m].Generation);
                if (levelS > 0)
                {
                    continue;
                }

                int levelN = MoveList.GetShedinjaMoveLevel((int)Species.Nincada, currentMoves[m], res[m].Generation);
                if (levelN > levelJ)
                {
                    res[m] = new CheckMoveResult(res[m], Invalid, string.Format(LMoveEvoFHigher, SpeciesStrings[(int)Species.Nincada], SpeciesStrings[(int)Species.Ninjask]), Move);
                }
            }
        }