Refactor some method signatures

vs -> chain (clarity on what it is; an evolution chain, rather than e.v.o.s - vs)
Clamp origin chain for transferred where we can use the max origin level
This commit is contained in:
Kurt
2020-06-27 22:18:29 -05:00
parent 065c1cc6d4
commit 3138fb20c6
18 changed files with 152 additions and 135 deletions

View File

@@ -48,21 +48,21 @@ public static T[] GetSimpleEncounterArea<T>(int[] species, int[] lvls, int locat
/// Gets the slots contained in the area that match the provided data.
/// </summary>
/// <param name="pkm">Pokémon Data</param>
/// <param name="vs">Evolution lineage</param>
/// <param name="chain">Evolution lineage</param>
/// <param name="minLevel">Minimum level of the encounter</param>
/// <returns>Enumerable list of encounters</returns>
public virtual IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> vs, int minLevel = 0)
public virtual IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel = 0)
{
if (minLevel == 0) // any
return Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species));
return Slots.Where(slot => chain.Any(evo => evo.Species == slot.Species));
var slots = GetMatchFromEvoLevel(pkm, vs, minLevel);
var slots = GetMatchFromEvoLevel(pkm, chain, minLevel);
return GetFilteredSlots(pkm, slots, minLevel);
}
protected virtual IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnumerable<EvoCriteria> vs, int minLevel)
protected virtual IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel)
{
var slots = Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin));
var slots = Slots.Where(slot => chain.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin));
// Get slots where pokemon can exist with respect to level constraints
return slots.Where(slot => slot.IsLevelWithinRange(minLevel));
}

View File

@@ -125,9 +125,9 @@ public static EncounterArea3[] GetArray3(byte[][] entries)
return entries.Select(GetArea3).Where(Area => Area.Slots.Length != 0).ToArray();
}
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnumerable<EvoCriteria> vs, int minLevel)
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel)
{
var slots = Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin));
var slots = Slots.Where(slot => chain.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin));
if (pkm.Format != 3) // transferred to Gen4+
return slots.Where(slot => slot.LevelMin <= minLevel);

View File

@@ -59,9 +59,9 @@ protected static void MarkStaticMagnetPermute(IEnumerable<EncounterSlot> grp, Li
EncounterUtil.MarkEncountersStaticMagnetPullPermutation(grp, PersonalTable.HGSS, trackPermute);
}
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnumerable<EvoCriteria> vs, int minLevel)
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel)
{
var slots = Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin));
var slots = Slots.Where(slot => chain.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin));
if (pkm.Format != 4) // transferred to Gen5+
return slots.Where(slot => slot.LevelMin <= minLevel);

View File

@@ -13,9 +13,9 @@ public sealed class EncounterArea6AO : EncounterArea32
private const int FluteBoostMax = 4; // Black Flute increases levels.
private const int DexNavBoost = 30; // Maximum DexNav chain
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnumerable<EvoCriteria> vs, int minLevel)
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel)
{
var slots = Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= (slot.LevelMin - FluteBoostMax)));
var slots = Slots.Where(slot => chain.Any(evo => evo.Species == slot.Species && evo.Level >= (slot.LevelMin - FluteBoostMax)));
// note: it's probably possible to determine a reduced DexNav boost based on the flawless IV count (no flawless = not chained)
// if someone wants to implement that logic to have the below method return a calculated max DexNavBoost, send a pull request :)

View File

@@ -71,14 +71,14 @@ public static bool WasFriendSafari(PKM pkm)
public static IEnumerable<EncounterSlot> GetValidFriendSafari(PKM pkm)
{
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
return GetValidFriendSafari(vs);
var chain = EvolutionChain.GetValidPreEvolutions(pkm);
return GetValidFriendSafari(chain);
}
public static IEnumerable<EncounterSlot> GetValidFriendSafari(IEnumerable<EvoCriteria> vs)
public static IEnumerable<EncounterSlot> GetValidFriendSafari(IReadOnlyList<DexLevel> chain)
{
var evos = vs.Where(d => d.Level >= 30);
return evos.SelectMany(z => Encounters6.FriendSafari[z.Species]);
var valid = chain.Where(d => d.Level >= 30);
return valid.SelectMany(z => Encounters6.FriendSafari[z.Species]);
}
}
}

View File

@@ -11,9 +11,9 @@ public sealed class EncounterArea7b : EncounterArea32
{
private const int CatchComboBonus = 1;
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnumerable<EvoCriteria> vs, int minLevel)
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel)
{
var slots = Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Form == slot.Form && evo.Level >= (slot.LevelMin - CatchComboBonus)));
var slots = Slots.Where(slot => chain.Any(evo => evo.Species == slot.Species && evo.Form == slot.Form && evo.Level >= (slot.LevelMin - CatchComboBonus)));
// Get slots where pokemon can exist with respect to level constraints
return slots.Where(s => s.IsLevelWithinRange(minLevel, minLevel, 0, CatchComboBonus));

View File

