Skip to content

Commit

Permalink
Refactor level-evolution checks slightly
Browse files Browse the repository at this point in the history
Allows evolution met level check to be skipped
Adds minimum level constraint for evolution chain generating

Closes #1430

also adds deferral to the gen3 encounter generator as encounterstatic
gifts can collide with wild encounters when transferred
  • Loading branch information
kwsch committed Aug 29, 2017
1 parent 41482af commit 072f1ba
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 26 deletions.
29 changes: 16 additions & 13 deletions PKHeX.Core/Legality/Core.cs
Expand Up @@ -976,7 +976,7 @@ internal static IEnumerable<int> GetLineage(PKM pkm)
return new[] {pkm.Species};

var table = EvolutionTree.GetEvolutionTree(pkm.Format);
var lineage = table.GetValidPreEvolutions(pkm, pkm.CurrentLevel);
var lineage = table.GetValidPreEvolutions(pkm, maxLevel: pkm.CurrentLevel);
return lineage.Select(evolution => evolution.Species);
}
internal static int[] GetWildBalls(PKM pkm)
Expand Down Expand Up @@ -1106,7 +1106,7 @@ internal static bool IsTradeEvolved(PKM pkm)
return false;

var table = EvolutionTree.GetEvolutionTree(pkm.Format);
var lineage = table.GetValidPreEvolutions(pkm, 100, skipChecks:true);
var lineage = table.GetValidPreEvolutions(pkm, maxLevel: 100, skipChecks:true);
return lineage.Any(evolution => EvolutionMethod.TradeMethods.Any(method => method == evolution.Flag)); // Trade Evolutions
}
internal static bool IsEvolutionValid(PKM pkm, int minSpecies = -1)
Expand Down Expand Up @@ -1190,18 +1190,21 @@ internal static bool IsFormChangeable(PKM pkm, int species)
return false;
}

