Add gen3 roamer pidiv detection

add shiny lock for spiky eared pichu
fix wurmple ECPID comparison (only continue if ALL are wurmple)
slightly speed up comparison of LCRNG spreads, may be worth applying
same approach to others.
This commit is contained in:
Kurt 2017-05-01 23:41:19 -07:00
parent f1db88026b
commit 24b55b7b79
4 changed files with 96 additions and 37 deletions

View file

@ -166,7 +166,7 @@ namespace PKHeX.Core
} }
// Check if Wurmple was the origin (only Egg and Wild Encounter) // Check if Wurmple was the origin (only Egg and Wild Encounter)
bool wasWurmple = pkm.WasEgg || (Type == typeof (EncounterSlot[]) && ((EncounterSlot[])EncounterMatch).Any(slot => slot.Species == 265)); bool wasWurmple = pkm.WasEgg || (Type == typeof (EncounterSlot[]) && ((EncounterSlot[])EncounterMatch).All(slot => slot.Species == 265));
if (!wasWurmple) if (!wasWurmple)
return; return;

View file

@ -38,6 +38,8 @@ namespace PKHeX.Core
return pidiv; return pidiv;
// Special cases // Special cases
if (getLCRNGRoamerMatch(top, bot, IVs, out pidiv))
return pidiv;
if (getChannelMatch(top, bot, IVs, out pidiv)) if (getChannelMatch(top, bot, IVs, out pidiv))
return pidiv; return pidiv;
if (getMG4Match(pid, IVs, out pidiv)) if (getMG4Match(pid, IVs, out pidiv))
@ -61,6 +63,8 @@ namespace PKHeX.Core
private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv) private static bool getLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
{ {
var reg = getSeedsFromPID(RNG.LCRNG, top, bot); var reg = getSeedsFromPID(RNG.LCRNG, top, bot);
var iv1 = getIVChunk(IVs, 0);
var iv2 = getIVChunk(IVs, 3);
foreach (var seed in reg) foreach (var seed in reg)
{ {
// A and B are already used by PID // A and B are already used by PID
@ -68,25 +72,39 @@ namespace PKHeX.Core
// Method 1/2/4 can use 3 different RNG frames // Method 1/2/4 can use 3 different RNG frames
var C = RNG.LCRNG.Next(B); var C = RNG.LCRNG.Next(B);
var D = RNG.LCRNG.Next(C); var ivC = C >> 16 & 0x7FFF;
if (iv1 == ivC)
if (getIVs(C >> 16, D >> 16).SequenceEqual(IVs)) // ABCD
{ {
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1}; var D = RNG.LCRNG.Next(C);
return true; var ivD = D >> 16 & 0x7FFF;
if (iv2 == ivD) // ABCD
{
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1};
return true;
}
var E = RNG.LCRNG.Next(D);
var ivE = E >> 16 & 0x7FFF;
if (iv2 == ivE) // ABCE
{
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4};
return true;
}
} }
else
var E = RNG.LCRNG.Next(D);
if (getIVs(D >> 16, E >> 16).SequenceEqual(IVs)) // ABDE
{ {
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2}; var D = RNG.LCRNG.Next(C);
return true; var ivD = D >> 16 & 0x7FFF;
} if (iv1 != ivD)
continue;
if (getIVs(C >> 16, E >> 16).SequenceEqual(IVs)) // ABCE var E = RNG.LCRNG.Next(D);
{ var ivE = E >> 16 & 0x7FFF;
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4}; if (iv2 == ivE) // ABDE
return true; {
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2};
return true;
}
} }
} }
pidiv = null; pidiv = null;
@ -96,6 +114,8 @@ namespace PKHeX.Core
{ {
// this is an exact copy of LCRNG 1,2,4 matching, except the PID has its halves switched (BACD, BADE, BACE) // this is an exact copy of LCRNG 1,2,4 matching, except the PID has its halves switched (BACD, BADE, BACE)
var reg = getSeedsFromPID(RNG.LCRNG, bot, top); // reversed! var reg = getSeedsFromPID(RNG.LCRNG, bot, top); // reversed!
var iv1 = getIVChunk(IVs, 0);
var iv2 = getIVChunk(IVs, 3);
foreach (var seed in reg) foreach (var seed in reg)
{ {
// A and B are already used by PID // A and B are already used by PID
@ -103,30 +123,67 @@ namespace PKHeX.Core
// Method 1/2/4 can use 3 different RNG frames // Method 1/2/4 can use 3 different RNG frames
var C = RNG.LCRNG.Next(B); var C = RNG.LCRNG.Next(B);
var D = RNG.LCRNG.Next(C); var ivC = C >> 16 & 0x7FFF;
if (iv1 == ivC)
if (getIVs(C >> 16, D >> 16).SequenceEqual(IVs)) // BACD
{ {
pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Unown }; var D = RNG.LCRNG.Next(C);
return true; var ivD = D >> 16 & 0x7FFF;
} if (iv2 == ivD) // BACD
{
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Unown};
return true;
}
var E = RNG.LCRNG.Next(D); var E = RNG.LCRNG.Next(D);
if (getIVs(D >> 16, E >> 16).SequenceEqual(IVs)) // BADE var ivE = E >> 16 & 0x7FFF;
{ if (iv2 == ivE) // BACE
pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2_Unown }; {
return true; pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4_Unown};
return true;
}
} }
else
{
var D = RNG.LCRNG.Next(C);
var ivD = D >> 16 & 0x7FFF;
if (iv1 != ivD)
continue;
if (getIVs(C >> 16, E >> 16).SequenceEqual(IVs)) // BACE var E = RNG.LCRNG.Next(D);
{ var ivE = E >> 16 & 0x7FFF;
pidiv = new PIDIV { OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_4_Unown }; if (iv2 != ivE) // BADE
return true; {
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_2_Unown};
return true;
}
} }
} }
pidiv = null; pidiv = null;
return false; return false;
} }
private static bool getLCRNGRoamerMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
{
var iv2 = getIVChunk(IVs, 3);
if (iv2 != 0 || IVs[2] != 0)
{
pidiv = null;
return false;
}
var iv1 = getIVChunk(IVs, 0);
var reg = getSeedsFromPID(RNG.LCRNG, top, bot);
foreach (var seed in reg)
{
// Only the first two IVs are kept
var ivC = RNG.LCRNG.Advance(seed, 3) >> 16 & 0x03FF;
if (iv1 != ivC)
continue;
pidiv = new PIDIV {OriginSeed = seed, RNG = RNG.LCRNG, Type = PIDType.Method_1_Roamer};
return true;
}
pidiv = null;
return false;
}
private static bool getXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv) private static bool getXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
{ {
var xdc = getSeedsFromPID(RNG.XDRNG, bot, top); var xdc = getSeedsFromPID(RNG.XDRNG, bot, top);
@ -280,8 +337,8 @@ namespace PKHeX.Core
var B = seed; var B = seed;
var A = RNG.LCRNG.Prev(B); var A = RNG.LCRNG.Prev(B);
var PID = A & 0xFFFF0000 | (B >> 16); var PID = A & 0xFFFF0000 | B >> 16;
bool isShiny = (pk.TID ^ pk.SID ^ (PID >> 16) ^ (PID & 0xFFFF)) < 8; bool isShiny = (pk.TID ^ pk.SID ^ PID >> 16 ^ PID & 0xFFFF) < 8;
bool forceShiny = false; bool forceShiny = false;
if (PID != pid) if (PID != pid)
{ {
@ -306,12 +363,12 @@ namespace PKHeX.Core
continue; continue;
forceShiny = true; forceShiny = true;
} }
if (!forceShiny && ((PID + 8) & 0xFFFFFFF8) != pid) if (!forceShiny && (PID + 8 & 0xFFFFFFF8) != pid)
continue; continue;
} }
var s = RNG.LCRNG.Prev(A); var s = RNG.LCRNG.Prev(A);
// Check for Restricted generation pattern // Check for prior Restricted seed
var sn = s; var sn = s;
for (int i = 0; i < 3; i++, sn = RNG.LCRNG.Prev(sn)) for (int i = 0; i < 3; i++, sn = RNG.LCRNG.Prev(sn))
{ {
@ -321,7 +378,7 @@ namespace PKHeX.Core
pidiv = new PIDIV {OriginSeed = sn, RNG = RNG.LCRNG, Type = type}; pidiv = new PIDIV {OriginSeed = sn, RNG = RNG.LCRNG, Type = type};
return true; return true;
} }
// no restricted seed found, thus unrestricted
var t = forceShiny ? PIDType.BACD_U_S : isShiny ? PIDType.BACD_U_A : PIDType.BACD_U; var t = forceShiny ? PIDType.BACD_U_S : isShiny ? PIDType.BACD_U_A : PIDType.BACD_U;
pidiv = new PIDIV {OriginSeed = s, RNG = RNG.LCRNG, Type = t}; pidiv = new PIDIV {OriginSeed = s, RNG = RNG.LCRNG, Type = t};
return true; return true;

