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 }
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()); }
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); }
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 } }
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, });
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 }
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)); }
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); } }
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()); }
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); }
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(); }
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(); }
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); }
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); }
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()); }
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); } } }