@@ -27,7 +27,7 @@ public override bool IsMatchLocation(int location)
return others.Contains((byte)location);
}
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnumerable<EvoCriteria> vs, int minLevel)
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel)
{
var loc = Location;
if (IsWildArea8(loc) || IsWildArea8Armor(loc)) // wild area gets boosted up to level 60 post-game
@@ -35,11 +35,11 @@ protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnu
const int boostTo = 60;
if (pkm.Met_Level == boostTo)
{
var boost = Slots.Where(slot => vs.Any(evo => IsMatch(evo, slot) && evo.Level >= boostTo));
var boost = Slots.Where(slot => chain.Any(evo => IsMatch(evo, slot) && evo.Level >= boostTo));
return boost.Where(s => s.LevelMax < boostTo || s.IsLevelWithinRange(minLevel));
}
}
var slots = Slots.Where(slot => vs.Any(evo => IsMatch(evo, slot) && evo.Level >= slot.LevelMin));
var slots = Slots.Where(slot => chain.Any(evo => IsMatch(evo, slot) && evo.Level >= slot.LevelMin));
// Get slots where pokemon can exist with respect to level constraints
return slots.Where(s => s.IsLevelWithinRange(minLevel));

View File

@@ -9,7 +9,7 @@ namespace PKHeX.Core
/// </summary>
public sealed class EncounterAreaFake : EncounterArea
{
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnumerable<EvoCriteria> vs, int minLevel)
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel)
=> Enumerable.Empty<EncounterSlot>();
protected override IEnumerable<EncounterSlot> GetFilteredSlots(PKM pkm, IEnumerable<EncounterSlot> slots, int minLevel)

View File

@@ -39,22 +39,22 @@ protected static EncounterSlot1[] ReadSlots1(byte[] data, ref int ofs, int count
return slots;
}
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> vs, int minLevel = 0)
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel = 0)
{
if (minLevel == 0) // any
return Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species));
return Slots.Where(slot => chain.Any(evo => evo.Species == slot.Species));
var Gen1Version = GameVersion.RBY;
bool RBDragonair = false;
if (minLevel != 0 && !FilterGBSlotsCatchRate(pkm, ref vs, ref Gen1Version, ref RBDragonair))
if (minLevel != 0 && !FilterGBSlotsCatchRate(pkm, ref chain, ref Gen1Version, ref RBDragonair))
return Enumerable.Empty<EncounterSlot>();
var encounterSlots = GetMatchFromEvoLevel(pkm, vs, minLevel);
var encounterSlots = GetMatchFromEvoLevel(pkm, chain, minLevel);
return GetFilteredSlots(pkm, encounterSlots, Gen1Version, RBDragonair).OrderBy(slot => slot.LevelMin); // prefer lowest levels
}
private static bool FilterGBSlotsCatchRate(PKM pkm, ref IReadOnlyList<EvoCriteria> vs, ref GameVersion Gen1Version, ref bool RBDragonair)
private static bool FilterGBSlotsCatchRate(PKM pkm, ref IReadOnlyList<DexLevel> chain, ref GameVersion Gen1Version, ref bool RBDragonair)
{
if (!(pkm is PK1 pk1) || !pkm.Gen1_NotTradeback)
return true;
@@ -71,34 +71,34 @@ private static bool FilterGBSlotsCatchRate(PKM pkm, ref IReadOnlyList<EvoCriteri
// Kadabra (YW)
case (int)Species.Kadabra when rate == 96:
case (int)Species.Alakazam when rate == 96:
vs = vs.Where(s => s.Species == (int)Species.Kadabra).ToArray();
chain = chain.Where(s => s.Species == (int)Species.Kadabra).ToArray();
Gen1Version = GameVersion.YW;
return true;
// Kadabra (RB)
case (int)Species.Kadabra when rate == 100:
case (int)Species.Alakazam when rate == 100:
vs = vs.Where(s => s.Species == (int)Species.Kadabra).ToArray();
chain = chain.Where(s => s.Species == (int)Species.Kadabra).ToArray();
Gen1Version = GameVersion.RB;
return true;
// Dragonair (YW)
case (int)Species.Dragonair when rate == 27:
case (int)Species.Dragonite when rate == 27:
vs = vs.Where(s => s.Species == (int)Species.Dragonair).ToArray(); // Yellow Dragonair, ignore Dratini encounters
chain = chain.Where(s => s.Species == (int)Species.Dragonair).ToArray(); // Yellow Dragonair, ignore Dratini encounters
Gen1Version = GameVersion.YW;
return true;
// Dragonair (RB)
case (int)Species.Dragonair:
case (int)Species.Dragonite:
// Red blue dragonair have the same catch rate as dratini, it could also be a dratini from any game
vs = vs.Where(s => rate == PersonalTable.RB[s.Species].CatchRate).ToArray();
// Red / Blue Dragonair have the same catch rate as Dratini; it could also be a Dratini from any game
chain = chain.Where(s => rate == PersonalTable.RB[s.Species].CatchRate).ToArray();
RBDragonair = true;
return true;
default:
vs = vs.Where(s => rate == PersonalTable.RB[s.Species].CatchRate).ToArray();
chain = chain.Where(s => rate == PersonalTable.RB[s.Species].CatchRate).ToArray();
return true;
}
}
@@ -128,9 +128,9 @@ private static IEnumerable<EncounterSlot> GetFilteredSlots(PKM pkm, IEnumerable<
}
}
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IEnumerable<EvoCriteria> vs, int minLevel)
protected override IEnumerable<EncounterSlot> GetMatchFromEvoLevel(PKM pkm, IReadOnlyList<DexLevel> chain, int minLevel)
{
var slots = Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin));
var slots = Slots.Where(slot => chain.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin));
if (pkm.Format >= 7 || !(pkm is PK2 pk2 && pk2.CaughtData != 0)) // transferred to Gen7+, or does not have Crystal met data
return slots.Where(slot => slot.LevelMin <= minLevel);

