Misc updates

reducing allocations, increasing clarity by removing some magic numbers
probably can rewrite some of the evo loading/checking for even less, but
good for now.
This commit is contained in:
Kurt 2019-01-06 16:22:45 -08:00
parent 744646e30d
commit 75202c7a89
7 changed files with 154 additions and 78 deletions

View file

@ -504,11 +504,9 @@ namespace PKHeX.Core
internal static bool IsTradeEvolved(IReadOnlyList<EvoCriteria>[] chain, int pkmFormat)
{
return chain[pkmFormat].Any(IsTradeEvolved);
return chain[pkmFormat].Any(z => z.IsTradeRequired);
}
internal static bool IsTradeEvolved(EvoCriteria z) => EvolutionMethod.TradeMethods.Contains(z.Method);
internal static bool IsEvolutionValid(PKM pkm, int minSpecies = -1, int minLevel = -1)
{
var curr = EvolutionChain.GetValidPreEvolutions(pkm);

View file

@ -6,5 +6,7 @@
public bool RequiresLvlUp { get; set; }
public int Form { get; set; } = -1;
public int Method { get; set; } = -1;
public bool IsTradeRequired => ((EvolutionType) Method).IsTrade();
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using static PKHeX.Core.EvolutionType;
namespace PKHeX.Core
{
@ -15,14 +16,19 @@ namespace PKHeX.Core
public int Form = -1;
public int Level;
public bool RequiresLevelUp;
// Not stored in binary data
public bool RequiresLevelUp; // tracks if this method requires levelup
internal IReadOnlyCollection<GameVersion> Banlist = Array.Empty<GameVersion>();
internal static readonly HashSet<int> TradeMethods = new HashSet<int> {5, 6, 7};
private static readonly IReadOnlyCollection<GameVersion> NoBanlist = Array.Empty<GameVersion>();
internal static readonly IReadOnlyCollection<GameVersion> BanSM = new[] {GameVersion.SN, GameVersion.MN};
internal static readonly IReadOnlyCollection<GameVersion> BanGG = new[] {GameVersion.GP, GameVersion.GE};
internal IReadOnlyCollection<GameVersion> Banlist = NoBanlist;
/// <summary>
/// Checks the <see cref="EvolutionMethod"/> for validity by comparing against the <see cref="PKM"/> data.
/// </summary>
/// <param name="pkm">Entity to check</param>
/// <param name="lvl">Current level</param>
/// <param name="skipChecks">Option to skip some comparisons to return a 'possible' evolution.</param>
/// <returns></returns>
public bool Valid(PKM pkm, int lvl, bool skipChecks)
{
RequiresLevelUp = false;
@ -32,39 +38,40 @@ namespace PKHeX.Core
return false;
}
if (!skipChecks && Banlist.Contains((GameVersion)pkm.Version) && pkm.IsUntraded) // sm lacks usum kantonian evos
if (!skipChecks && Banlist.Count > 0 && Banlist.Contains((GameVersion)pkm.Version) && pkm.IsUntraded) // sm lacks usum kantonian evos
return false;
switch (Method)
switch ((EvolutionType)Method)
{
case 8: // Use Item
case 42:
case UseItem:
case UseItemWormhole:
return true;
case 17: // Male
case UseItemMale:
return pkm.Gender == 0;
case 18: // Female
case UseItemFemale:
return pkm.Gender == 1;
case 5: // Trade Evolution
case 6: // Trade while Holding
case 7: // Trade for Opposite Species
case Trade:
case TradeHeldItem:
case TradeSpecies:
return !pkm.IsUntraded || skipChecks;
// Special Levelup Cases
case 16 when !(pkm is IContestStats s) || s.CNT_Beauty < Argument:
// Special Levelup Cases -- return false if invalid
case LevelUpBeauty when !(pkm is IContestStats s) || s.CNT_Beauty < Argument:
return skipChecks;
case 23 when pkm.Gender != 0: // Gender = Male
case LevelUpMale when pkm.Gender != 0:
return false;
case 24 when pkm.Gender != 1: // Gender = Female
case LevelUpFemale when pkm.Gender != 1:
return false;
case 34 when pkm.Gender != 1 || pkm.AltForm != 1: // Gender = Female, out Form1
case LevelUpFormFemale1 when pkm.Gender != 1 || pkm.AltForm != 1:
return false;
case 36 when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: // Any Time on Version
case 37 when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: // Daytime on Version
case 38 when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks: // Nighttime on Version
case LevelUpVersion when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks:
case LevelUpVersionDay when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks:
case LevelUpVersionNight when ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks:
return skipChecks; // Version checks come in pairs, check for any pair match
// Level Up (any); above levelup cases will reach here if they weren't invalid
default:
if (Level == 0 && lvl < 2)
return false;
@ -76,23 +83,30 @@ namespace PKHeX.Core
return lvl >= Level;
// Check Met Level for extra validity
switch (pkm.GenNumber)
{
case 1: // No metdata in RBY
case 2: // No metdata in GS, Crystal metdata can be reset
return true;
case 3:
case 4:
if (pkm.Format > pkm.GenNumber) // Pal Park / PokeTransfer updates Met Level
return true;
return pkm.Met_Level < lvl;
return HasMetLevelIncreased(pkm, lvl);
}
}
case 5: // Bank keeps current level
case 6:
case 7:
return lvl >= Level && (!pkm.IsNative || pkm.Met_Level < lvl);
}
return false;
private bool HasMetLevelIncreased(PKM pkm, int lvl)
{
int origin = pkm.GenNumber;
switch (origin)
{
case 1: // No metdata in RBY
case 2: // No metdata in GS, Crystal metdata can be reset
return true;
case 3:
case 4:
if (pkm.Format > origin) // Pal Park / PokeTransfer updates Met Level
return true;
return pkm.Met_Level < lvl;
case 5: // Bank keeps current level
case 6:
case 7:
return lvl >= Level && (!pkm.IsNative || pkm.Met_Level < lvl);
default: return false;
}
}
@ -107,10 +121,8 @@ namespace PKHeX.Core
};
}
public EvolutionMethod Copy(int species = -1)
public EvolutionMethod Copy(int species)
{
if (species < 0)
species = Species;
return new EvolutionMethod
{
Method = Method,

View file

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
{
@ -38,33 +37,43 @@ namespace PKHeX.Core
case 14: /* Shedinja spawn in Nincada -> Ninjask evolution */
return new EvolutionMethod { Method = method + 1, Species = species, Level = arg, Argument = arg };
}
return null;
throw new ArgumentException(nameof(method));
}
public static List<EvolutionSet> GetArray(byte[] data)
private static readonly EvolutionSet Blank = new EvolutionSet3 { PossibleEvolutions = Array.Empty<EvolutionMethod>() };
public static IReadOnlyList<EvolutionSet> GetArray(byte[] data)
{
EvolutionSet[] evos = new EvolutionSet[Legal.MaxSpeciesID_3 + 1];
evos[0] = new EvolutionSet3 { PossibleEvolutions = new EvolutionMethod[0] };
for (int i = 0; i <= Legal.MaxSpeciesIndex_3; i++)
var evos = new EvolutionSet[Legal.MaxSpeciesID_3 + 1];
evos[0] = Blank;
for (int i = 1; i <= Legal.MaxSpeciesIndex_3; i++)
{
int g4species = SpeciesConverter.GetG4Species(i);
if (g4species == 0)
continue;
int offset = i * 40;
var m_list = new List<EvolutionMethod>();
for (int j = 0; j < 5; j++)
const int maxCount = 5;
const int size = 8;
int offset = i * (maxCount * size);
int count = 0;
for (; count < maxCount; count++)
{
EvolutionMethod m = GetMethod(data, offset);
if (m != null)
m_list.Add(m);
else
if (data[offset + (count * size)] == 0)
break;
offset += 8;
}
evos[g4species] = new EvolutionSet3 { PossibleEvolutions = m_list.ToArray() };
if (count == 0)
{
evos[g4species] = Blank;
continue;
}
var set = new EvolutionMethod[count];
for (int j = 0; j < set.Length; j++)
set[j] = GetMethod(data, offset);
evos[g4species] = new EvolutionSet3 { PossibleEvolutions = set };
}
return evos.ToList();
return evos;
}
}
}

