Refactoring

split up current move parsing a little
This commit is contained in:
Kurt 2017-09-01 23:15:57 -07:00
parent 84c90e973e
commit d1aa02fb31
5 changed files with 459 additions and 354 deletions

View File

@ -30,8 +30,7 @@ private static CheckMoveResult[] ParseMovesForEncounters(PKM pkm, LegalInfo info
bool pre3DS = pkm.GenNumber < 6;
// gather valid moves for encounter species
info.EncounterMoves = GetEncounterValidMoves(pkm, info);
info.EncounterMoves = new ValidEncounterMoves(pkm, info);
if (pkm.GenNumber <= 3)
pkm.WasEgg = info.EncounterMatch.EggEncounter;
@ -51,7 +50,7 @@ private static CheckMoveResult[] ParseMovesForEncounters(PKM pkm, LegalInfo info
var res = pre3DS
? ParseMovesPre3DS(pkm, Moves, info)
: ParseMoves3DS(pkm, game, Moves, info);
: ParseMoves3DS(pkm, Moves, info);
if (res.All(x => x.Valid))
return res;
@ -71,79 +70,44 @@ private static CheckMoveResult[] ParseMovesForSmeargle(PKM pkm, int[] Moves, Leg
return ParseMovesSketch(pkm, Moves);
// can only know sketch as egg
info.EncounterMoves = new ValidEncounterMoves
{
LevelUpMoves = Legal.GetValidMovesAllGens(pkm, info.EvoChainsAllGens, minLvLG1: 1, Tutor: false, Machine: false, RemoveTransferHM: false)
};
return ParseMoves(pkm, pkm.Moves, new int[0], new int[0], new int[0], new int[0], new int[0], new int[0], info);
var levelup = Legal.GetValidMovesAllGens(pkm, info.EvoChainsAllGens, minLvLG1: 1, Tutor: false, Machine: false, RemoveTransferHM: false);
info.EncounterMoves = new ValidEncounterMoves(levelup);
var source = new MoveParseSource { CurrentMoves = pkm.Moves, };
return ParseMoves(pkm, source, info);
}
private class MoveInfoSet
private static CheckMoveResult[] ParseMovesIsEggPreRelearn(PKM pkm, int[] Moves, int[] SpecialMoves, EncounterEgg e)
{
public List<int> SpecialMoves { get; set; }
public List<int> EggMoves { get; set; }
public List<int> BaseMoves { get; set; }
public bool AllowInherited { get; set; }
public List<int> TutorMoves { get; set; }
public List<int> TMHMMoves { get; set; }
public List<int> LvlMoves { get; set; }
}
private static CheckMoveResult[] ParseMovesIsEggPreRelearn(PKM pkm, int[] Moves, int[] SpecialMoves, bool allowinherited, EncounterEgg e)
{
CheckMoveResult[] res = new CheckMoveResult[4];
var baseEggMoves = Legal.GetBaseEggMoves(pkm, e.Species, e.Game, pkm.GenNumber < 4 ? 5 : 1)?.ToList() ?? new List<int>();
// Level up moves cannot be inherited if Ditto is parent, thus genderless/single gender species cannot have level up moves as an egg
bool AllowLvlMoves = pkm.PersonalInfo.Gender > 0 && pkm.PersonalInfo.Gender < 255 || Legal.MixedGenderBreeding.Contains(e.Species);
var InheritedLvlMoves = !AllowLvlMoves? new List<int>() : Legal.GetBaseEggMoves(pkm, e.Species, e.Game, 100)?.ToList() ?? new List<int>();
InheritedLvlMoves.RemoveAll(x => baseEggMoves.Contains(x));
var infoset = new MoveInfoSet
{
EggMoves = Legal.GetEggMoves(pkm, e.Species, pkm.AltForm)?.ToList() ?? new List<int>(),
TutorMoves = e.Game == GameVersion.C ? Legal.GetTutorMoves(pkm, pkm.Species, pkm.AltForm, false, 2)?.ToList() : new List<int>(),
TMHMMoves = Legal.GetTMHM(pkm, pkm.Species, pkm.AltForm, pkm.GenNumber, e.Game, false)?.ToList(),
LvlMoves = InheritedLvlMoves,
BaseMoves = baseEggMoves,
SpecialMoves = SpecialMoves.Where(m => m != 0).ToList(),
AllowInherited = allowinherited
};
// Only TM Hm moves from the source game of the egg, not any other games from the same generation
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(pkm, Moves, infoset, e.Game);
}
else if (pkm.Format == 2)
{
infoset.SpecialMoves.Clear();
infoset.AllowInherited = true;
res = VerifyPreRelearnEggBase(pkm, Moves, infoset, e.Game);
}
return res;
EggInfoSource infoset = new EggInfoSource(pkm, SpecialMoves, e);
return VerifyPreRelearnEggBase(pkm, Moves, infoset);
}
private static CheckMoveResult[] ParseMovesWasEggPreRelearn(PKM pkm, int[] Moves, LegalInfo info, EncounterEgg e)
{
var EventEggMoves = GetSpecialMoves(info.EncounterMatch);
// Level up moves could not be inherited if Ditto is parent,
// that means genderless species and male only species except Nidoran and Volbet (they breed with female nidoran and illumise) could not have level up moves as an egg
var inheritLvlMoves = pkm.PersonalInfo.Gender > 0 && pkm.PersonalInfo.Gender < 255 || Legal.MixedGenderBreeding.Contains(e.Species);
int BaseLvlMoves = inheritLvlMoves ? 100 : pkm.GenNumber <= 3 ? 5 : 1;
var LvlupEggMoves = Legal.GetBaseEggMoves(pkm, e.Species, e.Game, BaseLvlMoves);
// that means genderless species and male only species except Nidoran and Volbeat (they breed with female nidoran and illumise) could not have level up moves as an egg
var AllowLevelUp = pkm.PersonalInfo.Gender > 0 && pkm.PersonalInfo.Gender < 255 || Legal.MixedGenderBreeding.Contains(e.Species);
int BaseLevel = AllowLevelUp ? 100 : e.LevelMin;
var LevelUp = Legal.GetBaseEggMoves(pkm, e.Species, e.Game, BaseLevel);
var TradebackPreevo = pkm.Format == 2 && info.EncounterMatch.Species > 151;
var NonTradebackLvlMoves = new int[0];
if (TradebackPreevo)
NonTradebackLvlMoves = Legal.GetExclusivePreEvolutionMoves(pkm, info.EncounterMatch.Species, info.EvoChainsAllGens[2], 2, e.Game).Where(m => m > Legal.MaxMoveID_1).ToArray();
var EggMoves = Legal.GetEggMoves(pkm, e.Species, pkm.AltForm);
var Egg = Legal.GetEggMoves(pkm, e.Species, pkm.AltForm);
bool volt = (pkm.GenNumber > 3 || e.Game == GameVersion.E) && Legal.LightBall.Contains(pkm.Species);
var SpecialMoves = volt && EventEggMoves.Length == 0 ? new[] { 344 } : new int[0]; // Volt Tackle for bred Pichu line
var Special = volt && EventEggMoves.Length == 0 ? new[] { 344 } : new int[0]; // Volt Tackle for bred Pichu line
return ParseMoves(pkm, Moves, SpecialMoves, LvlupEggMoves, EggMoves, NonTradebackLvlMoves, EventEggMoves, new int[0], info);
var source = new MoveParseSource
{
CurrentMoves = Moves,
SpecialSource = Special,
NonTradeBackLevelUpMoves = NonTradebackLvlMoves,
EggLevelUpSource = LevelUp,
EggMoveSource = Egg,
EggEventSource = EventEggMoves,
};
return ParseMoves(pkm, source, info);
}
private static CheckMoveResult[] ParseMovesSketch(PKM pkm, int[] Moves)
{
@ -154,7 +118,7 @@ private static CheckMoveResult[] ParseMovesSketch(PKM pkm, int[] Moves)
: new CheckMoveResult(MoveSource.Sketch, pkm.Format, CheckIdentifier.Move);
return res;
}
private static CheckMoveResult[] ParseMoves3DS(PKM pkm, GameVersion game, int[] Moves, LegalInfo info)
private static CheckMoveResult[] ParseMoves3DS(PKM pkm, int[] Moves, LegalInfo info)
{
info.EncounterMoves.Relearn = pkm.GenNumber >= 6 ? pkm.RelearnMoves : new int[0];
if (info.EncounterMatch is IMoveset)
@ -168,9 +132,7 @@ private static CheckMoveResult[] ParseMovesPre3DS(PKM pkm, int[] Moves, LegalInf
if (pkm.IsEgg && info.EncounterMatch is EncounterEgg egg)
{
int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
// Gift do not have special moves but also should not have normal egg moves
var allowinherited = SpecialMoves == null && !pkm.WasGiftEgg && pkm.Species != 489 && pkm.Species != 490;
return ParseMovesIsEggPreRelearn(pkm, Moves, SpecialMoves, allowinherited, egg);
return ParseMovesIsEggPreRelearn(pkm, Moves, SpecialMoves, egg);
}
var NoMoveReminder = (info.EncounterMatch as IGeneration)?.Generation == 1 || (info.EncounterMatch as IGeneration)?.Generation == 2 && !Legal.AllowGen2MoveReminder;
if (pkm.GenNumber <= 2 && NoMoveReminder)
@ -189,13 +151,19 @@ private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, int[] Moves, LegalInfo
return ParseMovesSpecialMoveset(pkm, Moves, info);
var InitialMoves = new int[0];
int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
var emptyegg = new int[0];
foreach (GameVersion ver in games)
{
var VerInitialMoves = Legal.GetInitialMovesGBEncounter(G1Encounter.Species, G1Encounter.LevelMin, ver).ToArray();
if (VerInitialMoves.SequenceEqual(InitialMoves))
return res;
res = ParseMoves(pkm, Moves, SpecialMoves, emptyegg, emptyegg, emptyegg, new int[0], VerInitialMoves, info);
var source = new MoveParseSource
{
CurrentMoves = Moves,
SpecialSource = SpecialMoves,
Base = VerInitialMoves,
};
res = ParseMoves(pkm, source, info);
if (res.All(r => r.Valid))
return res;
InitialMoves = VerInitialMoves;
@ -204,9 +172,12 @@ private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, int[] Moves, LegalInfo
}
private static CheckMoveResult[] ParseMovesSpecialMoveset(PKM pkm, int[] Moves, LegalInfo info)
{
int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
var emptyegg = new int[0];
return ParseMoves(pkm, Moves, SpecialMoves, emptyegg, emptyegg, emptyegg, new int[0], new int[0], info);
var source = new MoveParseSource
{
CurrentMoves = Moves,
SpecialSource = GetSpecialMoves(info.EncounterMatch),
};
return ParseMoves(pkm, source, info);
}
private static int[] GetSpecialMoves(IEncounterable EncounterMatch)
{
@ -222,251 +193,64 @@ private static int[] GetSpecialMoves(IEncounterable EncounterMatch)
private static CheckMoveResult[] ParseMovesRelearn(PKM pkm, int[] Moves, LegalInfo info)
{
var emptyegg = new int[0];
var source = new MoveParseSource
{
Base = emptyegg,
CurrentMoves = Moves,
SpecialSource = GetSpecialMoves(info.EncounterMatch),
EggLevelUpSource = emptyegg,
EggEventSource = emptyegg,
};
var e = info.EncounterMatch as EncounterEgg;
var EggMoves = e != null ? Legal.GetEggMoves(pkm, e.Species, pkm.AltForm) : emptyegg;
var TradebackPreevo = pkm.Format == 2 && info.EncounterMatch.Species > 151 && pkm.InhabitedGeneration(1);
var NonTradebackLvlMoves = TradebackPreevo ? Legal.GetExclusivePreEvolutionMoves(pkm, info.EncounterMatch.Species, info.EvoChainsAllGens[2], 2, e.Game).Where(m => m > Legal.MaxMoveID_1).ToArray() : new int[0];
if (e != null)
{
source.EggMoveSource = Legal.GetEggMoves(pkm, e.Species, pkm.AltForm);
bool TradebackPreevo = pkm.Format == 2 && info.EncounterMatch.Species > 151 && pkm.InhabitedGeneration(1);
if (TradebackPreevo)
source.NonTradeBackLevelUpMoves = Legal.GetExclusivePreEvolutionMoves(pkm, info.EncounterMatch.Species, info.EvoChainsAllGens[2], 2, e.Game)
.Where(m => m > Legal.MaxMoveID_1).ToArray();
}
CheckMoveResult[] res = ParseMoves(pkm, source, info);
int[] RelearnMoves = pkm.RelearnMoves;
int[] SpecialMoves = GetSpecialMoves(info.EncounterMatch);
CheckMoveResult[] res = ParseMoves(pkm, Moves, SpecialMoves, new int[0], EggMoves, NonTradebackLvlMoves, new int[0], new int[0], info);
for (int i = 0; i < 4; i++)
if ((pkm.IsEgg || res[i].Flag) && !RelearnMoves.Contains(Moves[i]))
res[i] = new CheckMoveResult(res[i], Severity.Invalid, string.Format(V170, res[i].Comment), res[i].Identifier);
return res;
}
private static CheckMoveResult[] ParseMoves(PKM pkm, int[] moves, int[] special, int[] lvlupegg, int[] egg, int[] NonTradebackLvlMoves, int[] eventegg, int[] initialmoves, LegalInfo info)
private static CheckMoveResult[] ParseMoves(PKM pkm, MoveParseSource source, LegalInfo info)
{
CheckMoveResult[] res = new CheckMoveResult[4];
var required = Legal.GetRequiredMoveCount(pkm, moves, info, initialmoves);
bool AllParsed() => res.All(r => r != null);
var required = Legal.GetRequiredMoveCount(pkm, source.CurrentMoves, info, source.Base);
// Check none moves and relearn moves before generation moves
// Check empty moves and relearn moves before generation specific moves
for (int m = 0; m < 4; m++)
{
if (moves[m] == 0)
if (source.CurrentMoves[m] == 0)
res[m] = new CheckMoveResult(MoveSource.None, pkm.Format, m < required ? Severity.Fishy : Severity.Valid, V167, CheckIdentifier.Move);
else if (info.EncounterMoves.Relearn.Contains(moves[m]))
else if (info.EncounterMoves.Relearn.Contains(source.CurrentMoves[m]))
res[m] = new CheckMoveResult(MoveSource.Relearn, pkm.GenNumber, Severity.Valid, V172, CheckIdentifier.Move) { Flag = true };
}
if (res.All(r => r != null))
if (AllParsed())
return res;
bool MixedGen1NonTradebackGen2 = false;
var Gen1MovesLearned = new List<int>();
var Gen2PreevoMovesLearned = new List<int>();
var EggMovesLearned = new List<int>();
var LvlupEggMovesLearned = new List<int>();
var EventEggMovesLearned = new List<int>();
var IsGen2Pkm = pkm.Format == 2 || pkm.VC2;
var IncenseMovesLearned = new List<int>();
// Encapsulate arguments to simplify method calls
var moveInfo = new LearnInfo(pkm) { Source = source };
// Check moves going backwards, marking the move valid in the most current generation when it can be learned
int[] generations = GetGenMovesCheckOrder(pkm);
if (pkm.Format <= 2)
generations = generations.Where(z => z < info.EncounterMoves.LevelUpMoves.Length).ToArray();
int lastgen = generations.Last();
foreach (var gen in generations)
{
var HMLearned = new int[0];
// Check if pokemon knows HM moves from generation 3 and 4 but are not valid yet, that means it cant learn the HMs in future generations
bool KnowDefogWhirlpool = false;
if (gen == 4 && pkm.Format > 4)
{
// Copy to array the hm found or else the list will be emptied when the legal status of moves changes in the current generation
HMLearned = moves.Where((m, i) => !(res[i]?.Valid ?? false) && Legal.HM_4_RemovePokeTransfer.Any(l => l == m)).Select((m, i) => i).ToArray();
// Defog and Whirlpool at the same time, also both can't be learned in future generations or else they will be valid
KnowDefogWhirlpool = moves.Where((m, i) => (m == 250 || m == 432) && !(res[i]?.Valid ?? false)).Count() == 2;
}
else if (gen == 3 && pkm.Format > 3)
HMLearned = moves.Select((m, i) => i).Where(i => !(res[i]?.Valid ?? false) && Legal.HM_3.Any(l => l == moves[i])).ToArray();
bool native = gen == pkm.Format;
for (int m = 0; m < 4; m++)
{
if (res[m]?.Valid ?? false) // already validated with another generation
continue;
if (moves[m] == 0)
continue;
if (gen == 1 && initialmoves.Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.Initial, gen, Severity.Valid, native ? V361 : string.Format(V362, gen), CheckIdentifier.Move);
else if (info.EncounterMoves.LevelUpMoves[gen].Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.LevelUp, gen, Severity.Valid, native ? V177 : string.Format(V330, gen), CheckIdentifier.Move);
else if (info.EncounterMoves.TMHMMoves[gen].Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.TMHM, gen, Severity.Valid, native ? V173 : string.Format(V331, gen), CheckIdentifier.Move);
else if (info.EncounterMoves.TutorMoves[gen].Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.Tutor, gen, Severity.Valid, native ? V174 : string.Format(V332, gen), CheckIdentifier.Move);
else if (gen == pkm.GenNumber && special.Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.Special, gen, Severity.Valid, V175, CheckIdentifier.Move);
if (res[m] == null || gen >= 3)
continue;
if (res[m].Valid && gen == 2 && NonTradebackLvlMoves.Contains(m))
Gen2PreevoMovesLearned.Add(m);
if (res[m].Valid && gen == 1)
{
Gen1MovesLearned.Add(m);
if (Gen2PreevoMovesLearned.Any())
MixedGen1NonTradebackGen2 = true;
}
if (res[m].Valid && gen <= 2 && pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber != gen)
pkm.TradebackStatus = TradebackType.WasTradeback;
}
if (gen == generations.Last())
{
// Check higher-level moves after all the moves but just before egg moves to differentiate it from normal level up moves
// Also check if the base egg moves is a non tradeback move
for (int m = 0; m < 4; m++)
{
if (res[m]?.Valid ?? false) // Skip valid move
continue;
if (moves[m] == 0)
continue;
if (!lvlupegg.Contains(moves[m])) // Check if contains level-up egg moves from parents
continue;
if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1)
{
res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Invalid, V334, CheckIdentifier.Move);
MixedGen1NonTradebackGen2 = true;
}
else
res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Valid, V345, CheckIdentifier.Move);
LvlupEggMovesLearned.Add(m);
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
pkm.TradebackStatus = TradebackType.WasTradeback;
}
// Check egg moves after all the generations and all the moves, every move that can't be learned in another source should have preference
// the moves that can only be learned from egg moves should in the future check if the move combinations can be breed in gens 2 to 5
for (int m = 0; m < 4; m++)
{
if (res[m]?.Valid ?? false)
continue;
if (moves[m] == 0)
continue;
if (egg.Contains(moves[m]))
{
if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1)
{
// To learn exclusive generation 1 moves the pokemon was tradeback, but it can't be trade to generation 1
// without removing moves above MaxMoveID_1, egg moves above MaxMoveID_1 and gen 1 moves are incompatible
res[m] = new CheckMoveResult(MoveSource.EggMove, gen, Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true };
MixedGen1NonTradebackGen2 = true;
}
else
res[m] = new CheckMoveResult(MoveSource.EggMove, gen, Severity.Valid, V171, CheckIdentifier.Move) { Flag = true };
EggMovesLearned.Add(m);
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
pkm.TradebackStatus = TradebackType.WasTradeback;
}
if (!eventegg.Contains(moves[m]))
continue;
if (!egg.Contains(moves[m]))
{
if (IsGen2Pkm && Gen1MovesLearned.Any() && moves[m] > Legal.MaxMoveID_1)
{
res[m] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true };
MixedGen1NonTradebackGen2 = true;
}
else
res[m] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Valid, V333, CheckIdentifier.Move) { Flag = true };
}
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
pkm.TradebackStatus = TradebackType.WasTradeback;
EventEggMovesLearned.Add(m);
}
// A pokemon could have normal egg moves and regular egg moves
// Only if all regular egg moves are event egg moves or all event egg moves are regular egg moves
var RegularEggMovesLearned = EggMovesLearned.Union(LvlupEggMovesLearned).ToList();
if (RegularEggMovesLearned.Any() && EventEggMovesLearned.Any())
{
// Moves that are egg moves or event egg moves but not both
var IncompatibleEggMoves = RegularEggMovesLearned.Except(EventEggMovesLearned).Union(EventEggMovesLearned.Except(RegularEggMovesLearned)).ToList();
if (IncompatibleEggMoves.Any())
{
foreach (int m in IncompatibleEggMoves)
{
if (EventEggMovesLearned.Contains(m) && !EggMovesLearned.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V337, CheckIdentifier.Move);
else if (!EventEggMovesLearned.Contains(m) && EggMovesLearned.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V336, CheckIdentifier.Move);
else if (!EventEggMovesLearned.Contains(m) && LvlupEggMovesLearned.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V358, CheckIdentifier.Move);
}
}
}
// If there is no incompatibility with event egg check that there is no inherited move in gift eggs and event eggs
else if (RegularEggMovesLearned.Any() && (pkm.WasGiftEgg || pkm.WasEventEgg))
{
foreach (int m in RegularEggMovesLearned)
{
if (EggMovesLearned.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, pkm.WasGiftEgg ? V377 : V341, CheckIdentifier.Move);
else if (LvlupEggMovesLearned.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, pkm.WasGiftEgg ? V378 : V347, CheckIdentifier.Move);
}
}
}
if (3 <= gen && gen <= 4 && pkm.Format > gen)
{
// After all the moves from the generations 3 and 4,
// including egg moves if is the origin generation because some hidden moves are also special egg moves in gen 3
// Check if the marked hidden moves that were invalid at the start are now marked as valid, that means
// the hidden move was learned in gen 3 or 4 but was not removed when transfer to 4 or 5
if (KnowDefogWhirlpool)
{
int invalidCount = moves.Where((m, i) => (m == 250 || m == 432) && (res[i]?.Valid ?? false)).Count();
if (invalidCount == 2) // can't know both at the same time
for (int i = 0; i < 4; i++) // flag both moves
if (moves[i] == 250 || moves[i] == 432)
res[i] = new CheckMoveResult(res[i], Severity.Invalid, V338, CheckIdentifier.Move);
}
for (int i = 0; i < HMLearned.Length; i++)
if (res[i]?.Valid ?? false)
res[i] = new CheckMoveResult(res[i], Severity.Invalid, string.Format(V339, gen, gen + 1), CheckIdentifier.Move);
}
// Mark the gen 1 exclusive moves as illegal because the pokemon also have Non tradeback egg moves.
if (MixedGen1NonTradebackGen2)
{
foreach (int m in Gen1MovesLearned)
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V335, CheckIdentifier.Move);
foreach (int m in Gen2PreevoMovesLearned)
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V412, CheckIdentifier.Move);
}
if (gen == 1 && pkm.Format == 1 && pkm.Gen1_NotTradeback)
{
// Check moves learned at the same level in red/blue and yellow, illegal because there is no move reminder
// Only two incompatibilites and only there are no illegal combination if generation 2 or 7 are included in the analysis
ParseRedYellowIncompatibleMoves(pkm, res, moves);
ParseEvolutionsIncompatibleMoves(pkm, res, moves, info.EncounterMoves.TMHMMoves[1]);
}
if (Legal.SpeciesEvolutionWithMove.Contains(pkm.Species))
{
// Pokemon that evolved by leveling up while learning a specific move
// This pokemon could only have 3 moves from preevolutions that are not the move used to evolved
// including special and eggs moves before realearn generations
ParseEvolutionLevelupMove(pkm, res, moves, IncenseMovesLearned, info);
}
if (res.All(r => r != null))
ParseMovesByGeneration(pkm, res, gen, info, moveInfo, lastgen);
if (AllParsed())
return res;
}
@ -475,7 +259,7 @@ private static CheckMoveResult[] ParseMoves(PKM pkm, int[] moves, int[] special,
// Ignore Shedinja if the Encounter was also a Shedinja, assume null Encounter as a Nincada egg
// Check Shedinja evolved moves from Ninjask after egg moves
// Those moves could also be inherited egg moves
ParseShedinjaEvolveMoves(pkm, res, moves);
ParseShedinjaEvolveMoves(pkm, res, source.CurrentMoves);
}
for (int m = 0; m < 4; m++)
@ -485,28 +269,228 @@ private static CheckMoveResult[] ParseMoves(PKM pkm, int[] moves, int[] special,
}
return res;
}
private static void ParseMovesByGeneration(PKM pkm, CheckMoveResult[] res, int gen, LegalInfo info, LearnInfo learnInfo, int last)
{
GetHMCompatibility(pkm, learnInfo.Source.CurrentMoves, gen, res, out bool[] HMLearned, out bool KnowDefogWhirlpool);
ParseMovesByGeneration(pkm, res, gen, info, learnInfo);
if (gen == last)
ParseMovesByGenerationLast(pkm, res, gen, learnInfo);
switch (gen)
{
case 3:
case 4:
if (pkm.Format > gen)
FlagIncompatibleTransferHMs(res, learnInfo.Source.CurrentMoves, gen, HMLearned, KnowDefogWhirlpool);
break;
case 1:
case 2:
ParseMovesByGeneration12(pkm, res, learnInfo.Source.CurrentMoves, gen, info, learnInfo);
break;
}
// Pokemon that evolved by leveling up while learning a specific move
// This pokemon could only have 3 moves from preevolutions that are not the move used to evolved
// including special and eggs moves before realearn generations
if (Legal.SpeciesEvolutionWithMove.Contains(pkm.Species))
ParseEvolutionLevelupMove(pkm, res, learnInfo.Source.CurrentMoves, learnInfo.IncenseMoves, info);
}
private static void ParseMovesByGeneration(PKM pkm, CheckMoveResult[] res, int gen, LegalInfo info, LearnInfo learnInfo)
{
var moves = learnInfo.Source.CurrentMoves;
bool native = gen == pkm.Format;
for (int m = 0; m < 4; m++)
{
if (IsCheckValid(res[m])) // already validated with another generation
continue;
if (moves[m] == 0)
continue;
if (gen == 1 && learnInfo.Source.Base.Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.Initial, gen, Severity.Valid, native ? V361 : string.Format(V362, gen), CheckIdentifier.Move);
else if (info.EncounterMoves.LevelUpMoves[gen].Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.LevelUp, gen, Severity.Valid, native ? V177 : string.Format(V330, gen), CheckIdentifier.Move);
else if (info.EncounterMoves.TMHMMoves[gen].Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.TMHM, gen, Severity.Valid, native ? V173 : string.Format(V331, gen), CheckIdentifier.Move);
else if (info.EncounterMoves.TutorMoves[gen].Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.Tutor, gen, Severity.Valid, native ? V174 : string.Format(V332, gen), CheckIdentifier.Move);
else if (gen == pkm.GenNumber && learnInfo.Source.SpecialSource.Contains(moves[m]))
res[m] = new CheckMoveResult(MoveSource.Special, gen, Severity.Valid, V175, CheckIdentifier.Move);
if (res[m] == null || gen >= 3)
continue;
if (res[m].Valid && gen == 2 && learnInfo.Source.NonTradeBackLevelUpMoves.Contains(m))
learnInfo.Gen2PreevoMoves.Add(m);
if (res[m].Valid && gen == 1)
{
learnInfo.Gen1Moves.Add(m);
if (learnInfo.Gen2PreevoMoves.Any())
learnInfo.MixedGen12NonTradeback = true;
}
if (res[m].Valid && gen <= 2 && pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber != gen)
pkm.TradebackStatus = TradebackType.WasTradeback;
}
}
private static void ParseMovesByGeneration12(PKM pkm, CheckMoveResult[] res, int[] moves, int gen, LegalInfo info, LearnInfo learnInfo)
{
// Mark the gen 1 exclusive moves as illegal because the pokemon also have Non tradeback egg moves.
if (learnInfo.MixedGen12NonTradeback)
{
foreach (int m in learnInfo.Gen1Moves)
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V335, CheckIdentifier.Move);
foreach (int m in learnInfo.Gen2PreevoMoves)
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V412, CheckIdentifier.Move);
}
if (gen == 1 && pkm.Format == 1 && pkm.Gen1_NotTradeback)
{
ParseRedYellowIncompatibleMoves(pkm, res, moves);
ParseEvolutionsIncompatibleMoves(pkm, res, moves, info.EncounterMoves.TMHMMoves[1]);
}
}
private static void ParseMovesByGenerationLast(PKM pkm, CheckMoveResult[] res, int gen, LearnInfo learnInfo)
{
ParseEggMovesInherited(pkm, res, gen, learnInfo);
ParseEggMoves(pkm, res, gen, learnInfo);
ParseEggMovesRemaining(pkm, res, learnInfo);
}
private static void ParseEggMovesInherited(PKM pkm, CheckMoveResult[] res, int gen, LearnInfo learnInfo)
{
var moves = learnInfo.Source.CurrentMoves;
// Check higher-level moves after all the moves but just before egg moves to differentiate it from normal level up moves
// Also check if the base egg moves is a non tradeback move
for (int m = 0; m < 4; m++)
{
if (res[m]?.Valid ?? false) // Skip valid move
continue;
if (moves[m] == 0)
continue;
if (!learnInfo.Source.EggLevelUpSource.Contains(moves[m])) // Check if contains level-up egg moves from parents
continue;
if (learnInfo.IsGen2Pkm && learnInfo.Gen1Moves.Any() && moves[m] > Legal.MaxMoveID_1)
{
res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Invalid, V334, CheckIdentifier.Move);
learnInfo.MixedGen12NonTradeback = true;
}
else
res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Valid, V345, CheckIdentifier.Move);
learnInfo.LevelUpEggMoves.Add(m);
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
pkm.TradebackStatus = TradebackType.WasTradeback;
}
}
private static void ParseEggMoves(PKM pkm, CheckMoveResult[] res, int gen, LearnInfo learnInfo)
{
var moves = learnInfo.Source.CurrentMoves;
// Check egg moves after all the generations and all the moves, every move that can't be learned in another source should have preference
// the moves that can only be learned from egg moves should in the future check if the move combinations can be breed in gens 2 to 5
for (int m = 0; m < 4; m++)
{
if (IsCheckValid(res[m]))
continue;
if (moves[m] == 0)
continue;
if (learnInfo.Source.EggMoveSource.Contains(moves[m]))
{
// To learn exclusive generation 1 moves the pokemon was tradeback, but it can't be trade to generation 1
// without removing moves above MaxMoveID_1, egg moves above MaxMoveID_1 and gen 1 moves are incompatible
if (learnInfo.IsGen2Pkm && learnInfo.Gen1Moves.Any() && moves[m] > Legal.MaxMoveID_1)
{
res[m] = new CheckMoveResult(MoveSource.EggMove, gen, Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true };
learnInfo.MixedGen12NonTradeback = true;
}
else
res[m] = new CheckMoveResult(MoveSource.EggMove, gen, Severity.Valid, V171, CheckIdentifier.Move) { Flag = true };
learnInfo.EggMovesLearned.Add(m);
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
pkm.TradebackStatus = TradebackType.WasTradeback;
}
if (!learnInfo.Source.EggEventSource.Contains(moves[m]))
continue;
if (!learnInfo.Source.EggMoveSource.Contains(moves[m]))
{
if (learnInfo.IsGen2Pkm && learnInfo.Gen1Moves.Any() && moves[m] > Legal.MaxMoveID_1)
{
res[m] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Invalid, V334, CheckIdentifier.Move) { Flag = true };
learnInfo.MixedGen12NonTradeback = true;
}
else
res[m] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Valid, V333, CheckIdentifier.Move) { Flag = true };
}
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
pkm.TradebackStatus = TradebackType.WasTradeback;
learnInfo.EventEggMoves.Add(m);
}
}
private static void ParseEggMovesRemaining(PKM pkm, CheckMoveResult[] res, LearnInfo learnInfo)
{
// A pokemon could have normal egg moves and regular egg moves
// Only if all regular egg moves are event egg moves or all event egg moves are regular egg moves
var RegularEggMovesLearned = learnInfo.EggMovesLearned.Union(learnInfo.LevelUpEggMoves).ToList();
if (RegularEggMovesLearned.Any() && learnInfo.EventEggMoves.Any())
{
// Moves that are egg moves or event egg moves but not both
var IncompatibleEggMoves = RegularEggMovesLearned.Except(learnInfo.EventEggMoves).Union(learnInfo.EventEggMoves.Except(RegularEggMovesLearned)).ToList();
if (!IncompatibleEggMoves.Any())
return;
foreach (int m in IncompatibleEggMoves)
{
if (learnInfo.EventEggMoves.Contains(m) && !learnInfo.EggMovesLearned.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V337, CheckIdentifier.Move);
else if (!learnInfo.EventEggMoves.Contains(m) && learnInfo.EggMovesLearned.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V336, CheckIdentifier.Move);
else if (!learnInfo.EventEggMoves.Contains(m) && learnInfo.LevelUpEggMoves.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V358, CheckIdentifier.Move);
}
}
// If there is no incompatibility with event egg check that there is no inherited move in gift eggs and event eggs
else if (RegularEggMovesLearned.Any() && (pkm.WasGiftEgg || pkm.WasEventEgg))
{
foreach (int m in RegularEggMovesLearned)
{
if (learnInfo.EggMovesLearned.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, pkm.WasGiftEgg ? V377 : V341, CheckIdentifier.Move);
else if (learnInfo.LevelUpEggMoves.Contains(m))
res[m] = new CheckMoveResult(res[m], Severity.Invalid, pkm.WasGiftEgg ? V378 : V347, CheckIdentifier.Move);
}
}
}
private static void ParseRedYellowIncompatibleMoves(PKM pkm, IList<CheckMoveResult> res, int[] moves)
{
// Check moves that are learned at the same level in red/blue and yellow, these are illegal because there is no move reminder
// There are only two incompatibilites; there is no illegal combination in generation 2+.
var incompatible = new List<int>();
if (pkm.Species == 134 && pkm.CurrentLevel < 47 && moves.Contains(151))
switch (pkm.Species)
{
// Vaporeon in Yellow learn Mist and Haze at level 42, Mist only if level up in day-care
// Vaporeon in Red Blue learn Acid Armor at level 42 and level 47 in Yellow
if (moves.Contains(54))
incompatible.Add(54);
if (moves.Contains(114))
incompatible.Add(114);
if (incompatible.Any())
incompatible.Add(151);
}
if (pkm.Species == 136 && pkm.CurrentLevel < 47 && moves.Contains(43) && moves.Contains(123))
{
// Flareon in Yellow learn Smog at level 42
// Flareon in Red Blue learn Leer at level 42 and level 47 in Yellow
incompatible.Add(43);
incompatible.Add(123);
// Vaporeon in Yellow learns Mist and Haze at level 42, Mist can only be larned if it levels up in the daycare
// Vaporeon in Red/Blue learns Acid Armor at level 42 and level 47 in Yellow
case 134 when pkm.CurrentLevel < 47 && moves.Contains(151):
if (moves.Contains(54))
incompatible.Add(54);
if (moves.Contains(114))
incompatible.Add(114);
if (incompatible.Any())
incompatible.Add(151);
break;
// Flareon in Yellow learns Smog at level 42
// Flareon in Red Blue learns Leer at level 42 and level 47 in Yellow
case 136 when pkm.CurrentLevel < 47 && moves.Contains(43) && moves.Contains(123):
incompatible.Add(43);
incompatible.Add(123);
break;
}
for (int m = 0; m < 4; m++)
{
if (incompatible.Contains(moves[m]))
@ -636,31 +620,74 @@ private static void ParseEvolutionLevelupMove(PKM pkm, IList<CheckMoveResult> re
for (int m = 0; m < 4; m++)
res[m] = new CheckMoveResult(res[m], Severity.Invalid, string.Format(V385, SpeciesStrings[pkm.Species]), CheckIdentifier.Move);
}
private static void GetHMCompatibility(PKM pkm, int[] moves, int gen, IReadOnlyList<CheckResult> res, out bool[] HMLearned, out bool KnowDefogWhirlpool)
{
HMLearned = new bool[4];
// Check if pokemon knows HM moves from generation 3 and 4 but are not valid yet, that means it cant learn the HMs in future generations
if (gen == 4 && pkm.Format > 4)
{
IsHMSource(ref HMLearned, Legal.HM_4_RemovePokeTransfer);
KnowDefogWhirlpool = moves.Where((m, i) => IsDefogWhirl(m) && IsCheckInvalid(res[i])).Count() == 2;
return;
}
KnowDefogWhirlpool = false;
if (gen == 3 && pkm.Format > 3)
IsHMSource(ref HMLearned, Legal.HM_3);
void IsHMSource(ref bool[] flags, int[] source)
{
for (int i = 0; i < 4; i++)
flags[i] = IsCheckInvalid(res[i]) && source.Contains(moves[i]);
}
}
private static bool IsDefogWhirl(int move) => move == 250 || move == 432;
private static bool IsCheckInvalid(CheckResult chk) => !(chk?.Valid ?? false);
private static bool IsCheckValid(CheckResult chk) => chk?.Valid ?? false;
private static void FlagIncompatibleTransferHMs(CheckMoveResult[] res, int[] moves, int gen, bool[] HMLearned, bool KnowDefogWhirlpool)
{
// After all the moves from the generations 3 and 4,
// including egg moves if is the origin generation because some hidden moves are also special egg moves in gen 3
// Check if the marked hidden moves that were invalid at the start are now marked as valid, that means
// the hidden move was learned in gen 3 or 4 but was not removed when transfer to 4 or 5
if (KnowDefogWhirlpool)
{
int invalidCount = moves.Where((m, i) => IsDefogWhirl(m) && IsCheckValid(res[i])).Count();
if (invalidCount == 2) // can't know both at the same time
for (int i = 0; i < 4; i++) // flag both moves
if (IsDefogWhirl(moves[i]))
res[i] = new CheckMoveResult(res[i], Severity.Invalid, V338, CheckIdentifier.Move);
}
// Flag moves that are only legal when learned from a past-gen HM source
for (int i = 0; i < HMLearned.Length; i++)
if (HMLearned[i] && IsCheckValid(res[i]))
res[i] = new CheckMoveResult(res[i], Severity.Invalid, string.Format(V339, gen, gen + 1), CheckIdentifier.Move);
}
/* 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 static CheckMoveResult[] VerifyPreRelearnEggBase(PKM pkm, int[] Moves, MoveInfoSet infoset, GameVersion ver)
private static CheckMoveResult[] VerifyPreRelearnEggBase(PKM pkm, int[] Moves, EggInfoSource infoset)
{
CheckMoveResult[] res = new CheckMoveResult[4];
var gen = pkm.GenNumber;
// Obtain level1 moves
int baseCt = infoset.BaseMoves.Count;
int baseCt = infoset.Base.Count;
if (baseCt > 4) baseCt = 4;
// Obtain Inherited moves
var inherited = Moves.Where(m => m != 0 && (!infoset.BaseMoves.Contains(m) || infoset.SpecialMoves.Contains(m) || infoset.EggMoves.Contains(m) || infoset.LvlMoves.Contains(m) || infoset.TMHMMoves.Contains(m) || infoset.TutorMoves.Contains(m))).ToList();
var inherited = Moves.Where(m => m != 0 && (!infoset.Base.Contains(m) || infoset.Special.Contains(m) || infoset.Egg.Contains(m) || infoset.LevelUp.Contains(m) || infoset.TMHM.Contains(m) || infoset.Tutor.Contains(m))).ToList();
int inheritCt = inherited.Count;
// Get required amount of base moves
int unique = infoset.BaseMoves.Concat(inherited).Distinct().Count();
int unique = infoset.Base.Concat(inherited).Distinct().Count();
int reqBase = inheritCt == 4 || baseCt + inheritCt > 4 ? 4 - inheritCt : baseCt;
if (Moves.Where(m => m != 0).Count() < Math.Min(4, infoset.BaseMoves.Count))
if (Moves.Where(m => m != 0).Count() < Math.Min(4, infoset.Base.Count))
reqBase = Math.Min(4, unique);
var em = string.Empty;
// Check if the required amount of Base Egg Moves are present.
for (int i = 0; i < reqBase; i++)
{
if (infoset.BaseMoves.Contains(Moves[i]))
if (infoset.Base.Contains(Moves[i]))
{
res[i] = new CheckMoveResult(MoveSource.Initial, gen, Severity.Valid, V179, CheckIdentifier.Move);
continue;
@ -671,16 +698,16 @@ private static CheckMoveResult[] VerifyPreRelearnEggBase(PKM pkm, int[] Moves, M
res[z] = new CheckMoveResult(MoveSource.Initial, gen, Severity.Invalid, V180, CheckIdentifier.Move);
// provide the list of suggested base moves for the last required slot
em = string.Join(", ", infoset.BaseMoves.Select(m => m >= MoveStrings.Length ? V190 : MoveStrings[m]));
em = string.Join(", ", infoset.Base.Select(m => m >= MoveStrings.Length ? V190 : MoveStrings[m]));
break;
}
int moveoffset = reqBase;
int endSpecial = moveoffset + infoset.SpecialMoves.Count;
int endSpecial = moveoffset + infoset.Special.Count;
// Check also if the required amount of Special Egg Moves are present, ir are after base moves
for (int i = moveoffset; i < endSpecial; i++)
{
if (infoset.SpecialMoves.Contains(Moves[i]))
if (infoset.Special.Contains(Moves[i]))
{
res[i] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Valid, V333, CheckIdentifier.Move);
continue;
@ -693,30 +720,27 @@ private static CheckMoveResult[] VerifyPreRelearnEggBase(PKM pkm, int[] Moves, M
// provide the list of suggested base moves and species moves for the last required slot
if (!string.IsNullOrEmpty(em)) em += ", ";
else
em = string.Join(", ", infoset.BaseMoves.Select(m => m >= MoveStrings.Length ? V190 : MoveStrings[m])) + ", ";
em += string.Join(", ", infoset.SpecialMoves.Select(m => m >= MoveStrings.Length ? V190 : MoveStrings[m]));
em = string.Join(", ", infoset.Base.Select(m => m >= MoveStrings.Length ? V190 : MoveStrings[m])) + ", ";
em += string.Join(", ", infoset.Special.Select(m => m >= MoveStrings.Length ? V190 : MoveStrings[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 (pkm.GenNumber >= 3 && Legal.LightBall.Contains(pkm.Species))
infoset.EggMoves.Add(344);
// Inherited moves appear after the required base moves.
var AllowInheritedSeverity = infoset.AllowInherited ? Severity.Valid : Severity.Invalid;
for (int i = reqBase + infoset.SpecialMoves.Count; i < 4; i++)
for (int i = reqBase + infoset.Special.Count; i < 4; i++)
{
if (Moves[i] == 0) // empty
res[i] = new CheckMoveResult(MoveSource.None, gen, Severity.Valid, V167, CheckIdentifier.Move);
else if (infoset.EggMoves.Contains(Moves[i])) // inherited egg move
else if (infoset.Egg.Contains(Moves[i])) // inherited egg move
res[i] = new CheckMoveResult(MoveSource.EggMove, gen, AllowInheritedSeverity, infoset.AllowInherited ? V344 : V341, CheckIdentifier.Move);
else if (infoset.LvlMoves.Contains(Moves[i])) // inherited lvl moves
else if (infoset.LevelUp.Contains(Moves[i])) // inherited lvl moves
res[i] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, AllowInheritedSeverity, infoset.AllowInherited ? V345 : V347, CheckIdentifier.Move);
else if (infoset.TMHMMoves.Contains(Moves[i])) // inherited TMHM moves
else if (infoset.TMHM.Contains(Moves[i])) // inherited TMHM moves
res[i] = new CheckMoveResult(MoveSource.TMHM, gen, AllowInheritedSeverity, infoset.AllowInherited ? V349 : V350, CheckIdentifier.Move);
else if (infoset.TutorMoves.Contains(Moves[i])) // inherited tutor moves
else if (infoset.Tutor.Contains(Moves[i])) // inherited tutor moves
res[i] = new CheckMoveResult(MoveSource.Tutor, gen, AllowInheritedSeverity, infoset.AllowInherited ? V346 : V348, CheckIdentifier.Move);
else // not inheritable, flag
res[i] = new CheckMoveResult(MoveSource.Unknown, gen, Severity.Invalid, V340, CheckIdentifier.Move);
@ -778,26 +802,5 @@ private static int[] GetGenMovesCheckOrder(PKM pkm)
order[i] = pkm.Format - i;
return order;
}
private static ValidEncounterMoves GetEncounterValidMoves(PKM pkm, LegalInfo info)
{
var minLvLG1 = pkm.GenNumber <= 2 ? info.EncounterMatch.LevelMin + 1 : 0;
var minLvlG2 = Legal.AllowGen2MoveReminder ? 1 : info.EncounterMatch.LevelMin + 1;
var encounterspecies = info.EncounterMatch.Species;
var EvoChainsAllGens = info.EvoChainsAllGens;
// If encounter species is the same species from the first match, the one in variable EncounterMatch, its evolution chains is already in EvoChainsAllGens
var LevelMoves = Legal.GetValidMovesAllGens(pkm, EvoChainsAllGens, minLvLG1: minLvLG1, minLvLG2: minLvlG2, Tutor: false, Machine: false, RemoveTransferHM: false);
var TMHMMoves = Legal.GetValidMovesAllGens(pkm, EvoChainsAllGens, LVL: false, Tutor: false, MoveReminder: false, RemoveTransferHM: false);
var TutorMoves = Legal.GetValidMovesAllGens(pkm, EvoChainsAllGens, LVL: false, Machine: false, MoveReminder: false, RemoveTransferHM: false);
return new ValidEncounterMoves
{
EncounterSpecies = encounterspecies,
LevelUpMoves = LevelMoves,
TMHMMoves = TMHMMoves,
TutorMoves = TutorMoves,
EvolutionChains = EvoChainsAllGens,
MinimumLevelGen1 = minLvLG1,
MinimumLevelGen2 = minLvlG2
};
}
}
}

View File

@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
{
internal class EggInfoSource
{
public EggInfoSource(PKM pkm, IEnumerable<int> specialMoves, EncounterEgg e)
{
// Eggs with special moves cannot inherit levelup moves as the current moves are predefined.
Special = specialMoves.Where(m => m != 0).ToList();
bool notSpecial = Special.Count == 0;
AllowInherited = notSpecial && !pkm.WasGiftEgg && pkm.Species != 489 && pkm.Species != 490;
// Level up moves can only be inherited if ditto is not the mother.
var ratio = pkm.PersonalInfo.Gender; // Genderless/Male Only (except a few) cannot inherit.
bool AllowLevelUp = ratio > 0 && ratio < 255 || Legal.MixedGenderBreeding.Contains(e.Species);
Base = Legal.GetBaseEggMoves(pkm, e.Species, e.Game, e.LevelMin).ToList();
Egg = Legal.GetEggMoves(pkm, e.Species, pkm.AltForm).ToList();
LevelUp = AllowLevelUp
? Legal.GetBaseEggMoves(pkm, e.Species, e.Game, 100).Where(x => !Base.Contains(x)).ToList()
: new List<int>();
Tutor = e.Game == GameVersion.C
? Legal.GetTutorMoves(pkm, pkm.Species, pkm.AltForm, false, 2).ToList()
: new List<int>();
// Only TM/HM moves from the source game of the egg, not any other games from the same generation
TMHM = Legal.GetTMHM(pkm, pkm.Species, pkm.AltForm, pkm.GenNumber, e.Game, false).ToList();
// Non-Base moves that can magically appear in the regular movepool
bool volt = notSpecial && (pkm.GenNumber > 3 || e.Game == GameVersion.E) && Legal.LightBall.Contains(pkm.Species);
if (volt)
Egg.Add(344); // Volt Tackle
}
public bool AllowInherited { get; }
public List<int> Base { get; }
public List<int> Special { get; }
public List<int> Egg { get; }
public List<int> Tutor { get; }
public List<int> TMHM { get; }
public List<int> LevelUp { get; }
}
}

View File

@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace PKHeX.Core
{
internal class LearnInfo
{
public bool MixedGen12NonTradeback { get; set; }
public List<int> Gen1Moves { get; } = new List<int>();
public List<int> Gen2PreevoMoves { get; } = new List<int>();
public List<int> EggMovesLearned { get; } = new List<int>();
public List<int> LevelUpEggMoves { get; } = new List<int>();
public List<int> EventEggMoves { get; } = new List<int>();
public List<int> IncenseMoves { get; } = new List<int>();
public MoveParseSource Source { get; set; }
public readonly bool IsGen2Pkm;
public LearnInfo(PKM pkm)
{
IsGen2Pkm = pkm.Format == 2 || pkm.VC2;
}
}
}

View File

@ -0,0 +1,19 @@
namespace PKHeX.Core
{
internal class MoveParseSource
{
private static readonly int[] Empty = new int[0];
public int[] CurrentMoves { get; set; } = Empty;
public int[] SpecialSource { get; set; } = Empty;
public int[] NonTradeBackLevelUpMoves { get; set; } = Empty;
/// <summary>
/// Base moves from a standard encounter
/// </summary>
public int[] Base { get; set; } = Empty;
public int[] EggLevelUpSource { get; set; } = Empty;
public int[] EggMoveSource { get; set; } = Empty;
public int[] EggEventSource { get; set; } = Empty;
}
}

View File

@ -5,16 +5,32 @@ namespace PKHeX.Core
{
public class ValidEncounterMoves
{
public int EncounterSpecies { get; set; }
public DexLevel[][] EvolutionChains { get; set; }
public List<int>[] LevelUpMoves { get; set; } = Empty;
public List<int>[] TMHMMoves { get; set; } = Empty;
public List<int>[] TutorMoves { get; set; } = Empty;
public int EncounterSpecies { get; }
public DexLevel[][] EvolutionChains { get; }
public List<int>[] LevelUpMoves { get; } = Empty;
public List<int>[] TMHMMoves { get; } = Empty;
public List<int>[] TutorMoves { get; } = Empty;
public int[] Relearn = new int[0];
public int MinimumLevelGen1 { get; set; }
public int MinimumLevelGen2 { get; set; }
public int MinimumLevelGen1 { get; }
public int MinimumLevelGen2 { get; }
private const int EmptyCount = 7;
private static readonly List<int>[] Empty = new int[EmptyCount].Select(z => new List<int>()).ToArray();
public ValidEncounterMoves(PKM pkm, LegalInfo info)
{
MinimumLevelGen1 = pkm.GenNumber <= 2 ? info.EncounterMatch.LevelMin + 1 : 0;
MinimumLevelGen2 = Legal.AllowGen2MoveReminder ? 1 : info.EncounterMatch.LevelMin + 1;
EncounterSpecies = info.EncounterMatch.Species;
EvolutionChains = info.EvoChainsAllGens;
LevelUpMoves = Legal.GetValidMovesAllGens(pkm, EvolutionChains, minLvLG1: MinimumLevelGen1, minLvLG2: MinimumLevelGen2, Tutor: false, Machine: false, RemoveTransferHM: false);
TMHMMoves = Legal.GetValidMovesAllGens(pkm, EvolutionChains, LVL: false, Tutor: false, MoveReminder: false, RemoveTransferHM: false);
TutorMoves = Legal.GetValidMovesAllGens(pkm, EvolutionChains, LVL: false, Machine: false, MoveReminder: false, RemoveTransferHM: false);
}
public ValidEncounterMoves(List<int>[] levelup)
{
LevelUpMoves = levelup;
}
}
}