Simplify encounter move checking

populates a list of possible encounters and iterates over all of them
the encounterstatic / mystery gift loop check was the same, and all they
provided was a set of special moves. Introduces an interface for easy
moveset retrieval.

fix typo in defaultmetlocation var name
add egg check for mystery gifts if transferred (can't transfer eggs
across generations)
This commit is contained in:
Kurt 2017-04-04 22:01:48 -07:00
parent b789478a25
commit d4d896e353
8 changed files with 100 additions and 94 deletions

View file

@ -13,6 +13,7 @@ namespace PKHeX.Core
private object EncounterMatch, EncounterOriginal;
private Type EncounterType;
private bool MatchIsMysteryGift => EncounterMatch.GetType().IsSubclassOf(typeof(MysteryGift));
private bool EncounterIsMysteryGift => EncounterType.IsSubclassOf(typeof (MysteryGift));
private string EncounterName => Legal.getEncounterTypeName(pkm, EncounterOriginal ?? EncounterMatch);
private List<MysteryGift> EventGiftMatch;

View file

@ -2317,14 +2317,8 @@ namespace PKHeX.Core
var validTMHM = Legal.getValidMovesAllGens(pkm, EvoChainsAllGens, LVL: false, Tutor: false, MoveReminder: false, RemoveTransferHM: false);
var validTutor = Legal.getValidMovesAllGens(pkm, EvoChainsAllGens, LVL: false, Machine: false, MoveReminder: false, RemoveTransferHM: false);
Legal.RemoveFutureMoves(pkm, EvoChainsAllGens, ref validLevelMoves, ref validTMHM, ref validTutor);
CheckResult[] res;
int[] Moves = pkm.Moves;
if (!pkm.IsEgg && pkm.Species == 235) // Smeargle can have any move except a few
res = parseMovesSketch(Moves);
else if (pkm.GenNumber < 6)
res = parseMovesPre3DS(game, validLevelMoves, validTMHM, validTutor, Moves);
else
res = parseMoves3DS(game, validLevelMoves, validTMHM, validTutor, Moves);
var res = parseMovesForEncounters(game, validLevelMoves, validTMHM, validTutor, Moves);
// Duplicate Moves Check
verifyNoEmptyDuplicates(Moves, res);
@ -2333,6 +2327,48 @@ namespace PKHeX.Core
return res;
}
private CheckResult[] parseMovesForEncounters(GameVersion game, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor, int[] Moves)
{
if (pkm.Species == 235) // special handling for smeargle
return parseMovesForSmeargle(Moves, validLevelMoves); // smeargle can have any moves except a few
// Gather Encounters
var encounters = new List<object>();
if (null != EventGiftMatch)
encounters.AddRange(EventGiftMatch);
if (null != EncounterStaticMatch)
encounters.AddRange(EncounterStaticMatch);
if (null != EncounterMatch)
encounters.Add(EncounterMatch);
if (!encounters.Any())
return parseMoves(pkm.Moves, validLevelMoves, pkm.RelearnMoves, validTMHM, validTutor, new int[0], new int[0], new int[0], new int[0]);
// Iterate over encounters
CheckResult[] res = new CheckResult[4];
bool pre3DS = pkm.GenNumber < 6;
foreach (var enc in encounters)
{
EncounterMatch = enc;
res = pre3DS
? parseMovesPre3DS(game, validLevelMoves, validTMHM, validTutor, Moves)
: parseMoves3DS(game, validLevelMoves, validTMHM, validTutor, Moves);
if (res.All(x => x.Valid))
break;
}
return res;
}
private CheckResult[] parseMovesForSmeargle(int[] Moves, List<int>[] validLevelMoves)
{
if (!pkm.IsEgg)
return parseMovesSketch(Moves);
// can only know sketch as egg
var empty = new List<int>[EvoChainsAllGens.Length];
for (int i = 0; i < empty.Length; i++)
empty[i] = new List<int>();
return parseMoves(pkm.Moves, validLevelMoves, new int[0], empty, empty, new int[0], new int[0], new int[0], new int[0]);
}
private GameVersion[] getBaseMovesIsEggGames()
{
GameVersion[] Games = { };
@ -2433,6 +2469,10 @@ namespace PKHeX.Core
return res;
}
}
for (int i = 0; i < 4; i++)
if (res[i] == null)
res[i] = new CheckResult(Severity.Invalid, V176, CheckIdentifier.Move);
return res;
}
private CheckResult[] parseMovesWasEggPreRelearn(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor)
@ -2442,11 +2482,9 @@ namespace PKHeX.Core
// Gen 3 could have an egg origin and a non-egg origin, check first non-egg origin
if (pkm.GenNumber == 3 && !pkm.HasOriginalMetLocation && EncounterMatch !=null)
{
res = EncounterStaticMatch?.Count > 1
? parseMovesStaticEncounters(Moves, validLevelMoves, validTMHM, validTutor)
: EventGiftMatch?.Count > 1
? parseMovesGetGift(Moves, validLevelMoves, validTMHM, validTutor) // Multiple possible Mystery Gifts matched, get the best match too
: parseMovesPreRelearnEncounter(Moves, validLevelMoves, validTMHM, validTutor, GameVersion.Any); // Everything else, non-egg encounters only
res = EncounterMatch is IMoveset
? parseMovesSpecialMoveset(Moves, validLevelMoves, validTMHM, validTutor)
: parseMovesPreRelearnEncounter(Moves, validLevelMoves, validTMHM, validTutor); // Everything else, non-egg encounters only
if (res.All(r => r.Valid)) // moves are satisfactory
return res;
// If non-egg encounter is not valid check egg-encounter with eggmoves and without special moves
@ -2489,19 +2527,8 @@ namespace PKHeX.Core
}
private CheckResult[] parseMovesIsEggPreRelearnEvent(int[] Moves)
{
foreach (MysteryGift mg in EventGiftMatch)
{
int[] SpecialMoves = mg.Moves;
CheckResult[] res = parseMovesIsEggPreRelearn(Moves, SpecialMoves, false);
if (res.Any(r => !r.Valid))
continue;
// Match Found
EncounterMatch = mg;
return res;
}
// no Mystery Gifts matched
return parseMovesIsEggPreRelearn(Moves, new int[0], false);
int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0];
return parseMovesIsEggPreRelearn(Moves, SpecialMoves, false);
}
private CheckResult[] parseMovesSketch(int[] Moves)
{
@ -2514,83 +2541,46 @@ namespace PKHeX.Core
}
private CheckResult[] parseMoves3DS(GameVersion game, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor, int[] Moves)
{
if (EventGiftMatch?.Count > 1) // Multiple possible Mystery Gifts matched, get the best match too
return parseMovesGetGift(Moves, validLevelMoves, validTMHM, validTutor);
else if (EncounterStaticMatch?.Count > 1) // Multiple possible Static Encounters matched, get the best match too
return parseMovesStaticEncounters(Moves, validLevelMoves, validTMHM, validTutor);
else if (pkm.WasEgg && Legal.SplitBreed.Contains(pkm.Species))
if (EncounterMatch is IMoveset)
return parseMovesSpecialMoveset(Moves, validLevelMoves, validTMHM, validTutor);
if (pkm.WasEgg && Legal.SplitBreed.Contains(pkm.Species))
return parseMovesRelearnSplitBreed(Moves, validLevelMoves, validTMHM, validTutor, game);
else // Everything else
return parseMovesRelearn(Moves, validLevelMoves, validTMHM, validTutor, 0, game);
// Everything else
return parseMovesRelearn(Moves, validLevelMoves, validTMHM, validTutor, 0, game);
}
private CheckResult[] parseMovesPre3DS(GameVersion game, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor, int[] Moves)
{
if (pkm.IsEgg)
{
if (EventGiftMatch?.Count > 0)
if (MatchIsMysteryGift)
return parseMovesIsEggPreRelearnEvent(Moves);
int[] SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ??
(EncounterMatch as List<EncounterStatic>)?.First().Moves ??
(EncounterMatch as EncounterTrade)?.Moves;
int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves;
var allowinherited = SpecialMoves == null && !pkm.WasGiftEgg && !pkm.WasEventEgg;
return parseMovesIsEggPreRelearn(Moves, SpecialMoves ?? new int[0], allowinherited);
}
if (pkm.WasEgg)
return parseMovesWasEggPreRelearn(Moves, validLevelMoves, validTMHM, validTutor);
if (EventGiftMatch?.Count > 1)
// Multiple possible non-egg Mystery Gifts matched, get the best match too
return parseMovesGetGift(Moves, validLevelMoves, validTMHM, validTutor);
if (EncounterStaticMatch?.Count > 1)
// Multiple possible Static Encounters matched, get the best match too
return parseMovesStaticEncounters(Moves, validLevelMoves, validTMHM, validTutor);
return parseMovesPreRelearnEncounter(Moves, validLevelMoves, validTMHM, validTutor, game);
return parseMovesSpecialMoveset(Moves, validLevelMoves, validTMHM, validTutor);
}
private CheckResult[] parseMovesGetGift(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor)
private CheckResult[] parseMovesSpecialMoveset(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor)
{
int[] RelearnMoves = pkm.GenNumber < 6 ? new int[0] : pkm.RelearnMoves;
foreach (MysteryGift mg in EventGiftMatch)
{
int[] SpecialMoves = mg.Moves;
CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0]);
if (res.Any(r => !r.Valid))
continue;
// Match Found
EncounterMatch = mg;
if(pkm.GenNumber >= 6)
RelearnBase = mg.RelearnMoves;
int[] RelearnMoves = pkm.GenNumber >= 6 ? pkm.RelearnMoves : new int[0];
var mg = EncounterMatch as IMoveset;
int[] SpecialMoves = mg?.Moves ?? new int[0];
CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0]);
if (res.Any(r => !r.Valid))
return res;
}
// no Mystery Gifts matched
return parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, new int[0], new int[0], new int[0], new int[0]);
}
private CheckResult[] parseMovesStaticEncounters(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor)
{
CheckResult[] res = null;
foreach (EncounterStatic stenc in EncounterStaticMatch)
{
int[] SpecialMoves = stenc.Moves;
res = parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0]);
if (res.Any(r => !r.Valid))
continue;
// Match Found
EncounterMatch = stenc;
return res;
}
if (pkm.GenNumber >= 6 && MatchIsMysteryGift)
RelearnBase = (EncounterMatch as MysteryGift).RelearnMoves;
return res;
}
private CheckResult[] parseMovesPreRelearnEncounter(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor, GameVersion game)
private CheckResult[] parseMovesPreRelearnEncounter(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor)
{
int[] SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ??
(EncounterMatch as List<EncounterStatic>)?.First().Moves ??
(EncounterMatch as EncounterTrade)?.Moves ??
new int[0];
int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0];
return parseMoves(Moves, validLevelMoves, new int[0], validTMHM, validTutor, SpecialMoves, new int[0], new int[0], new int[0]);
}
private CheckResult[] parseMovesRelearnSplitBreed(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor, GameVersion game)
@ -2611,10 +2601,7 @@ namespace PKHeX.Core
{
int[] EggMoves = pkm.WasEgg && !pkm.WasGiftEgg && !pkm.WasEventEgg? Legal.getEggMoves(pkm, SkipOption, game).ToArray() : new int[0];
int[] RelearnMoves = pkm.RelearnMoves;
int[] SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ??
(EncounterMatch as List<EncounterStatic>)?.First().Moves ??
(EncounterMatch as EncounterTrade)?.Moves ??
new int[0];
int[] SpecialMoves = (EncounterMatch as IMoveset)?.Moves ?? new int[0];
CheckResult[] res = parseMoves(Moves, validLevelMoves, RelearnMoves, validTMHM, validTutor, SpecialMoves, new int[0], EggMoves, new int[0]);

View file

@ -988,7 +988,7 @@ namespace PKHeX.Core
return false;
if (pkm.HasOriginalMetLocation)
{
z.Location = z.Location > 0 ? z.Location : EncounterTrade.DefalutMetLocation[pkm.GenNumber - 3];
z.Location = z.Location > 0 ? z.Location : EncounterTrade.DefaultMetLocation[pkm.GenNumber - 3];
if (z.Location != pkm.Met_Location)
return false;
if (pkm.Format < 5)
@ -1252,6 +1252,8 @@ namespace PKHeX.Core
int loc = pkm.IsEgg ? pkm.Met_Location : pkm.Egg_Location;
bool valid = loc == 2002; // Link Trade Egg
valid |= loc == 3001 && !pkm.IsShiny; // Ranger & notShiny
if (pkm.IsEgg && !pkm.IsNative) // transferred
valid = false;
if (valid)
validPCD.Add(new PGT { Data = { [0] = 7, [8] = 1 } });
return validPCD;
@ -1277,6 +1279,8 @@ namespace PKHeX.Core
if (wc.Egg_Location + 3000 != pkm.Egg_Location && pkm.Egg_Location != 2002) // traded
continue;
if (wc.CurrentLevel != pkm.Met_Level) continue;
if (!pkm.IsNative)
continue;
}
else
{
@ -1339,6 +1343,8 @@ namespace PKHeX.Core
{
if (wc.EggLocation != pkm.Egg_Location && pkm.Egg_Location != 30002) // traded
continue;
if (!pkm.IsNative)
continue;
}
else
{
@ -1394,6 +1400,8 @@ namespace PKHeX.Core
{
if (wc.EggLocation != pkm.Egg_Location && pkm.Egg_Location != 30002) // traded
continue;
if (!pkm.IsNative)
continue;
}
else
{
@ -1452,6 +1460,8 @@ namespace PKHeX.Core
{
if (wc.EggLocation != pkm.Egg_Location && pkm.Egg_Location != 30002) // traded
continue;
if (!pkm.IsNative)
continue;
}
else
{

View file

@ -1,8 +1,9 @@
namespace PKHeX.Core
{
public class EncounterStatic : IEncounterable
public class EncounterStatic : IEncounterable, IMoveset
{
public int Species { get; set; }
public int[] Moves { get; set; } = new int[4];
public int Level;
public int Location;
@ -10,7 +11,6 @@
public int Form;
public bool? Shiny; // false = never, true = always, null = possible
public int[] Relearn = new int[4];
public int[] Moves = new int[4];
public int Gender = -1;
public int EggLocation;
public Nature Nature = Nature.Random;

View file

@ -1,8 +1,9 @@
namespace PKHeX.Core
{
public class EncounterTrade : IEncounterable
public class EncounterTrade : IEncounterable, IMoveset
{
public int Species { get; set; }
public int[] Moves { get; set; }
public int Level;
public int Location = -1;
@ -13,7 +14,6 @@
public GameVersion Version = GameVersion.Any;
public int[] IVs = { -1, -1, -1, -1, -1, -1 };
public int[] Contest = { 0, 0, 0, 0, 0, 0 };
public int[] Moves;
public int Form = 0;
public bool Shiny = false;
public int Gender = -1;
@ -21,7 +21,7 @@
public string Name => "In-game Trade";
public static readonly int[] DefalutMetLocation =
public static readonly int[] DefaultMetLocation =
{
254, 2001, 30002, 30001, 30001,
};

View file

@ -0,0 +1,7 @@
namespace PKHeX.Core
{
internal interface IMoveset
{
int[] Moves { get; set; }
}
}

View file

@ -3,7 +3,7 @@ using System.Linq;
namespace PKHeX.Core
{
public abstract class MysteryGift : IEncounterable
public abstract class MysteryGift : IEncounterable, IMoveset
{
/// <summary>

View file

@ -164,6 +164,7 @@
<Compile Include="Legality\Structures\EncounterStatic.cs" />
<Compile Include="Legality\Structures\EncounterTrade.cs" />
<Compile Include="Legality\Structures\EvolutionTree.cs" />
<Compile Include="Legality\Structures\IMoveset.cs" />
<Compile Include="Legality\Structures\Learnset.cs" />
<Compile Include="Legality\Structures\Nature.cs" />
<Compile Include="Legality\Structures\SlotType.cs" />