View File

@@ -251,7 +251,7 @@ internal static bool IsEvolutionValid(PKM pkm, int minSpecies = -1, int minLevel
var min = curr.FindLast(z => z.Species == minSpecies);
if (min != null && min.Level < minLevel)
return false;
var poss = EvolutionChain.GetValidPreEvolutions(pkm, lvl: 100, minLevel: minLevel, skipChecks: true);
var poss = EvolutionChain.GetValidPreEvolutions(pkm, maxLevel: 100, minLevel: minLevel, skipChecks: true);
if (minSpecies != -1)
{
@@ -398,7 +398,7 @@ private static int GetMaxLevelGeneration(PKM pkm, int generation)
return pkm.CurrentLevel;
}
internal static int GetMinLevelEncounter(PKM pkm)
internal static int GetMaxLevelEncounter(PKM pkm)
{
// Only for gen 3 pokemon in format 3, after transfer to gen 4 it should return transfer level
if (pkm.Format == 3 && pkm.WasEgg)

View File

@@ -16,7 +16,7 @@ public static IEnumerable<EncounterEgg> GenerateEggs(PKM pkm, bool all = false)
return GenerateEggs(pkm, evos, all);
}
public static IEnumerable<EncounterEgg> GenerateEggs(PKM pkm, IReadOnlyList<EvoCriteria> vs, bool all = false)
public static IEnumerable<EncounterEgg> GenerateEggs(PKM pkm, IReadOnlyList<EvoCriteria> chain, bool all = false)
{
int species = pkm.Species;
if (NoHatchFromEgg.Contains(species))
@@ -33,7 +33,7 @@ public static IEnumerable<EncounterEgg> GenerateEggs(PKM pkm, IReadOnlyList<EvoC
int lvl = GetEggHatchLevel(gen);
int max = GetMaxSpeciesOrigin(gen);
var e = EvoBase.GetBaseSpecies(vs, 0);
var e = EvoBase.GetBaseSpecies(chain, 0);
if (e.Species <= max && !NoHatchFromEggFormGen(e.Species, e.Form, ver))
{
yield return new EncounterEgg(e.Species, e.Form, lvl, gen, ver);
@@ -44,7 +44,7 @@ public static IEnumerable<EncounterEgg> GenerateEggs(PKM pkm, IReadOnlyList<EvoC
if (!GetSplitBreedGeneration(gen).Contains(species))
yield break; // no other possible species
var o = EvoBase.GetBaseSpecies(vs, 1);
var o = EvoBase.GetBaseSpecies(chain, 1);
if (o.Species <= max && !NoHatchFromEggFormGen(o.Species, o.Form, ver))
{
yield return new EncounterEggSplit(o.Species, o.Form, lvl, gen, ver, e.Species);

View File

@@ -142,10 +142,10 @@ private static IEnumerable<IEncounterable> GenerateRawEncounters12(PKM pkm, Game
// Calculate all 3 at the same time and pick the best result (by species).
// Favor special event move gifts as Static Encounters when applicable
var maxspeciesorigin = gsc ? MaxSpeciesID_2 : MaxSpeciesID_1;
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin);
var chain = EvolutionChain.GetOriginChain(pkm, maxspeciesorigin: maxspeciesorigin);
var deferred = new List<IEncounterable>();
foreach (var t in GetValidEncounterTrades(pkm, vs, game))
foreach (var t in GetValidEncounterTrades(pkm, chain, game))
{
// some OTs are longer than the keyboard entry; don't defer these
if (pkm.Format >= 7 && pkm.OT_Name.Length <= (pkm.Japanese || pkm.Korean ? 5 : 7))
@@ -155,7 +155,7 @@ private static IEnumerable<IEncounterable> GenerateRawEncounters12(PKM pkm, Game
}
yield return t;
}
foreach (var s in GetValidStaticEncounter(pkm, vs, game))
foreach (var s in GetValidStaticEncounter(pkm, chain, game))
{
// Valid stadium and non-stadium encounters, return only non-stadium encounters, they are less restrictive
switch (s.Version)
@@ -179,7 +179,7 @@ private static IEnumerable<IEncounterable> GenerateRawEncounters12(PKM pkm, Game
}
yield return s;
}
foreach (var e in GetValidWildEncounters12(pkm, vs, game))
foreach (var e in GetValidWildEncounters12(pkm, chain, game))
{
yield return e;
}

View File

@@ -19,17 +19,17 @@ public static class EncounterSlotGenerator
public static IEnumerable<EncounterSlot> GetPossible(PKM pkm, GameVersion gameSource = GameVersion.Any)
{
int maxspeciesorigin = GetMaxSpecies(gameSource);
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin);
return GetPossible(pkm, vs, gameSource);
var chain = EvolutionChain.GetOriginChain(pkm, maxspeciesorigin: maxspeciesorigin);
return GetPossible(pkm, chain, gameSource);
}
public static IEnumerable<EncounterSlot> GetPossible(PKM pkm, IReadOnlyList<DexLevel> vs, GameVersion gameSource = GameVersion.Any)
public static IEnumerable<EncounterSlot> GetPossible(PKM pkm, IReadOnlyList<DexLevel> chain, GameVersion gameSource = GameVersion.Any)
{
var possibleAreas = GetEncounterSlots(pkm, gameSource);
return possibleAreas.SelectMany(area => area.Slots).Where(z => vs.Any(v => v.Species == z.Species));
return possibleAreas.SelectMany(area => area.Slots).Where(z => chain.Any(v => v.Species == z.Species));
}
private static IEnumerable<EncounterSlot> GetRawEncounterSlots(PKM pkm, int lvl, IReadOnlyList<EvoCriteria> vs, GameVersion gameSource)
private static IEnumerable<EncounterSlot> GetRawEncounterSlots(PKM pkm, int lvl, IReadOnlyList<EvoCriteria> chain, GameVersion gameSource)
{
if (pkm.Egg_Location != 0)
yield break;
@@ -37,7 +37,7 @@ private static IEnumerable<EncounterSlot> GetRawEncounterSlots(PKM pkm, int lvl,
var possibleAreas = GetEncounterAreas(pkm, gameSource);
foreach (var area in possibleAreas)
{
var slots = area.GetMatchingSlots(pkm, vs, lvl);
var slots = area.GetMatchingSlots(pkm, chain, lvl);
foreach (var s in slots)
yield return s;
}
@@ -54,7 +54,7 @@ private static int GetMaxSpecies(GameVersion gameSource)
public static IEnumerable<EncounterSlot> GetValidWildEncounters34(PKM pkm, GameVersion gameSource = GameVersion.Any)
{
int lvl = GetMinLevelEncounter(pkm);
int lvl = GetMaxLevelEncounter(pkm);
if (lvl <= 0)
return Enumerable.Empty<EncounterSlot>();
@@ -62,33 +62,33 @@ public static IEnumerable<EncounterSlot> GetValidWildEncounters34(PKM pkm, GameV
gameSource = (GameVersion)pkm.Version;
int maxspeciesorigin = GetMaxSpecies(gameSource);
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin);
var s = GetRawEncounterSlots(pkm, lvl, vs, gameSource);
var chain = EvolutionChain.GetOriginChain(pkm, maxspeciesorigin: maxspeciesorigin);
var slots = GetRawEncounterSlots(pkm, lvl, chain, gameSource);
return s; // defer deferrals to the method consuming this collection
return slots; // defer deferrals to the method consuming this collection
}
public static IEnumerable<EncounterSlot> GetValidWildEncounters12(PKM pkm, IReadOnlyList<EvoCriteria> vs, GameVersion gameSource = GameVersion.Any)
public static IEnumerable<EncounterSlot> GetValidWildEncounters12(PKM pkm, IReadOnlyList<EvoCriteria> chain, GameVersion gameSource = GameVersion.Any)
{
int lvl = GetMinLevelEncounter(pkm);
int lvl = GetMaxLevelEncounter(pkm);
if (lvl <= 0)
return Enumerable.Empty<EncounterSlot>();
if (gameSource == GameVersion.Any)
gameSource = (GameVersion)pkm.Version;
return GetRawEncounterSlots(pkm, lvl, vs, gameSource);
return GetRawEncounterSlots(pkm, lvl, chain, gameSource);
}
public static IEnumerable<EncounterSlot> GetValidWildEncounters(PKM pkm, IReadOnlyList<EvoCriteria> vs, GameVersion gameSource = GameVersion.Any)
public static IEnumerable<EncounterSlot> GetValidWildEncounters(PKM pkm, IReadOnlyList<EvoCriteria> chain, GameVersion gameSource = GameVersion.Any)
{
if (gameSource == GameVersion.Any)
gameSource = (GameVersion)pkm.Version;
int lvl = GetMinLevelEncounter(pkm);
int lvl = GetMaxLevelEncounter(pkm);
if (lvl <= 0)
return Enumerable.Empty<EncounterSlot>();
var s = GetRawEncounterSlots(pkm, lvl, vs, gameSource);
var s = GetRawEncounterSlots(pkm, lvl, chain, gameSource);
bool IsSafariBall = pkm.Ball == (int)Ball.Safari;
bool IsSportBall = pkm.Ball == (int)Ball.Sport;
@@ -101,8 +101,8 @@ public static IEnumerable<EncounterSlot> GetValidWildEncounters(PKM pkm, IReadOn
public static IEnumerable<EncounterSlot> GetValidWildEncounters(PKM pkm, GameVersion gameSource = GameVersion.Any)
{
int maxspeciesorigin = GetMaxSpecies(gameSource);
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin);
return GetValidWildEncounters(pkm, vs, gameSource);
var chain = EvolutionChain.GetOriginChain(pkm, maxspeciesorigin: maxspeciesorigin);
return GetValidWildEncounters(pkm, chain, gameSource);
}
public static bool IsDeferred3(this EncounterSlot slot, int currentSpecies, PKM pkm, bool IsSafariBall)
@@ -131,11 +131,11 @@ private static bool IsDeferred(this EncounterSlot slot, int currentSpecies, PKM
private static bool IsDeferredSport(this EncounterSlot slot, bool IsSportBall) => IsSportBall != ((slot.Type & SlotType.BugContest) != 0);
private static bool IsDeferredHiddenAbility(this EncounterSlot slot, bool IsHidden) => IsHidden != slot.IsHiddenAbilitySlot();
private static IEnumerable<EncounterSlot> GetValidEncounterSlots(PKM pkm, EncounterArea loc, IReadOnlyList<EvoCriteria> vs, int lvl)
private static IEnumerable<EncounterSlot> GetValidEncounterSlots(PKM pkm, EncounterArea loc, IReadOnlyList<EvoCriteria> chain, int lvl)
{
if (pkm.Egg_Location != 0)
return Enumerable.Empty<EncounterSlot>();
return loc.GetMatchingSlots(pkm, vs, lvl);
return loc.GetMatchingSlots(pkm, chain, lvl);
}
public static IEnumerable<EncounterArea> GetEncounterSlots(PKM pkm, GameVersion gameSource = GameVersion.Any)
@@ -166,9 +166,9 @@ private static bool IsHiddenAbilitySlot(this EncounterSlot slot)
internal static EncounterArea? GetCaptureLocation(PKM pkm)
{
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
var chain = EvolutionChain.GetOriginChain(pkm);
return (from area in GetEncounterSlots(pkm)
let slots = GetValidEncounterSlots(pkm, area, vs, lvl: 0).ToArray()
let slots = GetValidEncounterSlots(pkm, area, chain, lvl: 0).ToArray()
where slots.Length != 0
select new EncounterAreaFake
{

View File

@@ -25,16 +25,16 @@ public static IEnumerable<EncounterStatic> GetPossible(PKM pkm, GameVersion game
2 => MaxSpeciesID_2,
_ => -1
};
var dl = EvolutionChain.GetValidPreEvolutions(pkm, maxID);
var dl = EvolutionChain.GetOriginChain(pkm, maxID);
return GetPossible(pkm, dl, gameSource);
}
public static IEnumerable<EncounterStatic> GetPossible(PKM pkm, IReadOnlyList<DexLevel> vs, GameVersion gameSource = GameVersion.Any)
public static IEnumerable<EncounterStatic> GetPossible(PKM pkm, IReadOnlyList<DexLevel> chain, GameVersion gameSource = GameVersion.Any)
{
if (gameSource == GameVersion.Any)
gameSource = (GameVersion)pkm.Version;
var encs = GetStaticEncounters(pkm, vs, gameSource);
var encs = GetStaticEncounters(pkm, chain, gameSource);
return encs.Where(e => ParseSettings.AllowGBCartEra || !GameVersion.GBCartEraOnly.Contains(e.Version));
}
@@ -42,7 +42,7 @@ public static IEnumerable<EncounterStatic> GetValidStaticEncounter(PKM pkm, Game
{
var poss = GetPossible(pkm, gameSource: gameSource);
int lvl = GetMinLevelEncounter(pkm);
int lvl = GetMaxLevelEncounter(pkm);
if (lvl < 0)
return Enumerable.Empty<EncounterStatic>();
@@ -50,11 +50,11 @@ public static IEnumerable<EncounterStatic> GetValidStaticEncounter(PKM pkm, Game
return GetMatchingStaticEncounters(pkm, poss, lvl);
}
public static IEnumerable<EncounterStatic> GetValidStaticEncounter(PKM pkm, IReadOnlyList<DexLevel> vs, GameVersion gameSource)
public static IEnumerable<EncounterStatic> GetValidStaticEncounter(PKM pkm, IReadOnlyList<DexLevel> chain, GameVersion gameSource)
{
var poss = GetPossible(pkm, vs, gameSource: gameSource);
var poss = GetPossible(pkm, chain, gameSource: gameSource);
int lvl = GetMinLevelEncounter(pkm);
int lvl = GetMaxLevelEncounter(pkm);
if (lvl < 0)
return Enumerable.Empty<EncounterStatic>();
@@ -160,7 +160,7 @@ private static EncounterStatic GetGSStaticTransfer(int species, int pkmMetLevel)
case 2:
return GetGSStaticTransfer(species, pkm.Met_Level);
default:
var dl = EvolutionChain.GetValidPreEvolutions(pkm, lvl: 100, skipChecks: true);
var dl = EvolutionChain.GetValidPreEvolutions(pkm, maxLevel: 100, skipChecks: true);
return GetPossible(pkm, dl).FirstOrDefault();
}
}

View File

@@ -9,55 +9,55 @@ public static class EncounterTradeGenerator
{
public static IEnumerable<EncounterTrade> GetPossible(PKM pkm, GameVersion gameSource = GameVersion.Any)
{
var p = EvolutionChain.GetValidPreEvolutions(pkm);
var p = EvolutionChain.GetOriginChain(pkm);
return GetPossible(pkm, p, gameSource);
}
public static IEnumerable<EncounterTrade> GetPossible(PKM pkm, IReadOnlyList<DexLevel> vs, GameVersion gameSource = GameVersion.Any)
public static IEnumerable<EncounterTrade> GetPossible(PKM pkm, IReadOnlyList<DexLevel> chain, GameVersion gameSource = GameVersion.Any)
{
if (gameSource == GameVersion.Any)
gameSource = (GameVersion)pkm.Version;
if (pkm.VC || pkm.Format <= 2)
return GetPossibleVC(vs, gameSource);
return GetPossibleNonVC(pkm, vs, gameSource);
return GetPossibleVC(chain, gameSource);
return GetPossibleNonVC(pkm, chain, gameSource);
}
public static IEnumerable<EncounterTrade> GetValidEncounterTrades(PKM pkm, GameVersion gameSource = GameVersion.Any)
{
var p = EvolutionChain.GetValidPreEvolutions(pkm);
var p = EvolutionChain.GetOriginChain(pkm);
return GetValidEncounterTrades(pkm, p, gameSource);
}
public static IEnumerable<EncounterTrade> GetValidEncounterTrades(PKM pkm, IReadOnlyList<DexLevel> p, GameVersion gameSource = GameVersion.Any)
public static IEnumerable<EncounterTrade> GetValidEncounterTrades(PKM pkm, IReadOnlyList<DexLevel> chain, GameVersion gameSource = GameVersion.Any)
{
if (GetIsFromGB(pkm))
return GetValidEncounterTradesVC(pkm, p, gameSource);
return GetValidEncounterTradesVC(pkm, chain, gameSource);
int lvl = IsNotTrade(pkm);
if (lvl <= 0)
return Enumerable.Empty<EncounterTrade>();
var poss = GetPossibleNonVC(pkm, p, gameSource);
var poss = GetPossibleNonVC(pkm, chain, gameSource);
return poss.Where(z => z.IsMatch(pkm, lvl));
}
private static IEnumerable<EncounterTrade> GetPossibleNonVC(PKM pkm, IReadOnlyList<DexLevel> p, GameVersion gameSource = GameVersion.Any)
private static IEnumerable<EncounterTrade> GetPossibleNonVC(PKM pkm, IReadOnlyList<DexLevel> chain, GameVersion gameSource = GameVersion.Any)
{
if (gameSource == GameVersion.Any)
gameSource = (GameVersion)pkm.Version;
if (pkm.VC || pkm.Format <= 2)
return GetValidEncounterTradesVC(pkm, p, gameSource);
return GetValidEncounterTradesVC(pkm, chain, gameSource);
var table = GetEncounterTradeTable(pkm);
return table.Where(f => p.Any(r => r.Species == f.Species));
return table.Where(f => chain.Any(r => r.Species == f.Species));
}
private static IEnumerable<EncounterTrade> GetPossibleVC(IReadOnlyList<DexLevel> p, GameVersion gameSource = GameVersion.Any)
private static IEnumerable<EncounterTrade> GetPossibleVC(IReadOnlyList<DexLevel> chain, GameVersion gameSource = GameVersion.Any)
{
var table = GetEncounterTradeTableVC(gameSource);
return table.Where(f => p.Any(r => r.Species == f.Species));
return table.Where(f => chain.Any(r => r.Species == f.Species));
}
private static IEnumerable<EncounterTrade> GetEncounterTradeTableVC(GameVersion gameSource)
@@ -83,9 +83,9 @@ private static IEnumerable<EncounterTrade> GetEncounterTradeTable(PKM pkm)
};
}
private static IEnumerable<EncounterTrade> GetValidEncounterTradesVC(PKM pkm, IReadOnlyList<DexLevel> p, GameVersion gameSource)
private static IEnumerable<EncounterTrade> GetValidEncounterTradesVC(PKM pkm, IReadOnlyList<DexLevel> chain, GameVersion gameSource)
{
var poss = GetPossibleVC(p, gameSource);
var poss = GetPossibleVC(chain, gameSource);
if (gameSource == GameVersion.RBY)
return poss.Where(z => z.IsMatchVC1(pkm));
return poss.Where(z => z.IsMatchVC2(pkm));
@@ -101,7 +101,7 @@ private static int IsNotTrade(PKM pkm)
if (lang == (int)LanguageID.Hacked && !IsValidMissingLanguage(pkm)) // Japanese trades in BW have no language ID
return 0;
return GetMinLevelEncounter(pkm);
return GetMaxLevelEncounter(pkm);
}
}
}

View File

@@ -9,11 +9,11 @@ public static class MysteryGiftGenerator
public static IEnumerable<MysteryGift> GetPossible(PKM pkm)
{
int maxSpecies = Legal.GetMaxSpeciesOrigin(pkm.Format);
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxSpecies);
return GetPossible(pkm, vs);
var chain = EvolutionChain.GetOriginChain(pkm, maxSpecies);
return GetPossible(pkm, chain);
}
public static IEnumerable<MysteryGift> GetPossible(PKM pkm, IReadOnlyList<DexLevel> vs)
public static IEnumerable<MysteryGift> GetPossible(PKM pkm, IReadOnlyList<DexLevel> chain)
{
// Ranger Manaphy is a PGT and is not in the PCD[] for gen4. Check manually.
int gen = pkm.GenNumber;
@@ -21,7 +21,7 @@ public static IEnumerable<MysteryGift> GetPossible(PKM pkm, IReadOnlyList<DexLev
yield return RangerManaphy;
var table = GetTable(gen, pkm);
var possible = table.Where(wc => vs.Any(dl => dl.Species == wc.Species));
var possible = table.Where(wc => chain.Any(dl => dl.Species == wc.Species));
foreach (var enc in possible)
yield return enc;
}
@@ -66,14 +66,14 @@ private static IEnumerable<MysteryGift> GetMatchingPCD(PKM pkm, IEnumerable<PCD>
private static IEnumerable<MysteryGift> GetMatchingGifts(PKM pkm, IEnumerable<MysteryGift> DB)
{
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
return GetMatchingGifts(pkm, DB, vs);
var chain = EvolutionChain.GetOriginChain(pkm);
return GetMatchingGifts(pkm, DB, chain);
}
private static IEnumerable<MysteryGift> GetMatchingGifts(PKM pkm, IEnumerable<MysteryGift> DB, IReadOnlyList<DexLevel> vs)
private static IEnumerable<MysteryGift> GetMatchingGifts(PKM pkm, IEnumerable<MysteryGift> DB, IReadOnlyList<DexLevel> chain)
{
var deferred = new List<MysteryGift>();
var gifts = DB.Where(wc => vs.Any(dl => dl.Species == wc.Species));
var gifts = DB.Where(wc => chain.Any(dl => dl.Species == wc.Species));
foreach (var mg in gifts)
{
var result = mg.IsMatch(pkm);

View File

@@ -34,7 +34,7 @@ private static List<EvoCriteria>[] GetChainSingle(PKM pkm, List<EvoCriteria> Com
return chain;
}
private static List<EvoCriteria>[] GetChainAll(PKM pkm, IEncounterable Encounter, IEnumerable<EvoCriteria> CompleteEvoChain)
private static List<EvoCriteria>[] GetChainAll(PKM pkm, IEncounterable enc, IReadOnlyList<EvoCriteria> CompleteEvoChain)
{
int maxgen = pkm is PK1 && !pkm.Gen1_NotTradeback ? 2 : pkm.Format;
var GensEvoChains = GetChainBase(maxgen);
@@ -44,7 +44,7 @@ private static List<EvoCriteria>[] GetChainAll(PKM pkm, IEncounterable Encounter
int lvl = pkm.CurrentLevel;
int maxLevel = lvl;
int pkGen = Encounter.Generation;
int pkGen = enc.Generation;
// Iterate generations backwards
// Maximum level of an earlier generation (GenX) will never be greater than a later generation (GenX+Y).
@@ -104,7 +104,7 @@ private static List<EvoCriteria>[] GetChainAll(PKM pkm, IEncounterable Encounter
}
}
GensEvoChains[g] = GetEvolutionChain(pkm, Encounter, mostEvolved.Species, lvl);
GensEvoChains[g] = GetEvolutionChain(pkm, enc, mostEvolved.Species, lvl);
if (GensEvoChains[g].Count == 0)
continue;
@@ -163,60 +163,60 @@ internal static int GetEvoChainSpeciesIndex(IReadOnlyList<EvoCriteria> chain, in
private static List<EvoCriteria> GetEvolutionChain(PKM pkm, IEncounterable Encounter, int maxspec, int maxlevel)
{
var vs = GetValidPreEvolutions(pkm, minLevel: Encounter.LevelMin);
var chain = GetValidPreEvolutions(pkm, minLevel: Encounter.LevelMin);
if (Encounter.Species == maxspec)
{
if (vs.Count != 1)
if (chain.Count != 1)
{
vs.RemoveAll(z => z.Species != Encounter.Species);
vs[0].MinLevel = Encounter.LevelMin;
chain.RemoveAll(z => z.Species != Encounter.Species);
chain[0].MinLevel = Encounter.LevelMin;
}
return vs;
return chain;
}
// Evolution chain is in reverse order (devolution)
// Find the index of the minimum species to determine the end of the chain
int minindex = GetEvoChainSpeciesIndex(vs, Encounter.Species);
bool last = minindex < 0 || minindex == vs.Count - 1;
int minindex = GetEvoChainSpeciesIndex(chain, Encounter.Species);
bool last = minindex < 0 || minindex == chain.Count - 1;
// If we remove a pre-evolution, update the chain if appropriate.
if (!last)
{
// Remove chain species after the encounter
int count = vs.Count;
int count = chain.Count;
for (int i = minindex + 1; i < count; i++)
vs.RemoveAt(i);
chain.RemoveAt(i);
if (vs.Count == 0)
return vs; // no species left in chain
CheckLastEncounterRemoval(Encounter, vs);
if (chain.Count == 0)
return chain; // no species left in chain
CheckLastEncounterRemoval(Encounter, chain);
}
// maxspec is used to remove future geneneration evolutions, to gather evolution chain of a pokemon in previous generations
int skip = Math.Max(0, GetEvoChainSpeciesIndex(vs, maxspec));
int skip = Math.Max(0, GetEvoChainSpeciesIndex(chain, maxspec));
for (int i = 0; i < skip; i++)
vs.RemoveAt(0);
chain.RemoveAt(0);
// Gen3->4 and Gen4->5 transfer sets the Met Level property to the Pokémon's current level.
// Removes evolutions impossible before the transfer level.
// For example a FireRed Charizard with a current level (in XY) is 50 but Met Level is 20; it couldn't be a Charizard in Gen3 and Gen4 games
vs.RemoveAll(e => e.MinLevel > maxlevel);
chain.RemoveAll(e => e.MinLevel > maxlevel);
// Reduce the evolution chain levels to max level to limit any later analysis/results.
foreach (var d in vs)
foreach (var d in chain)
d.Level = Math.Min(d.Level, maxlevel);
return vs;
return chain;
}
private static void CheckLastEncounterRemoval(IEncounterable Encounter, IReadOnlyList<EvoCriteria> vs)
private static void CheckLastEncounterRemoval(IEncounterable enc, IReadOnlyList<EvoCriteria> chain)
{
// Last entry from vs is removed, turn next entry into the encountered Pokémon
var last = vs[vs.Count - 1];
last.MinLevel = Encounter.LevelMin;
// Last entry from chain is removed, turn next entry into the encountered Pokémon
var last = chain[chain.Count - 1];
last.MinLevel = enc.LevelMin;
last.RequiresLvlUp = false;
var first = vs[0];
var first = chain[0];
if (first.RequiresLvlUp)
return;
@@ -234,17 +234,34 @@ private static void CheckLastEncounterRemoval(IEncounterable Encounter, IReadOnl
}
}
internal static List<EvoCriteria> GetValidPreEvolutions(PKM pkm, int maxspeciesorigin = -1, int lvl = -1, int minLevel = 1, bool skipChecks = false)
internal static List<EvoCriteria> GetOriginChain(PKM pkm, int maxspeciesorigin = -1, int lvl = -1, int minLevel = 1, bool skipChecks = false)
{
if (lvl < 0)
lvl = pkm.CurrentLevel;
var chain = GetValidPreEvolutions(pkm, maxspeciesorigin, lvl, minLevel, skipChecks);
if (!pkm.HasOriginalMetLocation)
{
var maxLevel = Legal.GetMaxLevelEncounter(pkm);
if (maxLevel < 0)
{
chain.Clear();
return chain;
}
foreach (var c in chain)
c.Level = Math.Min(maxLevel, c.Level);
}
return chain;
}
internal static List<EvoCriteria> GetValidPreEvolutions(PKM pkm, int maxspeciesorigin = -1, int maxLevel = -1, int minLevel = 1, bool skipChecks = false)
{
if (maxLevel < 0)
maxLevel = pkm.CurrentLevel;
if (maxspeciesorigin == -1 && pkm.InhabitedGeneration(2) && pkm.Format <= 2 && pkm.GenNumber == 1)
maxspeciesorigin = MaxSpeciesID_2;
int tree = Math.Max(2, pkm.Format);
var et = EvolutionTree.GetEvolutionTree(pkm, tree);
return et.GetValidPreEvolutions(pkm, maxLevel: lvl, maxSpeciesOrigin: maxspeciesorigin, skipChecks: skipChecks, minLevel: minLevel);
return et.GetValidPreEvolutions(pkm, maxLevel: maxLevel, maxSpeciesOrigin: maxspeciesorigin, skipChecks: skipChecks, minLevel: minLevel);
}
private static int GetMinLevelGeneration(PKM pkm, int generation)

View File

@@ -240,7 +240,7 @@ internal static IEnumerable<int> GetExclusivePreEvolutionMoves(PKM pkm, int Spec
return preevomoves.Except(evomoves).Distinct();
}
internal static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion version, IReadOnlyList<EvoCriteria> vs, int generation, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true)
internal static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion version, IReadOnlyList<EvoCriteria> chain, int generation, int minLvLG1 = 1, int minLvLG2 = 1, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false, bool MoveReminder = true, bool RemoveTransferHM = true)
{
var r = new List<int> { 0 };
int species = pkm.Species;
@@ -257,7 +257,7 @@ internal static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion version, IRe
formCount = pkm.PersonalInfo.FormeCount;
for (int form = 0; form < formCount; form++)
r.AddRange(GetMoves(pkm, species, minLvLG1, minLvLG2, vs[0].Level, form, Tutor, version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, generation));
r.AddRange(GetMoves(pkm, species, minLvLG1, minLvLG2, chain[0].Level, form, Tutor, version, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, generation));
if (Relearn)
r.AddRange(pkm.RelearnMoves);
return r.Distinct();
@@ -266,10 +266,10 @@ internal static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion version, IRe
// Special Type Tutors Availability
bool moveTutor = Tutor || MoveReminder; // Usually true, except when called for move suggestions (no tutored moves)
for (var i = 0; i < vs.Count; i++)
for (var i = 0; i < chain.Count; i++)
{
var evo = vs[i];
var moves = GetEvoMoves(pkm, version, vs, generation, minLvLG1, minLvLG2, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, moveTutor, i, evo);
var evo = chain[i];
var moves = GetEvoMoves(pkm, version, chain, generation, minLvLG1, minLvLG2, LVL, Tutor, Machine, MoveReminder, RemoveTransferHM, moveTutor, i, evo);
r.AddRange(moves);
}
@@ -285,12 +285,12 @@ internal static IEnumerable<int> GetValidMoves(PKM pkm, GameVersion version, IRe
return r.Distinct();
}
private static IEnumerable<int> GetEvoMoves(PKM pkm, GameVersion Version, IReadOnlyList<EvoCriteria> vs, int generation, int minLvLG1, int minLvLG2, bool LVL, bool Tutor, bool Machine, bool MoveReminder, bool RemoveTransferHM, bool moveTutor, int i, EvoCriteria evo)
private static IEnumerable<int> GetEvoMoves(PKM pkm, GameVersion Version, IReadOnlyList<EvoCriteria> chain, int generation, int minLvLG1, int minLvLG2, bool LVL, bool Tutor, bool Machine, bool MoveReminder, bool RemoveTransferHM, bool moveTutor, int i, EvoCriteria evo)
{
int minlvlevo1 = GetEvoMoveMinLevel1(pkm, generation, minLvLG1, evo);
int minlvlevo2 = GetEvoMoveMinLevel2(pkm, generation, minLvLG2, evo);
var maxLevel = evo.Level;
if (i != 0 && vs[i - 1].RequiresLvlUp) // evolution
if (i != 0 && chain[i - 1].RequiresLvlUp) // evolution
++maxLevel; // allow lvlmoves from the level it evolved to the next species
return GetMoves(pkm, evo.Species, minlvlevo1, minlvlevo2, maxLevel, evo.Form, Tutor, Version, LVL, moveTutor, Machine, MoveReminder, RemoveTransferHM, generation);
}