Verify egg moves from gen 2 to 5 pokemon inside egg with a algorithm similar to verify relearn moves.

Egg moves should have fist the base egg moves and after that inherited egg moves, with base egg moves present if there are less that 4 egg moves.
Also for special eggs like gift and events every special moves should be present after base egg moves but should not have any egg move that are not included in the special moves list
This commit is contained in:
javierhimura 2017-03-26 15:39:09 +02:00
parent 8e703e17fb
commit 53984c1807
4 changed files with 211 additions and 19 deletions

View file

@ -2070,12 +2070,24 @@ namespace PKHeX.Core
Legal.RemoveFutureMoves(pkm, EvoChainsAllGens, ref validLevelMoves, ref validTMHM, ref validTutor);
CheckResult[] res;
int[] Moves = pkm.Moves;
if (pkm.Species == 235) // Smeargle can have any move except a few
if (pkm.IsEgg && pkm.GenNumber < 6)
{
if(EventGiftMatch?.Count > 0)
res = verifyMovesEggPreRelearnEvent(Moves);
else
{
var SpecialMoves = (EncounterMatch as MysteryGift)?.Moves ??
(EncounterMatch as EncounterStatic)?.Moves ??
(EncounterMatch as EncounterTrade)?.Moves ??
null;
var allowinherited = SpecialMoves == null;
res = verifyMovesEggPreRelearn(Moves, SpecialMoves ?? new int[0], allowinherited);
}
}
else if (pkm.Species == 235) // Smeargle can have any move except a few
res = parseMovesSketch(Moves);
else if (EventGiftMatch?.Count > 1) // Multiple possible Mystery Gifts matched, get the best match too
res = parseMovesGetGift(Moves, validLevelMoves, validTMHM, validTutor);
else if (pkm.WasEgg && pkm.GenNumber < 6)
res = verifyMovesEggPreRelearn(Moves, validLevelMoves, validTMHM, validTutor);
else // Everything else
res = parseMovesRegular(Moves, validLevelMoves, validTMHM, validTutor, new int[0], game);
@ -2086,11 +2098,8 @@ namespace PKHeX.Core
return res;
}
private CheckResult[] verifyMovesEggPreRelearn(int[] Moves, List<int>[] validLevelMoves, List<int>[] validTMHM, List<int>[] validTutor)
private GameVersion[] getBaseEggGames()
{
CheckResult[] res = new CheckResult[4];
// Some games can have different egg movepools. Have to check all situations.
GameVersion[] Games = { };
switch (pkm.GenNumber)
{
@ -2099,29 +2108,103 @@ namespace PKHeX.Core
Games = new[] { GameVersion.GS, GameVersion.C };
break;
case 3:
Games = new[] { GameVersion.RS, GameVersion.E, GameVersion.FRLG };
switch((GameVersion)pkm.Version)
{
case GameVersion.R:
case GameVersion.S:
Games = new[] { GameVersion.RS};
break;
case GameVersion.E:
Games = new[] { GameVersion.E };
break;
case GameVersion.FR:
case GameVersion.LG:
Games = new[] { GameVersion.FRLG };
break;
}
break;
case 4:
Games = new[] { GameVersion.DP, GameVersion.Pt, GameVersion.HGSS };
switch ((GameVersion)pkm.Version)
{
case GameVersion.D:
case GameVersion.P:
Games = new[] { GameVersion.DP };
break;
case GameVersion.Pt:
Games = new[] { GameVersion.Pt };
break;
case GameVersion.HG:
case GameVersion.SS:
Games = new[] { GameVersion.HGSS };
break;
}
break;
case 5:
Games = new[] { GameVersion.BW, GameVersion.B2W2 };
switch ((GameVersion)pkm.Version)
{
case GameVersion.B:
case GameVersion.W:
Games = new[] { GameVersion.BW };
break;
case GameVersion.Pt:
Games = new[] { GameVersion.Pt };
break;
case GameVersion.B2:
case GameVersion.W2:
Games = new[] { GameVersion.B2W2 };
break;
}
break;
}
int splitctr = Legal.SplitBreed.Contains(pkm.Species) ? 1 : 0;
return Games;
}
private CheckResult[] verifyMovesEggPreRelearn(int[] Moves, int[] SpecialMoves, bool allowinherited)
{
CheckResult[] res = new CheckResult[4];
// Some games can have different egg movepools. Have to check all situations.
GameVersion[] Games = getBaseEggGames();
int splitctr = Legal.getSplitBreedGeneration(pkm).Contains(pkm.Species) ? 1 : 0;
foreach (var ver in Games)
{
for (int i = 0; i <= splitctr; i++)
{
var baseEggMoves = Legal.getBaseEggMoves(pkm, i, ver, 100)?.ToArray() ?? new int[0];
res = parseMovesRegular(Moves, validLevelMoves, validTMHM, validTutor, baseEggMoves, ver);
if (res.All(r => r.Valid)) // moves is satisfactory
return res;
var EggMoves = Legal.getEggMoves(pkm, ver)?.ToList() ?? new List<int>();
if(pkm.Format > 2 || SpecialMoves.Any())
{
// For gen 2 is not possible to difference normal eggs from event eggs
// If there is no special moves assume normal egg
res = verifyPreRelearnEggBase(Moves, baseEggMoves, EggMoves, SpecialMoves, allowinherited, ver);
if (res.All(r => r.Valid)) // moves is satisfactory
return res;
}
if(pkm.Format == 2)
{
// For gen 2 if does not match special egg check for normal egg too
res = verifyPreRelearnEggBase(Moves, baseEggMoves, EggMoves, new int[0], true, ver);
if (res.All(r => r.Valid)) // moves is satisfactory
return res;
}
}
}
return res;
}
private CheckResult[] verifyMovesEggPreRelearnEvent(int[] Moves)
{
foreach (MysteryGift mg in EventGiftMatch)
{
int[] SpecialMoves = mg.Moves;
CheckResult[] res = verifyMovesEggPreRelearn(Moves, SpecialMoves, false);
if (res.Any(r => !r.Valid))
continue;
// Match Found
EncounterMatch = mg;
return res;
}
// no Mystery Gifts matched
return verifyMovesEggPreRelearn(Moves, new int[0], false);
}
private CheckResult[] parseMovesSketch(int[] Moves)
{
CheckResult[] res = new CheckResult[4];
@ -2461,7 +2544,7 @@ namespace PKHeX.Core
}
bool checkAllGames = pkm.WasTradedEgg;
bool splitBreed = Legal.SplitBreed.Contains(pkm.Species);
bool splitBreed = Legal.getSplitBreedGeneration(pkm).Contains(pkm.Species);
int iterate = (checkAllGames ? Games.Length : 1) * (splitBreed ? 2 : 1);
for (int i = 0; i < iterate; i++)
@ -2537,6 +2620,85 @@ namespace PKHeX.Core
return res;
}
/* Similar to verifyRelearnEgg but in pre relearn generation is the moves what should match the expected order
but only if the pokemon is inside an egg */
private CheckResult[] verifyPreRelearnEggBase(int[] Moves, int[] baseMoves, List<int> eggmoves,int[] specialmoves, bool AllowInherited, GameVersion ver)
{
CheckResult[] res = new CheckResult[4];
// Obtain level1 moves
int baseCt = baseMoves.Length;
if (baseCt > 4) baseCt = 4;
// Obtain Inherited moves
var inherited = Moves.Where(m => m != 0 && (!baseMoves.Contains(m) || eggmoves.Contains(m))).ToList();
int inheritCt = inherited.Distinct().Count();
// Get required amount of base moves
int unique = baseMoves.Concat(inherited).Distinct().Count();
int reqBase = inheritCt == 4 || baseCt + inheritCt > 4 ? 4 - inheritCt : baseCt;
if (Moves.Where(m => m != 0).Count() < Math.Min(4, baseMoves.Length))
reqBase = Math.Min(4, unique);
reqBase = reqBase + specialmoves.Length > 4 ? reqBase - specialmoves.Length : reqBase;
var em = string.Empty;
// Check if the required amount of Base Egg Moves are present.
for (int i = 0; i < reqBase; i++)
{
if (baseMoves.Contains(Moves[i]))
res[i] = new CheckResult(Severity.Valid, V179, CheckIdentifier.Move);
else if (specialmoves.Length > 0)
{
// mark remaining base egg moves missing
for (int z = i; z < reqBase; z++)
res[z] = new CheckResult(Severity.Invalid, V180, CheckIdentifier.Move);
// provide the list of suggested base moves for the last required slot
em = string.Join(", ", baseMoves.Select(m => m >= movelist.Length ? V190 : movelist[m]));
break;
}
}
// Check also if the required amount of Special Egg Moves are present, ir are after base moves
for (int i = reqBase; i < specialmoves.Length; i++)
{
if (specialmoves.Contains(Moves[i]))
res[i] = new CheckResult(Severity.Valid, V333, CheckIdentifier.Move);
else
{
// mark remaining special egg moves missing
for (int z = i; z < specialmoves.Length; z++)
res[z] = new CheckResult(Severity.Invalid, V342, CheckIdentifier.Move);
// provide the list of suggested base moves for the last required slot
em = string.Join(", ", baseMoves.Union(specialmoves).Select(m => m >= movelist.Length ? V190 : movelist[m]));
break;
}
}
if(!string.IsNullOrEmpty(em))
res[reqBase > 0 ? reqBase - 1 : 0].Comment += string.Format(Environment.NewLine + V343, em);
// Non-Base moves that can magically appear in the regular movepool
if (Legal.LightBall.Contains(pkm.Species))
eggmoves.Add(344);
// Inherited moves appear after the required base moves.
for (int i = reqBase + specialmoves.Length; i < 4; i++)
{
if (Moves[i] == 0) // empty
res[i] = new CheckResult(Severity.Valid, V167, CheckIdentifier.Move);
else if (AllowInherited && eggmoves.Contains(Moves[i])) // inherited
res[i] = new CheckResult(Severity.Valid, V171, CheckIdentifier.Move);
else if (!AllowInherited && eggmoves.Contains(Moves[i])) // inherited in event/gift pokemon
res[i] = new CheckResult(Severity.Invalid, V341, CheckIdentifier.Move);
else // not inheritable, flag
res[i] = new CheckResult(Severity.Invalid, V340, CheckIdentifier.Move);
}
return res;
}
private void verifyNoEmptyDuplicates(int[] Moves, CheckResult[] res)
{
bool emptySlot = false;

View file

@ -1371,6 +1371,25 @@ namespace PKHeX.Core
return null;
}
}
internal static int[] getSplitBreedGeneration(PKM pkm)
{
return getSplitBreedGeneration(pkm.GenNumber);
}
internal static int[] getSplitBreedGeneration(int generation)
{
switch (generation)
{
case 1: return new int[0];
case 2: return new int[0];
case 3: return SplitBreed_3;
case 4: return SplitBreed;
case 5: return SplitBreed;
case 6: return SplitBreed;
case 7: return SplitBreed;
default: return new int[0];
}
}
internal static int getMaxSpeciesOrigin(PKM pkm)
{
if (pkm.Format == 1 || pkm.VC1) // Gen1 VC could not trade with gen 2 yet
@ -1472,7 +1491,7 @@ namespace PKHeX.Core
var curr = getValidPreEvolutions(pkm);
var poss = getValidPreEvolutions(pkm, 100, skipChecks: true);
if (SplitBreed.Contains(getBaseSpecies(pkm, 1)))
if (getSplitBreedGeneration(pkm).Contains(getBaseSpecies(pkm, 1)))
return curr.Count() >= poss.Count() - 1;
return curr.Count() >= poss.Count();
}

View file

@ -325,7 +325,11 @@ namespace PKHeX.Core
public static string V337 {get; set;} = "Event Egg Move. Incompatible with normal egg moves.";
public static string V338 {get; set;} = "Defog and whirpool. One of the two moves should have been removed before transfered to generation 5.";
public static string V339 {get; set;} = "Generation {0} HM. Should have been removed before transfered to generation {1}.";
public static string V340 {get; set;} = "Not an expected egg move.";
public static string V341 {get; set;} = "Egg Move.Not expected in an event egg.";
public static string V342 {get; set;} = "Event egg move missing.";
public static string V343 {get; set;} = "Expected the following Moves: { 0}";
#endregion
}
}
}

View file

@ -10,7 +10,14 @@ namespace PKHeX.Core
internal const int MaxItemID_3 = 374;
internal const int MaxAbilityID_3 = 77;
internal const int MaxBallID_3 = 0xC;
public static readonly int[] SplitBreed_3 =
{
// Incense
183, 184, // Marill
202, // Wobbuffet
};
#region RS
internal static readonly ushort[] Pouch_Items_RS = {
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 93, 94, 95, 96, 97, 98, 103, 104, 106, 107, 108, 109, 110, 111, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 254, 255, 256, 257, 258