PKHeX/PKHeX.Core/Legality/Encounters/Verifiers/EvolutionVerifier.cs
Kurt ef3cb34387
Refactor EvoCriteria to be a struct, reduce allocation (#3483)
* Make EvolutionCriteria struct

8 bytes per object instead of 26
Unify LevelMin/LevelMax to match EncounterTemplate
bubble up precise array type for better iteration

* Inline queue operations, less allocation

* Inline some logic

* Update EvolutionChain.cs

* Improve clarity on duplicate move check

* Search reverse

For a dual stage chain, finds it first iteration rather than second.
2022-04-23 21:33:17 -07:00

59 lines
2.6 KiB
C#

using System.Linq;
using static PKHeX.Core.EvolutionRestrictions;
using static PKHeX.Core.LegalityCheckStrings;
namespace PKHeX.Core
{
/// <summary>
/// Verify Evolution Information for a matched <see cref="IEncounterable"/>
/// </summary>
public static class EvolutionVerifier
{
/// <summary>
/// Verifies Evolution scenarios of an <see cref="IEncounterable"/> for an input <see cref="PKM"/> and relevant <see cref="LegalInfo"/>.
/// </summary>
/// <param name="pkm">Source data to verify</param>
/// <param name="info">Source supporting information to verify with</param>
public static CheckResult VerifyEvolution(PKM pkm, LegalInfo info)
{
// Check if basic evolution methods are satisfiable with this encounter.
if (!IsValidEvolution(pkm, info))
return new CheckResult(Severity.Invalid, LEvoInvalid, CheckIdentifier.Evolution);
// Check if complex evolution methods are satisfiable with this encounter.
if (!IsValidEvolutionWithMove(pkm, info))
return new CheckResult(Severity.Invalid, string.Format(LMoveEvoFCombination_0, ParseSettings.SpeciesStrings[pkm.Species]), CheckIdentifier.Evolution);
return VALID;
}
private static readonly CheckResult VALID = new(CheckIdentifier.Evolution);
/// <summary>
/// Checks if the Evolution from the source <see cref="IEncounterable"/> is valid.
/// </summary>
/// <param name="pkm">Source data to verify</param>
/// <param name="info">Source supporting information to verify with</param>
/// <returns>Evolution is valid or not</returns>
private static bool IsValidEvolution(PKM pkm, LegalInfo info)
{
var chains = info.EvoChainsAllGens;
if (chains[pkm.Format].Length == 0)
return false; // Can't exist as current species
// OK if un-evolved from original encounter
int species = pkm.Species;
if (info.EncounterMatch.Species == species)
return true;
// Bigender->Fixed (non-Genderless) destination species, accounting for PID-Gender relationship
if (species == (int)Species.Vespiquen && info.Generation < 6 && (pkm.PID & 0xFF) >= 0x1F) // Combee->Vespiquen Invalid Evolution
return false;
if (chains[info.Generation].All(z => z.Species != info.EncounterMatch.Species))
return false; // Can't exist as origin species
return true;
}
}
}