View file

@ -0,0 +1,56 @@
using static PKHeX.Core.EvolutionType;
namespace PKHeX.Core
{
public enum EvolutionType : byte
{
None = 0,
LevelUpFriendship = 1,
LevelUpFriendshipMorning = 2,
LevelUpFriendshipNight = 3,
LevelUp = 4,
Trade = 5,
TradeHeldItem = 6,
TradeSpecies = 7,
UseItem = 8,
LevelUpATK = 9,
LevelUpDEF = 10,
LevelUpAeqD = 11,
LevelUpECl5 = 12,
LevelUpECgeq5 = 13,
LevelUpNinjask = 14,
LevelUpShedinja = 15,
LevelUpBeauty = 16,
UseItemMale = 17,
UseItemFemale = 18,
LevelUpHeldItemDay = 19,
LevelUpHeldItemNight = 20,
LevelUpKnowMove = 21,
LevelUpWithTeammate = 22,
LevelUpMale = 23,
LevelUpFemale = 24,
LevelUpElectric = 25,
LevelUpForest = 26,
LevelUpCold = 27,
LevelUpInverted = 28,
LevelUpAffection50MoveType = 29,
LevelUpMoveType = 30,
LevelUpWeather = 31,
LevelUpMorning = 32,
LevelUpNight = 33,
LevelUpFormFemale1 = 34,
UNUSED = 35,
LevelUpVersion = 36,
LevelUpVersionDay = 37,
LevelUpVersionNight = 38,
LevelUpSummit = 39,
LevelUpDusk = 40,
LevelUpWormhole = 41,
UseItemWormhole = 42,
}
public static class EvolutionTypeExtensions
{
public static bool IsTrade(this EvolutionType t) => t == Trade || t == TradeHeldItem || t == TradeSpecies;
}
}