public static int GetLowestLevel(PKM pkm, int refSpecies = -1)
public static int GetLowestLevel(PKM pkm, int startLevel)
{
if (refSpecies == -1)
refSpecies = GetBaseSpecies(pkm);
for (int i = 0; i < 100; i++)
if (startLevel == -1)
startLevel = 100;

var table = EvolutionTree.GetEvolutionTree(pkm.Format);
int count = 1;
for (int i = 100; i >= startLevel; i--)
{
var table = EvolutionTree.GetEvolutionTree(pkm.Format);
var evos = table.GetValidPreEvolutions(pkm, i, skipChecks:true).ToArray();
if (evos.Any(evo => evo.Species == refSpecies))
return evos.OrderByDescending(evo => evo.Level).First().Level;
var evos = table.GetValidPreEvolutions(pkm, maxLevel: i, minLevel: startLevel, skipChecks:true).ToArray();
if (evos.Length < count) // lost an evolution, prior level was minimum current level
return evos.Max(evo => evo.Level) + 1;
count = evos.Length;
}
return 100;
return startLevel;
}
internal static bool GetCanBeCaptured(int species, int gen, GameVersion version = GameVersion.Any)
{
Expand Down Expand Up @@ -1274,7 +1277,7 @@ internal static int GetBaseSpecies(PKM pkm, int skipOption = 0, int generation =
int tree = generation != -1 ? generation : pkm.Format;
var table = EvolutionTree.GetEvolutionTree(tree);
int maxSpeciesOrigin = generation != -1 ? GetMaxSpeciesOrigin(generation) : - 1;
var evos = table.GetValidPreEvolutions(pkm, 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks:true).ToArray();
var evos = table.GetValidPreEvolutions(pkm, maxLevel: 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks:true).ToArray();

switch (skipOption)
{
Expand Down Expand Up @@ -1534,7 +1537,7 @@ internal static IEnumerable<DexLevel> GetValidPreEvolutions(PKM pkm, int maxspec

int tree = maxspeciesorigin == MaxSpeciesID_2 ? 2 : pkm.Format;
var et = EvolutionTree.GetEvolutionTree(tree);
return et.GetValidPreEvolutions(pkm, lvl: lvl, maxSpeciesOrigin: maxspeciesorigin, skipChecks: skipChecks);
return et.GetValidPreEvolutions(pkm, maxLevel: lvl, maxSpeciesOrigin: maxspeciesorigin, skipChecks: skipChecks);
}
private static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion Version, IReadOnlyList<DexLevel[]> vs, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true)
{
Expand Down
26 changes: 18 additions & 8 deletions PKHeX.Core/Legality/Encounters/EncounterGenerator.cs
Expand Up @@ -282,10 +282,16 @@ private static IEnumerable<IEncounterable> GenerateRawEncounters3(PKM pkm)
foreach (var z in GetValidGifts(pkm))
yield return z;

var deferred = new List<IEncounterable>();
bool safari = pkm.Ball == 0x05; // never static encounters
if (!safari)
foreach (var z in GetValidStaticEncounter(pkm))
yield return z;
{
if (z.Gift && pkm.Ball != 4)
deferred.Add(z);
else
yield return z;
}
foreach (var z in GetValidWildEncounters(pkm))
yield return z;
foreach (var z in GetValidEncounterTrades(pkm))
Expand All @@ -301,6 +307,9 @@ private static IEnumerable<IEncounterable> GenerateRawEncounters3(PKM pkm)

foreach (var z in GenerateEggs(pkm))
yield return z;

foreach (var z in deferred)
yield return z;
}

// EncounterStatic
Expand Down Expand Up @@ -474,7 +483,7 @@ private static IEnumerable<EncounterStatic> GetMatchingStaticEncounters(PKM pkm,
foreach (var e in deferred)
yield return e;
}
private static IEnumerable<EncounterStatic> GetStaticEncounters(PKM pkm, int lvl = -1, GameVersion gameSource = GameVersion.Any)
private static IEnumerable<EncounterStatic> GetStaticEncounters(PKM pkm, GameVersion gameSource = GameVersion.Any)
{
if (gameSource == GameVersion.Any)
gameSource = (GameVersion)pkm.Version;
Expand All @@ -483,16 +492,16 @@ private static IEnumerable<EncounterStatic> GetStaticEncounters(PKM pkm, int lvl
switch (pkm.GenNumber)
{
case 1:
return GetStatic(pkm, table, maxspeciesorigin: MaxSpeciesID_1, lvl: lvl);
return GetStatic(pkm, table, maxspeciesorigin: MaxSpeciesID_1);
case 2:
return GetStatic(pkm, table, maxspeciesorigin: MaxSpeciesID_2, lvl: lvl);
return GetStatic(pkm, table, maxspeciesorigin: MaxSpeciesID_2);
default:
return GetStatic(pkm, table, lvl);
return GetStatic(pkm, table);
}
}
private static IEnumerable<EncounterStatic> GetStatic(PKM pkm, IEnumerable<EncounterStatic> table, int maxspeciesorigin = -1, int lvl = -1)
private static IEnumerable<EncounterStatic> GetStatic(PKM pkm, IEnumerable<EncounterStatic> table, int maxspeciesorigin = -1, int lvl = -1, bool skip = false)
{
IEnumerable<DexLevel> dl = GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin, lvl: lvl);
IEnumerable<DexLevel> dl = GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin, lvl: lvl, skipChecks: skip);
return table.Where(e => dl.Any(d => d.Species == e.Species));
}

Expand Down Expand Up @@ -1364,7 +1373,8 @@ internal static EncounterStatic GetStaticLocation(PKM pkm, int species = -1)
case 2:
return GetGSStaticTransfer(species, pkm.Met_Level);
default:
return GetStaticEncounters(pkm, 100).OrderBy(s => s.Level).FirstOrDefault();
var table = GetEncounterStaticTable(pkm, (GameVersion)pkm.Version);
return GetStatic(pkm, table, lvl: 100, skip: true).FirstOrDefault();
}
}
internal static EncounterStatic GetRBYStaticTransfer(int species, int pkmMetLevel)
Expand Down
12 changes: 9 additions & 3 deletions PKHeX.Core/Legality/Structures/EvolutionTree.cs
Expand Up @@ -198,12 +198,12 @@ private int GetIndex(EvolutionMethod evo)

