using System.Linq; using static PKHeX.Core.LegalityCheckStrings; namespace PKHeX.Core { /// /// Finds matching data and relevant for a . /// public static class EncounterFinder { /// /// Iterates through all possible encounters until a sufficient match is found /// /// /// The iterator lazily finds matching encounters, then verifies secondary checks to weed out any nonexact matches. /// /// Source data to find a match for /// /// Information containing the matched encounter and any parsed checks. /// If no clean match is found, the last checked match is returned. /// If no match is found, an invalid encounter object is returned. /// public static LegalInfo FindVerifiedEncounter(PKM pkm) { LegalInfo info = new LegalInfo(pkm); var encounters = EncounterGenerator.GetEncounters(pkm, info); using (var encounter = new PeekEnumerator(encounters.GetEnumerator())) { if (!encounter.PeekIsNext()) return VerifyWithoutEncounter(pkm, info); var EncounterValidator = EncounterVerifier.GetEncounterVerifierMethod(pkm); while (encounter.MoveNext()) { info.EncounterMatch = encounter.Current; var e = EncounterValidator(pkm, info); if (!e.Valid && encounter.PeekIsNext()) { info.Reject(e); continue; } info.Parse.Add(e); if (VerifySecondaryChecks(pkm, info, encounter)) break; // passes } if (!info.PIDIVMatches) // if false, all valid PIDIV matches have already been consumed info.Parse.Add(new CheckResult(Severity.Invalid, V411, CheckIdentifier.PID)); return info; } } /// /// Checks supplementary info to see if the encounter is still valid. /// /// /// When an encounter is initially validated, only encounter-related checks are performed. /// By checking Moves, Evolution, and data, a best match encounter can be found. /// If the encounter is not valid, the method will not reject it unless another encounter is available to check. /// /// Source data to check the match for /// Information containing the matched encounter /// Peekable iterator /// Indication whether or not the encounter passes secondary checks private static bool VerifySecondaryChecks(PKM pkm, LegalInfo info, PeekEnumerator iterator) { if (pkm.Format >= 6) { info.Relearn = VerifyRelearnMoves.VerifyRelearn(pkm, info); if (info.Relearn.Any(z => !z.Valid) && iterator.PeekIsNext()) return false; } else for (int i = 0; i < 4; i++) info.Relearn[i] = new CheckResult(CheckIdentifier.RelearnMove); info.Moves = VerifyCurrentMoves.VerifyMoves(pkm, info); if (info.Moves.Any(z => !z.Valid) && iterator.PeekIsNext()) return false; var evo = EvolutionVerifier.VerifyEvolution(pkm, info); if (!evo.Valid && iterator.PeekIsNext()) return false; info.Parse.Add(evo); return true; } /// /// Returns legality info for an unmatched encounter scenario, including a hint as to what the actual match could be. /// /// Source data to check the match for /// Information containing the unmatched encounter /// Updated information pertaining to the unmatched encounter private static LegalInfo VerifyWithoutEncounter(PKM pkm, LegalInfo info) { info.EncounterMatch = new EncounterInvalid(pkm); string hint; // hint why an encounter was not found if (pkm.WasGiftEgg) hint = V359; else if (pkm.WasEventEgg) hint = V360; else if (pkm.WasEvent) hint = V78; else hint = V80; info.Parse.Add(new CheckResult(Severity.Invalid, hint, CheckIdentifier.Encounter)); info.Relearn = VerifyRelearnMoves.VerifyRelearn(pkm, info); info.Moves = VerifyCurrentMoves.VerifyMoves(pkm, info); return info; } } }