View file

@ -640,7 +640,7 @@ namespace PKHeX.Core
return gender == 0;
int gen = GenNumber;
if (2 >= gen || gen >= 6)
if (gen <= 2 || gen >= 6)
return gender == (gender & 1);
return gender == PKX.GetGenderFromPIDAndRatio(PID, gv);
@ -669,28 +669,26 @@ namespace PKHeX.Core
/// </summary>
private void ReorderMoves()
{
if (Move4 != 0 && Move3 == 0)
{
Move3 = Move4;
Move3_PP = Move4_PP;
Move3_PPUps = Move4_PPUps;
Move4 = 0;
}
if (Move3 != 0 && Move2 == 0)
{
Move2 = Move3;
Move2_PP = Move3_PP;
Move2_PPUps = Move3_PPUps;
Move3 = 0;
ReorderMoves();
}
if (Move2 != 0 && Move1 == 0)
if (Move1 == 0 && Move2 != 0)
{
Move1 = Move2;
Move1_PP = Move2_PP;
Move1_PPUps = Move2_PPUps;
Move2 = 0;
ReorderMoves();
}
if (Move2 == 0 && Move3 != 0)
{
Move2 = Move3;
Move2_PP = Move3_PP;
Move2_PPUps = Move3_PPUps;
Move3 = 0;
}
if (Move3 == 0 && Move4 != 0)
{
Move3 = Move4;
Move3_PP = Move4_PP;
Move3_PPUps = Move4_PPUps;
Move4 = 0;
}
}

View file

@ -71,6 +71,7 @@ namespace PKHeX.Core
public abstract int Generation { get; }
public PersonalTable Personal { get; set; }
public bool GG => Data.Length == SaveUtil.SIZE_G7GG && GameVersion.GG.Contains(Version);
public bool USUM => Data.Length == SaveUtil.SIZE_G7USUM;
public bool SM => Data.Length == SaveUtil.SIZE_G7SM;
public bool ORASDEMO => Data.Length == SaveUtil.SIZE_G6ORASDEMO;