PKHeX/PKHeX.Core/Legality/Evolutions/EvolutionGroup/EvolutionGroup2.cs
Kurt dcc0e79435
Evotree: Evolution Traversal Enhancements (#3936)
Like move validation, evolutions are the earliest thing we wish to traverse when determining what encounters may have originated the current Pokémon. To determine the permitted species-form-levels a Pokémon could originate with, we must devolve a Pokémon by traveling down-generation to origin. Once we have an encounter, we can then evolve it to the current species, traversing upwards from origin to the current format.
2023-07-05 21:14:09 -07:00

75 lines
2.8 KiB
C#

using System;
namespace PKHeX.Core;
public sealed class EvolutionGroup2 : IEvolutionGroup
{
public static readonly EvolutionGroup2 Instance = new();
private static readonly EvolutionTree Tree = EvolutionTree.Evolves2;
private const int Generation = 2;
private static PersonalTable2 Personal => PersonalTable.C;
public IEvolutionGroup? GetNext(PKM pk, EvolutionOrigin enc) => pk.Format > Generation ? EvolutionGroup7.Instance : null;
public IEvolutionGroup? GetPrevious(PKM pk, EvolutionOrigin enc) => pk.Format != 1 ? EvolutionGroup1.Instance : null;
public void DiscardForOrigin(Span<EvoCriteria> result, PKM pk) => EvolutionUtil.Discard(result, Personal);
public int Devolve(Span<EvoCriteria> result, PKM pk, EvolutionOrigin enc)
{
if (pk.Format > Generation && !enc.SkipChecks)
{
var max = pk.Met_Level;
EvolutionUtil.UpdateCeiling(result, max);
enc = enc with { LevelMin = 2, LevelMax = (byte)max };
}
int present = 1;
for (int i = 1; i < result.Length; i++)
{
var prev = result[i - 1];
if (!TryDevolve(prev, pk, prev.LevelMax, enc.LevelMin, enc.SkipChecks, out var evo))
continue;
ref var reference = ref result[i];
if (evo.IsBetterDevolution(reference))
reference = evo;
present++;
}
return present;
}
public bool TryDevolve(ISpeciesForm head, PKM pk, byte currentMaxLevel, byte levelMin, bool skipChecks, out EvoCriteria result)
{
return Tree.Reverse.TryDevolve(head, pk, currentMaxLevel, levelMin, skipChecks, out result);
}
public int Evolve(Span<EvoCriteria> result, PKM pk, EvolutionOrigin enc, EvolutionHistory history)
{
if (pk.Format > Generation)
enc = enc with { LevelMax = (byte)pk.Met_Level };
int present = 1;
for (int i = result.Length - 1; i >= 1; i--)
{
ref var dest = ref result[i - 1];
var devolved = result[i];
if (!TryEvolve(devolved, dest, pk, enc.LevelMax, devolved.LevelMin, enc.SkipChecks, out var evo))
{
if (dest.Method == EvoCriteria.SentinelNotReached)
break; // Don't continue for higher evolutions.
continue;
}
if (evo.IsBetterEvolution(dest))
dest = evo;
present++;
}
history.Gen2 = EvolutionUtil.SetHistory(result, Personal);
return present;
}
public bool TryEvolve(ISpeciesForm head, ISpeciesForm next, PKM pk, byte currentMaxLevel, byte levelMin, bool skipChecks, out EvoCriteria result)
{
return Tree.Forward.TryEvolve(head, next, pk, currentMaxLevel, levelMin, skipChecks, out result);
}
}