Handle baby->mother parent fetch

Need to fix something with volbeat/nido for inheritance still.
This commit is contained in:
Kurt
2026-08-01 19:40:57 -05:00
parent fb40d0e04b
commit 78d4fc8d8f
3 changed files with 46 additions and 18 deletions

View File

@@ -51,13 +51,14 @@ public ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form)
}
// Present and not in Crystal:
// 001 (Bulbasaur) += Charm
// 016 (Pidgey) += SteelWing
// 043 (Oddish) += Charm
// 046 (Paras) += SweetScent
// 083 (Farfetchd) += SteelWing
// 120 (Staryu) += AuroraBeam, Barrier, Supersonic
// 142 (Aerodactyl) += SteelWing
// Inaccessible (no father in same egg group):
// 001 (Bulbasaur) += Charm
// 043 (Oddish) += Charm
// 120 (Staryu) += AuroraBeam, Barrier, Supersonic
// 143 (Snorlax) += Charm
// 238 (Smoochum) += LovelyKiss

View File

@@ -46,6 +46,7 @@ public static bool TryValidate(ushort species, byte form, GameVersion version, R
// For male-only split breed species (Volbeat/Nidoran-M) in Gen 2-5, we need special validation:
// All EGG moves must come from a single father.
// Level-up moves don't need this restriction (can breed with Ditto).
// No cases of chain breeding combinations, so we can just check if a single father can pass all egg moves.
var isMaleSplit = IsMaleOnlySplitBreed(species);
if (isMaleSplit)
{
@@ -239,18 +240,7 @@ private static bool CanSingleFatherPassAllMoves(ushort motherSpecies, byte mothe
continue;
// Check if this father can learn ALL the moves
bool canLearnAll = true;
foreach (var move in moves)
{
if (move == 0)
break;
// Father must be able to learn this move as an egg move or level-up move
if (CanFatherLearnMoveForEgg(fatherSpecies, fatherForm, move, learn))
continue;
canLearnAll = false;
break;
}
var canLearnAll = CanFatherLearnAll(moves, fatherSpecies, fatherForm, learn);
if (!canLearnAll)
continue;
@@ -262,6 +252,20 @@ private static bool CanSingleFatherPassAllMoves(ushort motherSpecies, byte mothe
return false; // No single father can pass all moves
}
private static bool CanFatherLearnAll(ReadOnlySpan<ushort> moves, ushort fatherSpecies, byte fatherForm, ILearnSource learn)
{
foreach (var move in moves)
{
if (move == 0)
break;
// Father must be able to learn this move as an egg move or level-up move
if (CanFatherLearnMoveForEgg(fatherSpecies, fatherForm, move, learn))
continue;
return false;
}
return true;
}
private static bool CanMotherAndFatherPassAllMoves(ushort motherSpecies, byte motherForm, GameVersion version, ReadOnlySpan<ushort> moves, out ChainBreedSummary summary)
{
// For male-only split breed species in Gen 6-7:
@@ -423,8 +427,7 @@ private static bool TryValidateBaseCounts(ushort eggSpecies, byte eggForm, GameV
var suffix = moves.Slice(baseCount, inheritedCount);
var suffixFlags = flags.Slice(baseCount, inheritedCount);
for (int i = 0; i < inheritedCount; i++)
inheritedMoves[i] = suffix[i];
suffix.CopyTo(inheritedMoves);
if (TryResolveInheritedSources(eggSpecies, eggForm, version, inheritedMoves[..inheritedCount], suffixFlags, 0, visited, depth + 1, out summary))
return true;
@@ -463,6 +466,8 @@ private static bool TryResolveFather(ushort eggSpecies, byte eggForm, GameVersio
return false;
var mother = table[eggSpecies, eggForm];
if (mother.EggGroup1 == (int)EggGroup.Undiscovered && TryGetEvolvedMother(eggSpecies, eggForm, version, out var newMother))
mother = table[newMother.Species, newMother.Form];
// If the egg species can't breed (baby Pokemon like Tyrogue), check if its evolutions can act as fathers
if (mother.Genderless || mother.OnlyMale || mother.EggGroup1 == (int)EggGroup.Undiscovered)
@@ -496,9 +501,28 @@ private static bool TryResolveFather(ushort eggSpecies, byte eggForm, GameVersio
return false;
}
private static bool TryGetEvolvedMother(ushort eggSpecies, byte eggForm, GameVersion version, out (ushort Species, byte Form) newMother)
{
var tree = EvolutionTree.GetEvolutionTree(version.Context);
var evos = tree.Forward.GetEvolutions(eggSpecies, eggForm);
var pt = GameData.GetPersonal(version);
foreach (var (evoSpecies, evoForm) in evos)
{
var pi = pt[evoSpecies, evoForm];
if (pi.EggGroup1 == (int)EggGroup.Undiscovered)
continue;
newMother = (evoSpecies, evoForm);
return true;
}
newMother = default;
return false;
}
private static bool TryResolveFatherViaEvolution(ushort eggSpecies, byte eggForm, GameVersion version, ReadOnlySpan<ushort> moves, Span<ChainQueryState> visited, int depth, out ChainBreedSummary summary)
{
summary = default;
var tree = EvolutionTree.GetEvolutionTree(version.Context);
var evos = tree.Forward.GetEvolutions(eggSpecies, eggForm);
@@ -511,6 +535,7 @@ private static bool TryResolveFatherViaEvolution(ushort eggSpecies, byte eggForm
return true;
}
summary = default;
return false;
}

View File

@@ -32,6 +32,7 @@ public void DetectsInvalidChains(GameVersion version, Species species, params Mo
[InlineData(HGSS, Mankey, Encore, Meditate, SmellingSalts)]
[InlineData(GS, Chansey, DoubleEdge)] // via Jigglypuff (Level 39)
[InlineData(Pt, Shellder, RapidSpin, IcicleSpear)]
[InlineData(R, Volbeat, HelpingHand)] // level up, breed with Illumise
public void DetectsValidChains(GameVersion version, Species species, params Move[] movelist)
=> ValidateSimple(version, species, 0, movelist);
@@ -60,6 +61,7 @@ private static void ValidateSimple(GameVersion version, Species species, byte fo
[Theory]
[InlineData(HGSS, Mankey, 0, Smeargle, Encore, Meditate, SmellingSalts)]
[InlineData(E, Pichu, 0, Smeargle, Reversal, Encore, Wish, Present)] // via Pikachu mother
public void DetectsValidChainSmeargle(GameVersion version, Species species, byte form, Species father, params Move[] movelist)
{
var moves = GetMoves(movelist);