return Personal.GetFormeIndex(evolvesToSpecies, evolvesToForm);
}
public IEnumerable<DexLevel> GetValidPreEvolutions(PKM pkm, int lvl, int maxSpeciesOrigin = -1, bool skipChecks = false)
public IEnumerable<DexLevel> GetValidPreEvolutions(PKM pkm, int maxLevel, int maxSpeciesOrigin = -1, bool skipChecks = false, int minLevel = 1)
{
int index = GetIndex(pkm);
if (maxSpeciesOrigin <= 0)
maxSpeciesOrigin = Legal.GetMaxSpeciesOrigin(pkm);
return Lineage[index].GetExplicitLineage(pkm, lvl, skipChecks, MaxSpeciesTree, maxSpeciesOrigin);
return Lineage[index].GetExplicitLineage(pkm, maxLevel, skipChecks, MaxSpeciesTree, maxSpeciesOrigin, minLevel);
}
}

Expand Down Expand Up @@ -574,6 +574,8 @@ public bool Valid(PKM pkm, int lvl, bool skipChecks)
return false;

RequiresLevelUp = true;
if (skipChecks)
return lvl >= Level;

// Check Met Level for extra validity
switch (pkm.GenNumber)
Expand Down Expand Up @@ -644,8 +646,9 @@ public void Insert(EvolutionStage evo)
Chain.Insert(0, evo);
}

public IEnumerable<DexLevel> GetExplicitLineage(PKM pkm, int lvl, bool skipChecks, int maxSpeciesTree, int maxSpeciesOrigin)
public IEnumerable<DexLevel> GetExplicitLineage(PKM pkm, int maxLevel, bool skipChecks, int maxSpeciesTree, int maxSpeciesOrigin, int minLevel)
{
int lvl = maxLevel;
List<DexLevel> dl = new List<DexLevel> { new DexLevel { Species = pkm.Species, Level = lvl, Form = pkm.AltForm } };
for (int i = Chain.Count - 1; i >= 0; i--) // reverse evolution!
{
Expand All @@ -655,6 +658,9 @@ public IEnumerable<DexLevel> GetExplicitLineage(PKM pkm, int lvl, bool skipCheck
if (!evo.Valid(pkm, lvl, skipChecks))
continue;

if (evo.RequiresLevelUp && minLevel >= lvl)
break; // impossible evolution

oneValid = true;
UpdateMinValues(dl, evo);
int species = evo.Species;
Expand Down
2 changes: 1 addition & 1 deletion PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs
Expand Up @@ -774,7 +774,7 @@ private bool SetSuggestedMetLocation(bool silent = false)

int level = encounter.Level;
int location = encounter.Location;
int minlvl = Legal.GetLowestLevel(pkm, encounter.Species);
int minlvl = Legal.GetLowestLevel(pkm, encounter.LevelMin);
if (minlvl == 0)
minlvl = level;

Expand Down
2 changes: 1 addition & 1 deletion PKHeX.WinForms/Subforms/PKM Editors/BatchEditor.cs
Expand Up @@ -503,7 +503,7 @@ private static bool SetSuggestedPKMProperty(PKM PKM, StringInstruction cmd, PKMI

int level = encounter.Level;
int location = encounter.Location;
int minlvl = Legal.GetLowestLevel(PKM, encounter.Species);
int minlvl = Legal.GetLowestLevel(PKM, encounter.LevelMin);

PKM.Met_Level = level;
PKM.Met_Location = location;
Expand Down

0 comments on commit 072f1ba

Please sign in to comment.