PKHeX/PKHeX.Core/Legality/Evolutions/Reversal/EvolutionReversePersonal.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

69 lines
2.3 KiB
C#

using System;
using System.Collections.Generic;
namespace PKHeX.Core;
public sealed class EvolutionReversePersonal : IEvolutionReverse
{
public IEvolutionLookup Lineage { get; }
public EvolutionReversePersonal(EvolutionMethod[][] entries, IPersonalTable t)
{
Lineage = GetLineage(t, entries);
}
private static EvolutionReverseLookup GetLineage(IPersonalTable t, EvolutionMethod[][] entries)
{
var maxSpecies = t.MaxSpeciesID;
var lineage = new EvolutionReverseLookup(maxSpecies);
for (ushort sSpecies = 1; sSpecies <= maxSpecies; sSpecies++)
{
var fc = t[sSpecies].FormCount;
for (byte sForm = 0; sForm < fc; sForm++)
{
var index = t.GetFormIndex(sSpecies, sForm);
foreach (var evo in entries[index])
{
var dSpecies = evo.Species;
if (dSpecies == 0)
break;
var dForm = evo.GetDestinationForm(sForm);
var link = new EvolutionLink(evo, sSpecies, sForm);
lineage.Register(link, dSpecies, dForm);
}
}
}
return lineage;
}
public EvolutionNode GetReverse(ushort species, byte form) => Lineage[species, form];
public IEnumerable<(ushort Species, byte Form)> GetPreEvolutions(ushort species, byte form)
{
var node = Lineage[species, form];
// No convergent evolutions; first method is enough.
var s = node.First;
if (s.Species == 0)
yield break;
var preEvolutions = GetPreEvolutions(s.Species, s.Form);
foreach (var preEvo in preEvolutions)
yield return preEvo;
yield return (s.Species, s.Form);
}
public int Devolve(Span<EvoCriteria> result, ushort species, byte form, PKM pk, byte levelMin, byte levelMax, ushort stopSpecies,
bool skipChecks)
{
return Lineage.Devolve(result, species, form, pk, levelMin, levelMax, stopSpecies, skipChecks);
}
public bool TryDevolve(ISpeciesForm head, PKM pk, byte currentMaxLevel, byte levelMin, bool skipChecks, out EvoCriteria result)
{
var node = Lineage[head.Species, head.Form];
return node.TryDevolve(pk, currentMaxLevel, levelMin, skipChecks, out result);
}
}