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); }
private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, int[] Moves, LegalInfo info) { GameVersion[] games = (info.EncounterMatch as IGeneration)?.Generation == 1 ? Legal.GetGen1Versions(info) : Legal.GetGen2Versions(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); var emptyegg = new int[0]; foreach (GameVersion ver in games) { var VerInitialMoves = Legal.GetInitialMovesGBEncounter(G1Encounter.Species, G1Encounter.LevelMin, ver).ToArray(); if (VerInitialMoves.SequenceEqual(InitialMoves)) { return(res); } res = ParseMoves(pkm, Moves, SpecialMoves, emptyegg, emptyegg, emptyegg, new int[0], VerInitialMoves, info); if (res.All(r => r.Valid)) { return(res); } InitialMoves = VerInitialMoves; } return(res); }
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];
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];
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); }
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); }
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); }
private static CheckMoveResult[] ParseMoves(PKM pkm, MoveParseSource source, LegalInfo info) { CheckMoveResult[] res = new CheckMoveResult[4]; bool AllParsed() => res.All(r => r != null); var required = Legal.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, V167, CheckIdentifier.Move); } else if (info.EncounterMoves.Relearn.Contains(source.CurrentMoves[m])) { res[m] = new CheckMoveResult(MoveSource.Relearn, info.Generation, Severity.Valid, V172, 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, V176, CheckIdentifier.Move); } } return(res); }
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); }
private static CheckMoveResult[] ParseMoves(PKM pkm, int[] moves, int[] special, int[] lvlupegg, int[] egg, int[] NonTradebackLvlMoves, int[] eventegg, int[] initialmoves, LegalInfo info) { CheckMoveResult[] res = new CheckMoveResult[4]; var required = Legal.GetRequiredMoveCount(pkm, moves, info, initialmoves); // Check none moves and relearn moves before generation moves for (int m = 0; m < 4; m++) { if (moves[m] == 0) { res[m] = new CheckMoveResult(MoveSource.None, pkm.Format, m < required ? Severity.Fishy : Severity.Valid, V167, CheckIdentifier.Move); } else if (info.EncounterMoves.Relearn.Contains(moves[m])) { res[m] = new CheckMoveResult(MoveSource.Relearn, pkm.GenNumber, Severity.Valid, V172, CheckIdentifier.Move) { Flag = true } } ; } if (res.All(r => r != null)) { return(res); } bool MixedGen1NonTradebackGen2 = false; var Gen1MovesLearned = new List <int>(); var Gen2PreevoMovesLearned = new List <int>(); var EggMovesLearned = new List <int>(); var LvlupEggMovesLearned = new List <int>(); var EventEggMovesLearned = new List <int>(); var IsGen2Pkm = pkm.Format == 2 || pkm.VC2; var IncenseMovesLearned = new List <int>(); // 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(); } foreach (var gen in generations) { var HMLearned = new int[0]; // Check if pokemon knows HM moves from generation 3 and 4 but are not valid yet, that means it cant learn the HMs in future generations bool KnowDefogWhirlpool = false; if (gen == 4 && pkm.Format > 4) { // Copy to array the hm found or else the list will be emptied when the legal status of moves changes in the current generation HMLearned = moves.Where((m, i) => !(res[i]?.Valid ?? false) && Legal.HM_4_RemovePokeTransfer.Any(l => l == m)).Select((m, i) => i).ToArray(); // Defog and Whirlpool at the same time, also both can't be learned in future generations or else they will be valid KnowDefogWhirlpool = moves.Where((m, i) => (m == 250 || m == 432) && !(res[i]?.Valid ?? false)).Count() == 2; } else if (gen == 3 && pkm.Format > 3) { HMLearned = moves.Select((m, i) => i).Where(i => !(res[i]?.Valid ?? false) && Legal.HM_3.Any(l => l == moves[i])).ToArray(); } bool native = gen == pkm.Format; for (int m = 0; m < 4; m++) { if (res[m]?.Valid ?? false) // already validated with another generation { continue; } if (moves[m] == 0) { continue; } if (gen == 1 && initialmoves.Contains(moves[m])) { res[m] = new CheckMoveResult(MoveSource.Initial, gen, Severity.Valid, native ? V361 : string.Format(V362, gen), CheckIdentifier.Move); } else if (info.EncounterMoves.LevelUpMoves[gen].Contains(moves[m])) { res[m] = new CheckMoveResult(MoveSource.LevelUp, gen, Severity.Valid, native ? V177 : string.Format(V330, gen), CheckIdentifier.Move); } else if (info.EncounterMoves.TMHMMoves[gen].Contains(moves[m])) { res[m] = new CheckMoveResult(MoveSource.TMHM, gen, Severity.Valid, native ? V173 : string.Format(V331, gen), CheckIdentifier.Move); } else if (info.EncounterMoves.TutorMoves[gen].Contains(moves[m])) { res[m] = new CheckMoveResult(MoveSource.Tutor, gen, Severity.Valid, native ? V174 : string.Format(V332, gen), CheckIdentifier.Move); } else if (gen == pkm.GenNumber && special.Contains(moves[m])) { res[m] = new CheckMoveResult(MoveSource.Special, gen, Severity.Valid, V175, CheckIdentifier.Move); } if (res[m] == null || gen >= 3) { continue; } if (res[m].Valid && gen == 2 && NonTradebackLvlMoves.Contains(m)) { Gen2PreevoMovesLearned.Add(m); } if (res[m].Valid && gen == 1) { Gen1MovesLearned.Add(m); if (Gen2PreevoMovesLearned.Any()) { MixedGen1NonTradebackGen2 = true; } } if (res[m].Valid && gen <= 2 && pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber != gen) { pkm.TradebackStatus = TradebackType.WasTradeback; } } if (gen == generations.Last()) { // 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 (res[m]?.Valid ?? false) // Skip valid move { continue; } if (moves[m] == 0) { continue; } if (!lvlupegg.Contains(moves[m])) // Check if contains level-up egg moves from parents { continue; } if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) { res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Invalid, V334, CheckIdentifier.Move); MixedGen1NonTradebackGen2 = true; } else { res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Valid, V345, CheckIdentifier.Move); } LvlupEggMovesLearned.Add(m); if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1) { pkm.TradebackStatus = TradebackType.WasTradeback; } } // Check egg moves after all the generations and all the moves, every move that can't be learned in another source should have preference // the moves that can only be learned from egg moves should in the future check if the move combinations can be breed in gens 2 to 5 for (int m = 0; m < 4; m++) { if (res[m]?.Valid ?? false) { continue; } if (moves[m] == 0) { continue; } if (egg.Contains(moves[m])) { if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) { // To learn exclusive generation 1 moves the pokemon was tradeback, but it can't be trade to generation 1 // without removing moves above MaxMoveID_1, egg moves above MaxMoveID_1 and gen 1 moves are incompatible res[m] = new CheckMoveResult(MoveSource.EggMove, gen, Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true }; MixedGen1NonTradebackGen2 = true; } else { res[m] = new CheckMoveResult(MoveSource.EggMove, gen, Severity.Valid, V171, CheckIdentifier.Move) { Flag = true } }; EggMovesLearned.Add(m); if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1) { pkm.TradebackStatus = TradebackType.WasTradeback; } } if (!eventegg.Contains(moves[m])) { continue; } if (!egg.Contains(moves[m])) { if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1) { res[m] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true }; MixedGen1NonTradebackGen2 = true; } else { res[m] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Valid, V333, CheckIdentifier.Move) { Flag = true } }; } if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1) { pkm.TradebackStatus = TradebackType.WasTradeback; } EventEggMovesLearned.Add(m); } // 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 = EggMovesLearned.Union(LvlupEggMovesLearned).ToList(); if (RegularEggMovesLearned.Any() && EventEggMovesLearned.Any()) { // Moves that are egg moves or event egg moves but not both var IncompatibleEggMoves = RegularEggMovesLearned.Except(EventEggMovesLearned).Union(EventEggMovesLearned.Except(RegularEggMovesLearned)).ToList(); if (IncompatibleEggMoves.Any()) { foreach (int m in IncompatibleEggMoves) { if (EventEggMovesLearned.Contains(m) && !EggMovesLearned.Contains(m)) { res[m] = new CheckMoveResult(res[m], Severity.Invalid, V337, CheckIdentifier.Move); } else if (!EventEggMovesLearned.Contains(m) && EggMovesLearned.Contains(m)) { res[m] = new CheckMoveResult(res[m], Severity.Invalid, V336, CheckIdentifier.Move); } else if (!EventEggMovesLearned.Contains(m) && LvlupEggMovesLearned.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.Any() && (pkm.WasGiftEgg || pkm.WasEventEgg)) { foreach (int m in RegularEggMovesLearned) { if (EggMovesLearned.Contains(m)) { res[m] = new CheckMoveResult(res[m], Severity.Invalid, pkm.WasGiftEgg ? V377 : V341, CheckIdentifier.Move); } else if (LvlupEggMovesLearned.Contains(m)) { res[m] = new CheckMoveResult(res[m], Severity.Invalid, pkm.WasGiftEgg ? V378 : V347, CheckIdentifier.Move); } } } } if (3 <= gen && gen <= 4 && pkm.Format > gen) { // After all the moves from the generations 3 and 4, // including egg moves if is the origin generation because some hidden moves are also special egg moves in gen 3 // Check if the marked hidden moves that were invalid at the start are now marked as valid, that means // the hidden move was learned in gen 3 or 4 but was not removed when transfer to 4 or 5 if (KnowDefogWhirlpool) { int invalidCount = moves.Where((m, i) => (m == 250 || m == 432) && (res[i]?.Valid ?? false)).Count(); if (invalidCount == 2) // can't know both at the same time { for (int i = 0; i < 4; i++) // flag both moves { if (moves[i] == 250 || moves[i] == 432) { res[i] = new CheckMoveResult(res[i], Severity.Invalid, V338, CheckIdentifier.Move); } } } } for (int i = 0; i < HMLearned.Length; i++) { if (res[i]?.Valid ?? false) { res[i] = new CheckMoveResult(res[i], Severity.Invalid, string.Format(V339, gen, gen + 1), CheckIdentifier.Move); } } } // Mark the gen 1 exclusive moves as illegal because the pokemon also have Non tradeback egg moves. if (MixedGen1NonTradebackGen2) { foreach (int m in Gen1MovesLearned) { res[m] = new CheckMoveResult(res[m], Severity.Invalid, V335, CheckIdentifier.Move); } foreach (int m in Gen2PreevoMovesLearned) { res[m] = new CheckMoveResult(res[m], Severity.Invalid, V412, CheckIdentifier.Move); } } if (gen == 1 && pkm.Format == 1 && pkm.Gen1_NotTradeback) { // Check moves learned at the same level in red/blue and yellow, illegal because there is no move reminder // Only two incompatibilites and only there are no illegal combination if generation 2 or 7 are included in the analysis ParseRedYellowIncompatibleMoves(pkm, res, moves); ParseEvolutionsIncompatibleMoves(pkm, res, moves, info.EncounterMoves.TMHMMoves[1]); } if (Legal.SpeciesEvolutionWithMove.Contains(pkm.Species)) { // Pokemon that evolved by leveling up while learning a specific move // This pokemon could only have 3 moves from preevolutions that are not the move used to evolved // including special and eggs moves before realearn generations ParseEvolutionLevelupMove(pkm, res, moves, IncenseMovesLearned, info); } if (res.All(r => r != null)) { return(res); } } if (pkm.Species == 292 && info.EncounterMatch.Species != 292) { // Ignore Shedinja if the Encounter was also a Shedinja, assume null Encounter as a Nincada egg // Check Shedinja evolved moves from Ninjask after egg moves // Those moves could also be inherited egg moves ParseShedinjaEvolveMoves(pkm, res, moves); } for (int m = 0; m < 4; m++) { if (res[m] == null) { res[m] = new CheckMoveResult(MoveSource.Unknown, pkm.GenNumber, Severity.Invalid, V176, CheckIdentifier.Move); } } return(res); }
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); }