private static IEnumerable <IEncounterable> GenerateFilteredEncounters12(PKM pkm) { bool crystal = (pkm.Format == 2 && pkm.Met_Location != 0) || (pkm.Format >= 7 && pkm.OT_Gender == 1); bool kadabra = pkm.Species == 64 && pkm is PK1 pk1 && (pk1.Catch_Rate == PersonalTable.RB[64].CatchRate || pk1.Catch_Rate == PersonalTable.Y[64].CatchRate); // catch rate outsider, return gen1 first always // iterate over both games, consuming from one list at a time until the other list has higher priority encounters var get1 = GenerateRawEncounters1(pkm, crystal); var get2 = GenerateRawEncounters2(pkm, crystal); var g1i = new PeekEnumerator <IEncounterable>(get1); var g2i = new PeekEnumerator <IEncounterable>(get2); var deferred = new List <IEncounterable>(); while (g2i.PeekIsNext() || g1i.PeekIsNext()) { var move = GetPreferredGBIterator(pkm, g1i, g2i); var obj = move.Peek(); int gen = obj is IGeneration g ? g.Generation : 2; // only eggs don't implement interface if (gen == 1 && (pkm.Korean || (obj is EncounterTrade t && !IsEncounterTrade1Valid(pkm, t)))) { deferred.Add(obj); }
/// <summary> /// Checks supplementary info to see if the encounter is still valid. /// </summary> /// <remarks> /// When an encounter is initially validated, only encounter-related checks are performed. /// By checking Moves, Evolution, and <see cref="PIDIV"/> 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. /// </remarks> /// <param name="pkm">Source data to check the match for</param> /// <param name="info">Information containing the matched encounter</param> /// <param name="iterator">Peekable iterator </param> /// <returns>Indication whether or not the encounter passes secondary checks</returns> private static bool VerifySecondaryChecks(PKM pkm, LegalInfo info, PeekEnumerator <IEncounterable> 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); }
/// <summary> /// Iterates through all possible encounters until a sufficient match is found /// </summary> /// <remarks> /// The iterator lazily finds matching encounters, then verifies secondary checks to weed out any nonexact matches. /// </remarks> /// <param name="pkm">Source data to find a match for</param> /// <param name="info">Object to store matched encounter info</param> /// <returns> /// 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. /// </returns> public static void FindVerifiedEncounter(PKM pkm, LegalInfo info) { var encounters = EncounterGenerator.GetEncounters(pkm, info); using var encounter = new PeekEnumerator <IEncounterable>(encounters); if (!encounter.PeekIsNext()) { VerifyWithoutEncounter(pkm, info); return; } var first = encounter.Current; var EncounterValidator = EncounterVerifier.GetEncounterVerifierMethod(first.Generation); while (encounter.MoveNext()) { var enc = encounter.Current; // Check for basic compatibility. var e = EncounterValidator(pkm, enc); if (!e.Valid && encounter.PeekIsNext()) { info.Reject(e); continue; } // Looks like we might have a good enough match. Check if this is really a good match. info.EncounterMatch = enc; info.Parse.Add(e); if (!VerifySecondaryChecks(pkm, info, encounter)) { continue; } // Sanity Check -- Some secondary checks might not be as thorough as the partial-match leak-through checks done by the encounter. if (enc is not IEncounterMatch mx) { break; } var match = mx.GetMatchRating(pkm); if (match != EncounterMatchRating.PartialMatch) { break; } // Reaching here implies the encounter wasn't valid. Try stepping to the next encounter. if (encounter.PeekIsNext()) { continue; } // We ran out of possible encounters without finding a suitable match; add a message indicating that the encounter is not a complete match. info.Parse.Add(new CheckResult(Severity.Invalid, LEncInvalid, CheckIdentifier.Encounter)); break; } if (!info.FrameMatches && info.EncounterMatch is EncounterSlot { Version : not GameVersion.CXD }) // if false, all valid RNG frame matches have already been consumed
/// <summary> /// Iterates through all possible encounters until a sufficient match is found /// </summary> /// <remarks> /// The iterator lazily finds matching encounters, then verifies secondary checks to weed out any nonexact matches. /// </remarks> /// <param name="pkm">Source data to find a match for</param> /// <returns> /// 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. /// </returns> public static LegalInfo FindVerifiedEncounter(PKM pkm) { LegalInfo info = new LegalInfo(pkm); var encounters = EncounterGenerator.GetEncounters(pkm, info); using (var encounter = new PeekEnumerator <IEncounterable>(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 } } return(info); } }
/// <summary> /// Iterates through all possible encounters until a sufficient match is found /// </summary> /// <remarks> /// The iterator lazily finds matching encounters, then verifies secondary checks to weed out any nonexact matches. /// </remarks> /// <param name="pkm">Source data to find a match for</param> /// <returns> /// 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. /// </returns> public static LegalInfo FindVerifiedEncounter(PKM pkm) { var info = new LegalInfo(pkm); var encounters = EncounterGenerator.GetEncounters(pkm, info); using var encounter = new PeekEnumerator <IEncounterable>(encounters); 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.FrameMatches && info.EncounterMatch is EncounterSlot { Version : not GameVersion.CXD }) // if false, all valid RNG frame matches have already been consumed
/// <summary> /// Iterates through all possible encounters until a sufficient match is found /// </summary> /// <remarks> /// The iterator lazily finds matching encounters, then verifies secondary checks to weed out any nonexact matches. /// </remarks> /// <param name="pkm">Source data to find a match for</param> /// <param name="info">Object to store matched encounter info</param> /// <returns> /// 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. /// </returns> public static void FindVerifiedEncounter(PKM pkm, LegalInfo info) { var encounters = EncounterGenerator.GetEncounters(pkm, info); using var encounter = new PeekEnumerator <IEncounterable>(encounters); if (!encounter.PeekIsNext()) { VerifyWithoutEncounter(pkm, info); return; } 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)) { continue; } // Sanity Check -- Some secondary checks might not be as thorough as the partial-match leak-through checks done by the encounter. if (info.EncounterMatch is not IEncounterMatch mx) { break; } var match = mx.GetMatchRating(pkm); if (match != EncounterMatchRating.PartialMatch) { break; } if (encounter.PeekIsNext()) { continue; } info.Parse.Add(new CheckResult(Severity.Invalid, LEncInvalid, CheckIdentifier.Encounter)); break; } if (!info.FrameMatches && info.EncounterMatch is EncounterSlot { Version : not GameVersion.CXD }) // if false, all valid RNG frame matches have already been consumed
/// <summary> /// Gets the preferred iterator from a pair of <see cref="GBEncounterData"/> iterators based on the highest value <see cref="GBEncounterData.Type"/>. /// </summary> /// <param name="g1i">Generation 1 Iterator</param> /// <param name="g2i">Generation 2 Iterator</param> /// <returns>Preferred iterator </returns> private static PeekEnumerator <GBEncounterData> GetPreferredGBIterator(PeekEnumerator <GBEncounterData> g1i, PeekEnumerator <GBEncounterData> g2i) { if (!g1i.PeekIsNext()) { return(g2i); } if (!g2i.PeekIsNext()) { return(g1i); } return(g1i.Peek().Type > g2i.Peek().Type ? g1i : g2i); }
private static IEnumerable <GBEncounterData> GenerateFilteredEncounters(PKM pkm) { bool crystal = pkm.Format == 2 && pkm.Met_Location != 0 || pkm.Format >= 7 && pkm.OT_Gender == 1; var g1i = new PeekEnumerator <GBEncounterData>(get1()); var g2i = new PeekEnumerator <GBEncounterData>(get2()); var deferred = new List <GBEncounterData>(); while (g2i.PeekIsNext() || g1i.PeekIsNext()) { var move = GetPreferredGBIterator(g1i, g2i); var obj = move.Peek(); if (obj.Generation == 1 && obj.Encounter is EncounterTrade && !IsEncounterTrade1Valid(pkm)) { deferred.Add(obj); } else { yield return(obj); } pkm.WasEgg = false; move.MoveNext(); } foreach (var z in deferred) { yield return(z); } IEnumerable <GBEncounterData> get1() { if (!pkm.Gen2_NotTradeback && !crystal) { foreach (var z in GenerateRawEncounters12(pkm, GameVersion.RBY)) { yield return(z); } } } IEnumerable <GBEncounterData> get2() { if (!pkm.Gen1_NotTradeback) { foreach (var z in GenerateRawEncounters12(pkm, crystal ? GameVersion.C : GameVersion.GSC)) { yield return(z); } } } }
private static IEnumerable <GBEncounterData> GenerateFilteredEncounters(PKM pkm) { bool crystal = pkm.Format == 2 && pkm.Met_Location != 0 || pkm.Format >= 7 && pkm.OT_Gender == 1; var g1i = new PeekEnumerator <GBEncounterData>(get1()); var g2i = new PeekEnumerator <GBEncounterData>(get2()); var deferred = new List <GBEncounterData>(); while (g2i.PeekIsNext() || g1i.PeekIsNext()) { var move = GetPreferredGBIterator(g1i, g2i); var obj = move.Peek(); if ((obj.Generation == 1 && (pkm.Korean || (obj.Encounter is EncounterTrade && !IsEncounterTrade1Valid(pkm)))) || (obj.Generation == 2 && (pkm.Korean && (obj.Encounter is IVersion v && v.Version == GameVersion.C)))) { deferred.Add(obj); }
private static IEnumerable <IEncounterable> GenerateFilteredEncounters12Both(PKM pkm) { // Iterate over both games, consuming from one list at a time until the other list has higher priority encounters // Buffer the encounters so that we can consume each iterator separately var get1 = GenerateRawEncounters12(pkm, GameVersion.RBY); var get2 = GenerateRawEncounters12(pkm, GameVersion.GSC); using var g1i = new PeekEnumerator <IEncounterable>(get1); using var g2i = new PeekEnumerator <IEncounterable>(get2); while (g2i.PeekIsNext() || g1i.PeekIsNext()) { var iter = PickPreferredIterator(pkm, g1i, g2i); yield return(iter.Current); iter.MoveNext(); } }
/// <summary> /// Iterates through all possible encounters until a sufficient match is found /// </summary> /// <remarks> /// The iterator lazily finds matching encounters, then verifies secondary checks to weed out any nonexact matches. /// </remarks> /// <param name="pkm">Source data to find a match for</param> /// <returns> /// 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. /// </returns> public static LegalInfo FindVerifiedEncounter(PKM pkm) { LegalInfo info = new LegalInfo(pkm); var encounters = EncounterGenerator.GetEncounters(pkm, info); using (var encounter = new PeekEnumerator <IEncounterable>(encounters)) { 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.FrameMatches && info.EncounterMatch is EncounterSlot && pkm.Version != (int)GameVersion.CXD) // if false, all valid RNG frame matches have already been consumed { info.Parse.Add(new CheckResult(Severity.Fishy, LEncConditionBadRNGFrame, CheckIdentifier.PID)); // todo for further confirmation } if (!info.PIDIVMatches) // if false, all valid PIDIV matches have already been consumed { info.Parse.Add(new CheckResult(Severity.Invalid, LPIDTypeMismatch, CheckIdentifier.PID)); } return(info); } }
/// <summary> /// Iterates through all possible encounters until a sufficient match is found /// </summary> /// <remarks> /// The iterator lazily finds matching encounters, then verifies secondary checks to weed out any nonexact matches. /// </remarks> /// <param name="pkm">Source data to find a match for</param> /// <returns> /// 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. /// </returns> public static LegalInfo FindVerifiedEncounter(PKM pkm) { LegalInfo info = new LegalInfo(pkm); var encounters = EncounterGenerator.GetEncounters(pkm, info); using (var encounter = new PeekEnumerator <IEncounterable>(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); } }
private static PeekEnumerator <IEncounterable> PickPreferredIterator(PKM pkm, PeekEnumerator <IEncounterable> g1i, PeekEnumerator <IEncounterable> g2i) { if (!g1i.PeekIsNext()) { return(g2i); } if (!g2i.PeekIsNext()) { return(g1i); } var p1 = GetGBEncounterPriority(pkm, g1i.Current); var p2 = GetGBEncounterPriority(pkm, g2i.Current); return(p1 > p2 ? g1i : g2i); }