Minor clean

Use some enums, save a few virtual/static fetches
This commit is contained in:
Kurt 2021-01-16 12:01:40 -08:00
parent 15da92f9bc
commit bb1d23e112
8 changed files with 223 additions and 195 deletions

View file

@ -106,7 +106,7 @@ namespace PKHeX.Core
public static void SetRandomEC(this PKM pk)
{
int gen = pk.Generation;
if (2 < gen && gen < 6)
if (gen is 3 or 4 or 5)
{
pk.EncryptionConstant = pk.PID;
return;

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
@ -48,6 +49,19 @@ namespace PKHeX.Core
return ((atk & 3) << 2) | (def & 3);
}
/// <summary>
/// Modifies the provided <see cref="IVs"/> to have the requested <see cref="hiddenPowerType"/> for Generations 1 &amp; 2
/// </summary>
/// <param name="hiddenPowerType">Hidden Power Type</param>
/// <param name="IVs">Current IVs</param>
/// <returns>True if the Hidden Power of the <see cref="IVs"/> is obtained, with or without modifications</returns>
public static bool SetTypeGB(int hiddenPowerType, int[] IVs)
{
IVs[1] = (IVs[1] & ~3) | (hiddenPowerType >> 2);
IVs[2] = (IVs[2] & ~3) | (hiddenPowerType & 3);
return true;
}
/// <summary>
/// Modifies the provided <see cref="IVs"/> to have the requested <see cref="hiddenPowerType"/>.
/// </summary>
@ -58,11 +72,7 @@ namespace PKHeX.Core
public static bool SetIVsForType(int hiddenPowerType, int[] IVs, int format)
{
if (format <= 2)
{
IVs[1] = (IVs[1] & ~3) | (hiddenPowerType >> 2);
IVs[2] = (IVs[2] & ~3) | (hiddenPowerType & 3);
return true;
}
return SetTypeGB(hiddenPowerType, IVs);
return SetIVsForType(hiddenPowerType, IVs);
}
@ -74,7 +84,7 @@ namespace PKHeX.Core
/// <returns>True if the Hidden Power of the <see cref="IVs"/> is obtained, with or without modifications</returns>
public static bool SetIVsForType(int hpVal, int[] IVs)
{
if (IVs.All(z => z == 31))
if (Array.TrueForAll(IVs, z => z == 31))
{
SetIVs(hpVal, IVs); // Get IVs
return true;
@ -101,9 +111,9 @@ namespace PKHeX.Core
var permutations = GetPermutations(flawless, flawless.Length);
int flawedCount = 0;
int[]? best = null;
int[] ivs = (int[])IVs.Clone();
foreach (var permute in permutations)
{
var ivs = (int[])IVs.Clone();
foreach (var item in permute)
{
ivs[item] ^= 1;
@ -115,9 +125,11 @@ namespace PKHeX.Core
break; // any further flaws are always worse
flawedCount = ct;
best = ivs;
best = (int[])ivs.Clone();
break; // any further flaws are always worse
}
// Restore IVs for another iteration
Array.Copy(IVs, 0, ivs, 0, ivs.Length);
}
return best;
}
@ -158,7 +170,7 @@ namespace PKHeX.Core
/// These are just precomputed for fast modification.
/// Individual Values (H/A/B/S/C/D)
/// </remarks>
public static readonly int[,] DefaultLowBits =
public static readonly byte[,] DefaultLowBits =
{
{ 1, 1, 0, 0, 0, 0 }, // Fighting
{ 0, 0, 0, 1, 0, 0 }, // Flying

View file

@ -166,8 +166,9 @@ namespace PKHeX.Core
: ParseMovesWasEggPreRelearn(pkm, currentMoves, info, e);
}
// Not all games have a re-learner. Initial moves may not fill out all 4 slots.
int gen = info.EncounterMatch.Generation;
if (gen <= 2 && (gen == 1 || (gen == 2 && !ParseSettings.AllowGen2MoveReminder(pkm)))) // fixed encounter moves without relearning
if (gen == 1 || (gen == 2 && !AllowGen2MoveReminder(pkm)))
return ParseMovesGenGB(pkm, currentMoves, info);
return ParseMovesSpecialMoveset(pkm, currentMoves, info);
@ -176,13 +177,13 @@ namespace PKHeX.Core
private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, IReadOnlyList<int> currentMoves, LegalInfo info)
{
var res = new CheckMoveResult[4];
var G1Encounter = info.EncounterMatch;
var enc = info.EncounterMatch;
var InitialMoves = Array.Empty<int>();
var SpecialMoves = GetSpecialMoves(info.EncounterMatch);
var games = info.EncounterMatch.Generation == 1 ? GBRestrictions.GetGen1Versions(info) : GBRestrictions.GetGen2Versions(info, pkm.Korean);
var SpecialMoves = GetSpecialMoves(enc);
var games = enc.Generation == 1 ? GBRestrictions.GetGen1Versions(enc) : GBRestrictions.GetGen2Versions(enc, pkm.Korean);
foreach (var ver in games)
{
var VerInitialMoves = MoveLevelUp.GetEncounterMoves(G1Encounter.Species, 0, G1Encounter.LevelMin, ver);
var VerInitialMoves = MoveLevelUp.GetEncounterMoves(enc.Species, 0, enc.LevelMin, ver);
if (VerInitialMoves.Intersect(InitialMoves).Count() == VerInitialMoves.Length)
return res;
@ -546,22 +547,22 @@ namespace PKHeX.Core
{
// Vaporeon in Yellow learns Mist and Haze at level 42, Mist can only be learned if it leveled up in the daycare
// Vaporeon in Red/Blue learns Acid Armor at level 42 and level 47 in Yellow
case (int)Species.Vaporeon when pkm.CurrentLevel < 47 && currentMoves.Contains(151):
case (int)Species.Vaporeon when pkm.CurrentLevel < 47 && currentMoves.Contains((int)Move.AcidArmor):
{
var incompatible = new List<int>(3);
if (currentMoves.Contains(54))
incompatible.Add(54);
if (currentMoves.Contains(114))
incompatible.Add(114);
if (currentMoves.Contains((int)Move.Mist))
incompatible.Add((int)Move.Mist);
if (currentMoves.Contains((int)Move.Haze))
incompatible.Add((int)Move.Haze);
if (incompatible.Count != 0)
incompatible.Add(151);
incompatible.Add((int)Move.AcidArmor);
return incompatible;
}
// Flareon in Yellow learns Smog at level 42
// Flareon in Red Blue learns Leer at level 42 and level 47 in Yellow
case (int)Species.Flareon when pkm.CurrentLevel < 47 && currentMoves.Contains(43) && currentMoves.Contains(123):
return new[] {43, 123};
case (int)Species.Flareon when pkm.CurrentLevel < 47 && currentMoves.Contains((int)Move.Leer) && currentMoves.Contains((int)Move.Smog):
return new[] { (int)Move.Leer, (int)Move.Smog };
default: return Array.Empty<int>();
}
@ -664,25 +665,25 @@ namespace PKHeX.Core
{
case (int)Species.MrMime: // Mr. Mime (Mime Jr with Mimic)
case (int)Species.Sudowoodo: // Sudowoodo (Bonsly with Mimic)
ValidMoves.Add(102);
ValidMoves.Add((int)Move.Mimic);
break;
case (int)Species.Ambipom: // Ambipom (Aipom with Double Hit)
ValidMoves.Add(458);
ValidMoves.Add((int)Move.DoubleHit);
break;
case (int)Species.Lickilicky: // Lickilicky (Lickitung with Rollout)
ValidMoves.Add(205);
ValidMoves.Add((int)Move.Rollout);
break;
case (int)Species.Tangrowth: // Tangrowth (Tangela with Ancient Power)
case (int)Species.Yanmega: // Yanmega (Yanma with Ancient Power)
case (int)Species.Mamoswine: // Mamoswine (Piloswine with Ancient Power)
ValidMoves.Add(246);
ValidMoves.Add((int)Move.AncientPower);
break;
case (int)Species.Sylveon: // Sylveon (Eevee with Fairy Move)
// Add every fairy moves without checking if Eevee learn it or not; pokemon moves are determined legal before this function
ValidMoves.AddRange(EvolutionRestrictions.FairyMoves);
break;
case (int)Species.Tsareena: // Tsareena (Steenee with Stomp)
ValidMoves.Add(023);
ValidMoves.Add((int)Move.Stomp);
break;
}

View file

@ -20,123 +20,103 @@ namespace PKHeX.Core
internal static readonly int[] BabyEvolutionWithMove =
{
122, // Mr. Mime (Mime Jr with Mimic)
185, // Sudowoodo (Bonsly with Mimic)
(int)Species.MrMime, // (Mime Jr with Mimic)
(int)Species.Sudowoodo, // (Bonsly with Mimic)
};
// List of species that evolve from a previous species having a move while leveling up
internal static readonly int[] SpeciesEvolutionWithMove =
{
122, // Mr. Mime (Mime Jr with Mimic)
185, // Sudowoodo (Bonsly with Mimic)
424, // Ambipom (Aipom with Double Hit)
463, // Lickilicky (Lickitung with Rollout)
465, // Tangrowth (Tangela with Ancient Power)
469, // Yanmega (Yamma with Ancient Power)
473, // Mamoswine (Piloswine with Ancient Power)
700, // Sylveon (Eevee with Fairy Move)
763, // Tsareena (Steenee with Stomp)
(int)Species.MrMime, // Mr. Mime (Mime Jr with Mimic)
(int)Species.Sudowoodo, // Sudowoodo (Bonsly with Mimic)
(int)Species.Ambipom, // Ambipom (Aipom with Double Hit)
(int)Species.Lickilicky, // Lickilicky (Lickitung with Rollout)
(int)Species.Tangrowth, // Tangrowth (Tangela with Ancient Power)
(int)Species.Yanmega, // Yanmega (Yamma with Ancient Power)
(int)Species.Mamoswine, // Mamoswine (Piloswine with Ancient Power)
(int)Species.Sylveon, // Sylveon (Eevee with Fairy Move)
(int)Species.Tsareena, // Tsareena (Steenee with Stomp)
(int)Species.Grapploct // (Clobbopus with Taunt)
};
internal static readonly int[] FairyMoves =
{
186, // Sweet Kiss
204, // Charm
236, // Moonlight
574, // Disarming Voice
577, // Draining Kiss
578, // Crafty Shield
579, // Flower Shield
581, // Misty Terrain
583, // Play Rough
584, // Fairy Wind
585, // Moonblast
587, // Fairy Lock
597, // Aromatic Mist
601, // Geomancy
605, // Dazzling Gleam
608, // Baby-Doll Eyes
617, // Light of Ruin
656, // Twinkle Tackle
657, // Twinkle Tackle
666, // Floral Healing
698, // Guardian of Alola
705, // Fleur Cannon
717, // Nature's Madness
726, // Let's Snuggle Forever
740, // Sparkly Swirl
767, // Max Starfall
777, // Decorate
789, // Spirit Break
790, // Strange Steam
802, // Misty Explosion
(int)Move.SweetKiss,
(int)Move.Charm,
(int)Move.Moonlight,
(int)Move.DisarmingVoice,
(int)Move.DrainingKiss,
(int)Move.CraftyShield,
(int)Move.FlowerShield,
(int)Move.MistyTerrain,
(int)Move.PlayRough,
(int)Move.FairyWind,
(int)Move.Moonblast,
(int)Move.FairyLock,
(int)Move.AromaticMist,
(int)Move.Geomancy,
(int)Move.DazzlingGleam,
(int)Move.BabyDollEyes,
(int)Move.LightofRuin,
(int)Move.TwinkleTackleP,
(int)Move.TwinkleTackleS,
(int)Move.FloralHealing,
(int)Move.GuardianofAlola,
(int)Move.FleurCannon,
(int)Move.NaturesMadness,
(int)Move.LetsSnuggleForever,
(int)Move.SparklySwirl,
(int)Move.MaxStarfall,
(int)Move.Decorate,
(int)Move.SpiritBreak,
(int)Move.StrangeSteam,
(int)Move.MistyExplosion,
};
// Moves that trigger the evolution by move
private static readonly int[][] MoveEvolutionWithMove =
{
new [] { 102 }, // Mr. Mime (Mime Jr with Mimic)
new [] { 102 }, // Sudowoodo (Bonsly with Mimic)
new [] { 458 }, // Ambipom (Aipom with Double Hit)
new [] { 205 }, // Lickilicky (Lickitung with Rollout)
new [] { 246 }, // Tangrowth (Tangela with Ancient Power)
new [] { 246 }, // Yanmega (Yamma with Ancient Power)
new [] { 246 }, // Mamoswine (Piloswine with Ancient Power)
new [] { (int)Move.Mimic }, // Mr. Mime (Mime Jr with Mimic)
new [] { (int)Move.Mimic }, // Sudowoodo (Bonsly with Mimic)
new [] { (int)Move.DoubleHit }, // Ambipom (Aipom with Double Hit)
new [] { (int)Move.Rollout }, // Lickilicky (Lickitung with Rollout)
new [] { (int)Move.AncientPower }, // Tangrowth (Tangela with Ancient Power)
new [] { (int)Move.AncientPower }, // Yanmega (Yamma with Ancient Power)
new [] { (int)Move.AncientPower }, // Mamoswine (Piloswine with Ancient Power)
FairyMoves, // Sylveon (Eevee with Fairy Move)
new [] { 023 }, // Tsareena (Steenee with Stomp)
new [] { 269 }, // Grapploct (Clobbopus with Taunt)
new [] { (int)Move.Stomp }, // Tsareena (Steenee with Stomp)
new [] { (int)Move.Taunt }, // Grapploct (Clobbopus with Taunt)
};
// Min level for any species for every generation to learn the move for evolution by move
// 0 means it cant be learned in that generation
private static readonly int[][] MinLevelEvolutionWithMove =
{
// Mr. Mime (Mime Jr with Mimic)
new [] { 0, 0, 0, 0, 18, 15, 15, 2, 2 },
// Sudowoodo (Bonsly with Mimic)
new [] { 0, 0, 0, 0, 17, 17, 15, 2, 2 },
// Ambipom (Aipom with Double Hit)
new [] { 0, 0, 0, 0, 32, 32, 32, 2, 2 },
// Lickilicky (Lickitung with Rollout)
new [] { 0, 0, 2, 0, 2, 33, 33, 2, 2 },
// Tangrowth (Tangela with Ancient Power)
new [] { 0, 0, 0, 0, 2, 36, 38, 2, 2 },
// Yanmega (Yanma with Ancient Power)
new [] { 0, 0, 0, 0, 2, 33, 33, 2, 2 },
// Mamoswine (Piloswine with Ancient Power)
new [] { 0, 0, 0, 0, 2, 2, 2, 2, 2 },
// Sylveon (Eevee with Fairy Move)
new [] { 0, 0, 0, 0, 0, 29, 9, 2, 2 },
// Tsareena (Steenee with Stomp)
new [] { 0, 0, 0, 0, 0, 0, 0, 2, 28 },
// Grapploct (Clobbopus with Taunt)
new [] { 0, 0, 0, 0, 0, 0, 0, 0, 35 },
new [] { 00, 00, 00, 00, 18, 15, 15, 02, 02 }, // Mr. Mime (Mime Jr with Mimic)
new [] { 00, 00, 00, 00, 17, 17, 15, 02, 02 }, // Sudowoodo (Bonsly with Mimic)
new [] { 00, 00, 00, 00, 32, 32, 32, 02, 02 }, // Ambipom (Aipom with Double Hit)
new [] { 00, 00, 02, 00, 02, 33, 33, 02, 02 }, // Lickilicky (Lickitung with Rollout)
new [] { 00, 00, 00, 00, 02, 36, 38, 02, 02 }, // Tangrowth (Tangela with Ancient Power)
new [] { 00, 00, 00, 00, 02, 33, 33, 02, 02 }, // Yanmega (Yanma with Ancient Power)
new [] { 00, 00, 00, 00, 02, 02, 02, 02, 02 }, // Mamoswine (Piloswine with Ancient Power)
new [] { 00, 00, 00, 00, 00, 29, 09, 02, 02 }, // Sylveon (Eevee with Fairy Move)
new [] { 00, 00, 00, 00, 00, 00, 00, 02, 28 }, // Tsareena (Steenee with Stomp)
new [] { 00, 00, 00, 00, 00, 00, 00, 00, 35 }, // Grapploct (Clobbopus with Taunt)
};
// True -> the pokemon could hatch from an egg with the move for evolution as an egg move
private static readonly bool[][] EggMoveEvolutionWithMove =
{
// Mr. Mime (Mime Jr with Mimic)
new [] { false, false, false, false, true, true, true, true, true },
// Sudowoodo (Bonsly with Mimic)
new [] { false, false, false, false, true, true, true, true, true },
// Ambipom (Aipom with Double Hit)
new [] { false, false, false, false, true, true, true, true, true },
// Lickilicky (Lickitung with Rollout)
new [] { false, false, true, false, true, true, true, true, true },
// Tangrowth (Tangela with Ancient Power)
new [] { false, false, false, false, true, true, true, true, true },
// Yanmega (Yanma with Ancient Power)
new [] { false, false, false, false, true, true, true, true, true },
// Mamoswine (Piloswine with Ancient Power)
new [] { false, false, true, true, true, true, true, true, true },
// Sylveon (Eevee with Fairy Move)
new [] { false, false, true, true, true, true, true, true, true },
// Tsareena (Steenee with Stomp)
new [] { false, false, false, false, false, false, false, false, false },
// Grapploct (Clobbopus with Taunt)
new [] { false, false, false, false, false, false, false, false, true },
new [] { false, false, false, false, true, true, true, true, true }, // Mr. Mime (Mime Jr with Mimic)
new [] { false, false, false, false, true, true, true, true, true }, // Sudowoodo (Bonsly with Mimic)
new [] { false, false, false, false, true, true, true, true, true }, // Ambipom (Aipom with Double Hit)
new [] { false, false, true, false, true, true, true, true, true }, // Lickilicky (Lickitung with Rollout)
new [] { false, false, false, false, true, true, true, true, true }, // Tangrowth (Tangela with Ancient Power)
new [] { false, false, false, false, true, true, true, true, true }, // Yanmega (Yanma with Ancient Power)
new [] { false, false, true, true, true, true, true, true, true }, // Mamoswine (Piloswine with Ancient Power)
new [] { false, false, true, true, true, true, true, true, true }, // Sylveon (Eevee with Fairy Move)
new [] { false, false, false, false, false, false, false, false, false }, // Tsareena (Steenee with Stomp)
new [] { false, false, false, false, false, false, false, false, true }, // Grapploct (Clobbopus with Taunt)
};
public static bool IsEvolutionValidWithMove(PKM pkm, LegalInfo info)

View file

@ -4,6 +4,8 @@ using System.Linq;
using PKHeX.Core;
using static PKHeX.Core.Legal;
using static PKHeX.Core.GameVersion;
using static PKHeX.Core.Species;
namespace PKHeX
{
@ -26,20 +28,35 @@ namespace PKHeX
private static readonly HashSet<int> Stadium_GiftSpecies = new()
{
001, // Bulbasaur
004, // Charmander
007, // Squirtle
054, // Psyduck (Amnesia)
106, // Hitmonlee
107, // Hitmonchan
133, // Eevee
138, // Omanyte
140, // Kabuto
(int)Bulbasaur,
(int)Charmander,
(int)Squirtle,
(int)Psyduck,
(int)Hitmonlee,
(int)Hitmonchan,
(int)Eevee,
(int)Omanyte,
(int)Kabuto,
};
private static readonly HashSet<int> SpecialMinMoveSlots = new()
{
25, 26, 29, 30, 31, 32, 33, 34, 36, 38, 40, 59, 91, 103, 114, 121,
(int)Pikachu,
(int)Raichu,
(int)NidoranF,
(int)Nidorina,
(int)Nidoqueen,
(int)NidoranM,
(int)Nidorino,
(int)Nidoking,
(int)Clefable,
(int)Ninetales,
(int)Wigglytuff,
(int)Arcanine,
(int)Cloyster,
(int)Exeggutor,
(int)Tangela,
(int)Starmie,
};
internal static bool TypeIDExists(int type) => Types_Gen1.Contains(type);
@ -49,17 +66,35 @@ namespace PKHeX
0, 1, 2, 3, 4, 5, 7, 8, 20, 21, 22, 23, 24, 25, 26
};
/// <summary>
/// Species that have a catch rate value that is different from their pre-evolutions, and cannot be obtained directly.
/// </summary>
internal static readonly HashSet<int> Species_NotAvailable_CatchRate = new()
{
12, 18, 31, 34, 38, 45, 53, 59, 62, 65, 68, 71, 78, 91, 103, 121
(int)Butterfree,
(int)Pidgeot,
(int)Nidoqueen,
(int)Nidoking,
(int)Ninetales,
(int)Vileplume,
(int)Persian,
(int)Arcanine,
(int)Poliwrath,
(int)Alakazam,
(int)Machamp,
(int)Victreebel,
(int)Rapidash,
(int)Cloyster,
(int)Exeggutor,
(int)Starmie,
};
internal static readonly HashSet<int> Trade_Evolution1 = new()
{
064,
067,
075,
093
(int)Kadabra,
(int)Machoke,
(int)Graveler,
(int)Haunter,
};
private static int[] GetMinLevelLearnMoveG1(int species, List<int> moves)
@ -108,7 +143,7 @@ namespace PKHeX
{
switch (pkm.Species)
{
case (int)Species.Nidoking when moves.Contains(31) && moves.Contains(37):
case (int)Nidoking when moves.Contains(31) && moves.Contains(37):
// Nidoking learns Thrash at level 23
// Nidorino learns Fury Attack at level 36, Nidoran♂ at level 30
// Other moves are either learned by Nidoran♂ up to level 23 or by TM
@ -117,7 +152,7 @@ namespace PKHeX
previousspecies = 33;
return;
case (int)Species.Exeggutor when moves.Contains(23) && moves.Any(m => G1Exeggcute_IncompatibleMoves.Contains(m)):
case (int)Exeggutor when moves.Contains(23) && moves.Any(m => G1Exeggcute_IncompatibleMoves.Contains(m)):
// Exeggutor learns Stomp at level 28
// Exeggcute learns Stun Spore at 32, PoisonPowder at 37 and Sleep Powder at 48
incompatible_current = new[] { 23 };
@ -125,12 +160,12 @@ namespace PKHeX
previousspecies = 103;
return;
case (int)Species.Vaporeon or (int)Species.Jolteon or (int)Species.Flareon:
case (int)Vaporeon or (int)Jolteon or (int)Flareon:
incompatible_previous = new List<int>();
incompatible_current = new List<int>();
previousspecies = 133;
var ExclusiveMoves = GetExclusiveMovesG1((int)Species.Eevee, pkm.Species, tmhm, moves);
var EeveeLevels = GetMinLevelLearnMoveG1((int)Species.Eevee, ExclusiveMoves[0]);
var ExclusiveMoves = GetExclusiveMovesG1((int)Eevee, pkm.Species, tmhm, moves);
var EeveeLevels = GetMinLevelLearnMoveG1((int)Eevee, ExclusiveMoves[0]);
var EvoLevels = GetMaxLevelLearnMoveG1(pkm.Species, ExclusiveMoves[1]);
for (int i = 0; i < ExclusiveMoves[0].Count; i++)
@ -191,15 +226,15 @@ namespace PKHeX
int catch_rate = ((PK1)pk).Catch_Rate;
// Caterpie and Metapod evolution lines have different count of possible slots available if captured in different evolutionary phases
// Example: a level 7 caterpie evolved into metapod will have 3 learned moves, a captured metapod will have only 1 move
if ((species == (int)Species.Metapod || species == (int)Species.Butterfree) && catch_rate == 120)
if ((species == (int)Metapod || species == (int)Butterfree) && catch_rate == 120)
{
// Captured as Metapod without Caterpie moves
return initialmoves.Union(learn[1]).Distinct().Count(lm => lm != 0 && !G1CaterpieMoves.Contains(lm));
// There is no valid Butterfree encounter in generation 1 games
}
if ((species == (int)Species.Kakuna || species == (int)Species.Beedrill) && (catch_rate == 45 || catch_rate == 120))
if ((species == (int)Kakuna || species == (int)Beedrill) && (catch_rate == 45 || catch_rate == 120))
{
if (species == (int)Species.Beedrill && catch_rate == 45) // Captured as Beedril without Weedle and Kakuna moves
if (species == (int)Beedrill && catch_rate == 45) // Captured as Beedril without Weedle and Kakuna moves
return initialmoves.Union(learn[1]).Distinct().Count(lm => lm != 0 && !G1KakunaMoves.Contains(lm));
// Captured as Kakuna without Weedle moves
@ -214,13 +249,13 @@ namespace PKHeX
// Species that evolve and learn the 4th move as evolved species at a greater level than base species
// The 4th move is included in the level up table set as a pre-evolution move,
// it should be removed from the used slots count if is not the learn move
(int)Species.Pidgeotto => level < 21 && !moves.Contains(018), // Whirlwind
(int)Species.Sandslash => level < 27 && !moves.Contains(040), // Poison Sting
(int)Species.Parasect => level < 30 && !moves.Contains(147), // Spore
(int)Species.Golduck => level < 39 && !moves.Contains(093), // Confusion
(int)Species.Dewgong => level < 44 && !moves.Contains(156), // Rest
(int)Species.Weezing => level < 39 && !moves.Contains(108), // Smoke Screen
(int)Species.Haunter or (int) Species.Gengar => level < 29 && !moves.Contains(095), // Hypnosis
(int)Pidgeotto => level < 21 && !moves.Contains(018), // Whirlwind
(int)Sandslash => level < 27 && !moves.Contains(040), // Poison Sting
(int)Parasect => level < 30 && !moves.Contains(147), // Spore
(int)Golduck => level < 39 && !moves.Contains(093), // Confusion
(int)Dewgong => level < 44 && !moves.Contains(156), // Rest
(int)Weezing => level < 39 && !moves.Contains(108), // Smoke Screen
(int)Haunter or (int)Gengar => level < 29 && !moves.Contains(095), // Hypnosis
_ => false,
};
@ -229,20 +264,20 @@ namespace PKHeX
int usedslots = initialmoves.Union(learn[1]).Where(m => m != 0).Distinct().Count();
switch (pk.Species)
{
case (int)Species.Venonat: // Venonat; ignore Venomoth (by the time Venonat evolves it will always have 4 moves)
case (int)Venonat: // Venonat; ignore Venomoth (by the time Venonat evolves it will always have 4 moves)
if (pk.CurrentLevel >= 11 && !moves.Contains(48)) // Supersonic
usedslots--;
if (pk.CurrentLevel >= 19 && !moves.Contains(93)) // Confusion
usedslots--;
break;
case (int)Species.Kadabra or (int)Species.Alakazam: // Abra & Kadabra
case (int)Kadabra or (int)Alakazam: // Abra & Kadabra
int catch_rate = ((PK1)pk).Catch_Rate;
if (catch_rate != 100)// Initial Yellow Kadabra Kinesis (move 134)
usedslots--;
if (catch_rate == 200 && pk.CurrentLevel < 20) // Kadabra Disable, not learned until 20 if captured as Abra (move 50)
usedslots--;
break;
case (int)Species.Cubone or (int)Species.Marowak: // Cubone & Marowak
case (int)Cubone or (int)Marowak: // Cubone & Marowak
if (!moves.Contains(39)) // Initial Yellow Tail Whip
usedslots--;
if (!moves.Contains(125)) // Initial Yellow Bone Club
@ -250,15 +285,15 @@ namespace PKHeX
if (pk.Species == 105 && pk.CurrentLevel < 33 && !moves.Contains(116)) // Marowak evolved without Focus Energy
usedslots--;
break;
case (int)Species.Chansey:
case (int)Chansey:
if (!moves.Contains(39)) // Yellow Initial Tail Whip
usedslots--;
if (!moves.Contains(3)) // Yellow Lvl 12 and Initial Red/Blue Double Slap
usedslots--;
break;
case (int)Species.Mankey when pk.CurrentLevel >= 9 && !moves.Contains(67): // Mankey (Low Kick)
case (int)Species.Pinsir when pk.CurrentLevel >= 21 && !moves.Contains(20): // Pinsir (Bind)
case (int)Species.Gyarados when pk.CurrentLevel < 32: // Gyarados
case (int)Mankey when pk.CurrentLevel >= 9 && !moves.Contains(67): // Mankey (Low Kick)
case (int)Pinsir when pk.CurrentLevel >= 21 && !moves.Contains(20): // Pinsir (Bind)
case (int)Gyarados when pk.CurrentLevel < 32: // Gyarados
usedslots--;
break;
default: return usedslots;
@ -274,17 +309,17 @@ namespace PKHeX
var mandatory = GetRequiredMoveCountLevel(pk);
switch (pk.Species)
{
case (int)Species.Exeggutor when pk.CurrentLevel >= 28: // Exeggutor
case (int)Exeggutor when pk.CurrentLevel >= 28: // Exeggutor
// At level 28 learn different move if is a Exeggute or Exeggutor
if (moves.Contains(73))
mandatory.Add(73); // Leech Seed level 28 Exeggute
if (moves.Contains(23))
mandatory.Add(23); // Stomp level 28 Exeggutor
break;
case (int)Species.Pikachu when pk.CurrentLevel >= 33:
case (int)Pikachu when pk.CurrentLevel >= 33:
mandatory.Add(97); // Pikachu always learns Agility
break;
case (int)Species.Tangela:
case (int)Tangela:
mandatory.Add(132); // Tangela always has Constrict as Initial Move
break;
}
@ -300,12 +335,12 @@ namespace PKHeX
int maxlevel = 1;
int minlevel = 1;
if (species == (int)Species.Tangela) // Tangela moves before level 32 are different in RB vs Y
if (species == (int)Tangela) // Tangela moves before level 32 are different in RB vs Y
{
minlevel = 32;
maxlevel = pk.CurrentLevel;
}
else if ((int)Species.NidoranF <= species && species <= (int)Species.Nidoking && pk.CurrentLevel >= 8)
else if (species is >= (int)NidoranF and <= (int)Nidoking && pk.CurrentLevel >= 8)
{
maxlevel = 8; // Always learns a third move at level 8
}
@ -316,31 +351,31 @@ namespace PKHeX
return MoveLevelUp.GetMovesLevelUp1(basespecies, 0, maxlevel, minlevel);
}
internal static IEnumerable<GameVersion> GetGen2Versions(LegalInfo Info, bool korean)
internal static IEnumerable<GameVersion> GetGen2Versions(IEncounterable enc, bool korean)
{
if (ParseSettings.AllowGen2Crystal(korean) && Info.Game.Contains(GameVersion.C))
yield return GameVersion.C;
yield return GameVersion.GS;
if (ParseSettings.AllowGen2Crystal(korean) && enc.Version is C or GSC)
yield return C;
yield return GS;
}
internal static IEnumerable<GameVersion> GetGen1Versions(LegalInfo Info)
internal static IEnumerable<GameVersion> GetGen1Versions(IEncounterable enc)
{
if (Info.EncounterMatch.Species == (int)Species.Eevee && Info.Game == GameVersion.Stadium)
if (enc.Species == (int)Eevee && enc.Version == Stadium)
{
// Stadium Eevee; check for RB and yellow initial moves
yield return GameVersion.RB;
yield return GameVersion.YW;
yield return RB;
yield return YW;
yield break;
}
if (Info.Game == GameVersion.YW)
if (enc.Version == YW)
{
yield return GameVersion.YW;
yield return YW;
yield break;
}
// Any encounter marked with version RBY is for pokemon with the same moves and catch rate in RB and Y,
// it is sufficient to check just RB's case
yield return GameVersion.RB;
yield return RB;
}
private static bool GetCatchRateMatchesPreEvolution(PKM pkm, int catch_rate, IEnumerable<int> gen1)
@ -352,7 +387,7 @@ namespace PKHeX
// Dragonite's Catch Rate is different than Dragonair's in Yellow, but there is no Dragonite encounter.
bool IsCatchRateRBY(IEnumerable<int> ds) => ds.Any(s => catch_rate == PersonalTable.RB[s].CatchRate || (s != 149 && catch_rate == PersonalTable.Y[s].CatchRate));
// Krabby encounter trade special catch rate
bool IsCatchRateTrade() => catch_rate == 204 && (pkm.Species == (int)Species.Krabby || pkm.Species == (int)Species.Kingler);
bool IsCatchRateTrade() => catch_rate == 204 && (pkm.Species == (int)Krabby || pkm.Species == (int)Kingler);
bool IsCatchRateStadium() => Stadium_GiftSpecies.Contains(pkm.Species) && Stadium_CatchRate.Contains(catch_rate);
}
@ -429,28 +464,27 @@ namespace PKHeX
internal static bool IsTradedKadabraG1(PKM pkm)
{
if (pkm is not PK1 pk1 || pk1.Species != (int)Species.Kadabra)
if (pkm is not PK1 pk1 || pk1.Species != (int)Kadabra)
return false;
if (pk1.TradebackStatus == TradebackType.WasTradeback)
return true;
if (ParseSettings.ActiveTrainer.Game == (int)GameVersion.Any)
if (ParseSettings.ActiveTrainer.Game == (int)Any)
return false;
var IsYellow = ParseSettings.ActiveTrainer.Game == (int)GameVersion.YW;
var IsYellow = ParseSettings.ActiveTrainer.Game == (int)YW;
if (pk1.TradebackStatus == TradebackType.Gen1_NotTradeback)
{
// If catch rate is Abra catch rate it wont trigger as invalid trade without evolution, it could be traded as Abra
// Yellow Kadabra catch rate in Red/Blue game, must be Alakazam
var table = IsYellow ? PersonalTable.RB : PersonalTable.Y;
if (pk1.Catch_Rate == table[(int)Species.Kadabra].CatchRate)
if (pk1.Catch_Rate == table[(int)Kadabra].CatchRate)
return true;
}
if (IsYellow)
return false;
// Yellow only moves in Red/Blue game, must be Alakazam
var moves = pk1.Moves;
if (moves.Contains(134)) // Kinesis, yellow only move
if (pk1.HasMove((int)Move.Kinesis)) // Kinesis, yellow only move
return true;
if (pk1.CurrentLevel < 20 && moves.Contains(50)) // Obtaining Disable below level 20 implies a yellow only move
if (pk1.CurrentLevel < 20 && pk1.HasMove((int)Move.Disable)) // Obtaining Disable below level 20 implies a yellow only move
return true;
return false;

View file

@ -24,8 +24,7 @@ namespace PKHeX.Core
// Check for PID relationship to Gender & Nature if applicable
int gen = data.Info.Generation;
if (3 <= gen && gen <= 5)
if (gen is 3 or 4 or 5)
{
// Gender-PID & Nature-PID relationship check
var result = IsValidGenderPID(data) ? GetValid(LPIDGenderMatch) : GetInvalid(LPIDGenderMismatch);

View file

@ -125,7 +125,7 @@ namespace PKHeX.Core
}
// Gen3-5 => Gen6 have PID==EC with an edge case exception.
if (3 <= Info.Generation && Info.Generation <= 5)
if (Info.Generation is 3 or 4 or 5)
{
VerifyTransferEC(data);
return;

View file

@ -491,12 +491,13 @@ namespace PKHeX.Core
get => 15 * HPBitValType / 63;
set
{
IV_HP = (IV_HP & ~1) + HiddenPower.DefaultLowBits[value, 0];
IV_ATK = (IV_ATK & ~1) + HiddenPower.DefaultLowBits[value, 1];
IV_DEF = (IV_DEF & ~1) + HiddenPower.DefaultLowBits[value, 2];
IV_SPE = (IV_SPE & ~1) + HiddenPower.DefaultLowBits[value, 3];
IV_SPA = (IV_SPA & ~1) + HiddenPower.DefaultLowBits[value, 4];
IV_SPD = (IV_SPD & ~1) + HiddenPower.DefaultLowBits[value, 5];
var dlb = HiddenPower.DefaultLowBits;
IV_HP = (IV_HP & ~1) + dlb[value, 0];
IV_ATK = (IV_ATK & ~1) + dlb[value, 1];
IV_DEF = (IV_DEF & ~1) + dlb[value, 2];
IV_SPE = (IV_SPE & ~1) + dlb[value, 3];
IV_SPA = (IV_SPA & ~1) + dlb[value, 4];
IV_SPD = (IV_SPD & ~1) + dlb[value, 5];
}
}
@ -591,7 +592,8 @@ namespace PKHeX.Core
if (species < 0)
species = Species;
if (Format == generation)
var format = Format;
if (format == generation)
return true;
if (!IsOriginValid)
@ -602,21 +604,21 @@ namespace PKHeX.Core
return false;
// Trade generation 1 -> 2
if (Format == 2 && generation == 1 && !Gen2_NotTradeback)
if (format == 2 && generation == 1 && !Gen2_NotTradeback)
return true;
// Trade generation 2 -> 1
if (Format == 1 && generation == 2 && !Gen1_NotTradeback)
if (format == 1 && generation == 2 && !Gen1_NotTradeback)
return true;
if (Format < generation)
if (format < generation)
return false; // Future
int gen = Generation;
return generation switch
{
1 => Format == 1 || VC, // species compat checked via sanity above
2 => Format == 2 || VC,
1 => format == 1 || VC, // species compat checked via sanity above
2 => format == 2 || VC,
3 => Gen3,
4 => gen is >= 3 and <= 4,
5 => gen is >= 3 and <= 5,