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); } }
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); } }
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[] 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); }
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); } }
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; } }
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[] 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); }
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); }
/// <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); }
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); }
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); }
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); } }
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; } }
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); } } }
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); } } }
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); } } } }
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); } } } }
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); } } }
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); } } }
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); } } }
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); }
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]); } }
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]); } }
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; } } }
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 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); } } }
/* 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); }
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); } } }