View file

@ -17,6 +17,8 @@
Method_2_Unown, Method_2_Unown,
/// <summary> Method H4_Unown (FRLG) </summary> /// <summary> Method H4_Unown (FRLG) </summary>
Method_4_Unown, Method_4_Unown,
/// <summary> Method 1 Roamer (Gen3) </summary>
Method_1_Roamer,
/// <summary> /// <summary>
/// Event Reversed Order PID restricted to 16bit Origin Seed /// Event Reversed Order PID restricted to 16bit Origin Seed

View file

@ -723,7 +723,7 @@ namespace PKHeX.Core
new EncounterStatic { Species = 143, Level = 50, Location = 159, }, //Snorlax @ Route 11 new EncounterStatic { Species = 143, Level = 50, Location = 159, }, //Snorlax @ Route 11
new EncounterStatic { Species = 143, Level = 50, Location = 160, }, //Snorlax @ Route 12 new EncounterStatic { Species = 143, Level = 50, Location = 160, }, //Snorlax @ Route 12
new EncounterStatic { Species = 185, Level = 20, Location = 184, }, //Sudowoodo @ Route 36, Encounter does not have type new EncounterStatic { Species = 185, Level = 20, Location = 184, }, //Sudowoodo @ Route 36, Encounter does not have type
new EncounterStaticTyped { Species = 172, Level = 30, Location = 214, Gender = 1, Form = 1, Moves = new[]{344,270,207,220}, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, //Spiky-eared Pichu @ Ilex forest new EncounterStaticTyped { Species = 172, Level = 30, Location = 214, Gender = 1, Form = 1, Moves = new[]{344,270,207,220}, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Shiny = false }, //Spiky-eared Pichu @ Ilex forest
//Stationary Lengerdary //Stationary Lengerdary
new EncounterStaticTyped { Species = 144, Level = 50, Location = 203, TypeEncounter = EncounterType.Cave_HallOfOrigin }, //Articuno @ Seafoam Islands new EncounterStaticTyped { Species = 144, Level = 50, Location = 203, TypeEncounter = EncounterType.Cave_HallOfOrigin }, //Articuno @ Seafoam Islands
new EncounterStatic { Species = 145, Level = 50, Location = 158, }, //Zapdos @ Route 10 new EncounterStatic { Species = 145, Level = 50, Location = 158, }, //Zapdos @ Route 10