mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 12:33:06 +00:00
Update current RNG frame detection methods
Still not hooked in or handling every case, but is enough progress for now.
This commit is contained in:
parent
404651774a
commit
9380ca25d9
9 changed files with 398 additions and 207 deletions
20
PKHeX.Core/Legality/RNG/LockInfo.cs
Normal file
20
PKHeX.Core/Legality/RNG/LockInfo.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public enum LockInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// PID matches the required parameters.
|
||||
/// </summary>
|
||||
Pass,
|
||||
|
||||
/// <summary>
|
||||
/// PID did not match the required Nature.
|
||||
/// </summary>
|
||||
Nature,
|
||||
|
||||
/// <summary>
|
||||
/// PID did not match the required Gender.
|
||||
/// </summary>
|
||||
Gender,
|
||||
}
|
||||
}
|
|
@ -261,9 +261,9 @@ namespace PKHeX.Core
|
|||
var gr = pk.PersonalInfo.Gender;
|
||||
if (254 <= gr) // no modification for PID
|
||||
break;
|
||||
if (pid < gr)
|
||||
break;
|
||||
if (pid >= gr + 25)
|
||||
var rate = pk.Gender == 1 ? 0 : 25*(gr/25 + 1); // buffered
|
||||
var nature = pid % 25;
|
||||
if (nature + rate != pid)
|
||||
break;
|
||||
|
||||
pidiv = new PIDIV {NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.CuteCharm};
|
||||
|
|
103
PKHeX.Core/Legality/RNG/SearchCriteria.cs
Normal file
103
PKHeX.Core/Legality/RNG/SearchCriteria.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public class SearchCriteria
|
||||
{
|
||||
public uint Nature;
|
||||
public bool Gendered;
|
||||
public int GenderHigh;
|
||||
public int GenderLow;
|
||||
public bool DPPt;
|
||||
public bool CanSync;
|
||||
public bool MethodH;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Search Criteria parameters necessary for generating <see cref="SeedInfo"/> and <see cref="SlotResult"/> objects.
|
||||
/// </summary>
|
||||
/// <param name="pk"><see cref="PKM"/> object containing various accessible information required for the encounter.</param>
|
||||
/// <returns>Object containing search criteria to be passed by reference to search/filter methods.</returns>
|
||||
public static SearchCriteria getSearchCriteria(PKM pk)
|
||||
{
|
||||
var ver = (GameVersion)pk.Version;
|
||||
switch (ver)
|
||||
{
|
||||
// Method H
|
||||
case GameVersion.R:
|
||||
case GameVersion.S:
|
||||
case GameVersion.FR:
|
||||
case GameVersion.LG:
|
||||
return new SearchCriteria
|
||||
{
|
||||
Nature = pk.EncryptionConstant % 25,
|
||||
DPPt = false,
|
||||
MethodH = true,
|
||||
};
|
||||
|
||||
// Method H with Emerald Features
|
||||
case GameVersion.E:
|
||||
|
||||
// Cute Charm waits for gender too!
|
||||
var gender = pk.Gender;
|
||||
bool gendered = ver == GameVersion.E && gender != 2;
|
||||
|
||||
var criteria = new SearchCriteria
|
||||
{
|
||||
Nature = pk.EncryptionConstant % 25,
|
||||
DPPt = false,
|
||||
CanSync = true,
|
||||
MethodH = true,
|
||||
};
|
||||
if (gendered)
|
||||
{
|
||||
var gr = pk.PersonalInfo.Gender;
|
||||
criteria.Gendered = true;
|
||||
criteria.GenderLow = getGenderMinMax(gender, gr, false);
|
||||
criteria.GenderHigh = getGenderMinMax(gender, gr, true);
|
||||
}
|
||||
return criteria;
|
||||
|
||||
// Method J
|
||||
case GameVersion.D:
|
||||
case GameVersion.P:
|
||||
case GameVersion.Pt:
|
||||
return new SearchCriteria
|
||||
{
|
||||
Nature = pk.EncryptionConstant % 25,
|
||||
DPPt = true,
|
||||
CanSync = true,
|
||||
};
|
||||
|
||||
// Method K
|
||||
case GameVersion.HG:
|
||||
case GameVersion.SS:
|
||||
return new SearchCriteria
|
||||
{
|
||||
Nature = pk.EncryptionConstant % 25,
|
||||
DPPt = false,
|
||||
CanSync = true,
|
||||
};
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the span of values for a given Gender
|
||||
/// </summary>
|
||||
/// <param name="gender">Gender</param>
|
||||
/// <param name="ratio">Gender Ratio</param>
|
||||
/// <param name="max">Return Max (or Min)</param>
|
||||
/// <returns>Returns the maximum or minimum gender value that corresponds to the input gender ratio.</returns>
|
||||
private static int getGenderMinMax(int gender, int ratio, bool max)
|
||||
{
|
||||
if (ratio == 0 || ratio == 0xFE || ratio == 0xFF)
|
||||
gender = 2;
|
||||
switch (gender)
|
||||
{
|
||||
case 0: return max ? 255 : ratio; // male
|
||||
case 1: return max ? ratio - 1 : 0; // female
|
||||
default: return max ? 255 : 0; // fixed/genderless
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
60
PKHeX.Core/Legality/RNG/SeedInfo.cs
Normal file
60
PKHeX.Core/Legality/RNG/SeedInfo.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public class SeedInfo
|
||||
{
|
||||
public uint Seed;
|
||||
public bool Charm3;
|
||||
public static IEnumerable<SeedInfo> getSeedsUntilNature(PIDIV pidiv, SearchCriteria info)
|
||||
{
|
||||
bool reverse = pidiv.Type.IsReversedPID();
|
||||
bool charm3 = false;
|
||||
|
||||
var seed = pidiv.OriginSeed;
|
||||
yield return new SeedInfo { Seed = seed };
|
||||
|
||||
var s1 = seed;
|
||||
var s2 = pidiv.RNG.Prev(s1);
|
||||
while (true)
|
||||
{
|
||||
var a = s2 >> 16;
|
||||
var b = s1 >> 16;
|
||||
|
||||
var pid = reverse ? a << 16 | b : b << 16 | a;
|
||||
|
||||
// Process Conditions
|
||||
switch (verifyPIDCriteria(pid, info))
|
||||
{
|
||||
case LockInfo.Pass:
|
||||
yield break;
|
||||
case LockInfo.Gender:
|
||||
charm3 = true;
|
||||
break;
|
||||
}
|
||||
|
||||
s1 = pidiv.RNG.Prev(s2);
|
||||
s2 = pidiv.RNG.Prev(s1);
|
||||
|
||||
yield return new SeedInfo { Seed = s1, Charm3 = charm3 };
|
||||
}
|
||||
}
|
||||
|
||||
private static LockInfo verifyPIDCriteria(uint pid, SearchCriteria info)
|
||||
{
|
||||
// Nature locks are always a given
|
||||
var nval = pid % 25;
|
||||
if (nval != info.Nature)
|
||||
return LockInfo.Nature;
|
||||
|
||||
if (!info.Gendered)
|
||||
return LockInfo.Pass;
|
||||
|
||||
var gender = pid & 0xFF;
|
||||
if (info.GenderLow > gender || gender > info.GenderHigh)
|
||||
return LockInfo.Gender;
|
||||
|
||||
return LockInfo.Pass;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,97 +4,96 @@ namespace PKHeX.Core
|
|||
{
|
||||
public static class SlotFinder
|
||||
{
|
||||
public static List<uint> getSlotSeeds(PIDIV pidiv, uint nature, GameVersion v)
|
||||
/// <summary>
|
||||
/// Checks a <see cref="PIDIV"/> to see if any encounter frames can generate the spread. Requires further filtering against matched Encounter Slots and generation patterns.
|
||||
/// </summary>
|
||||
/// <param name="pidiv">Matched <see cref="PIDIV"/> containing <see cref="PIDIV.RNG"/> info and <see cref="PIDIV.OriginSeed"/>.</param>
|
||||
/// <param name="pk"><see cref="PKM"/> object containing various accessible information required for the encounter.</param>
|
||||
/// <returns><see cref="IEnumerable{SlotResult}"/> to yield possible encounter details for further filtering</returns>
|
||||
public static IEnumerable<SlotResult> getSlotSeeds(PIDIV pidiv, PKM pk)
|
||||
{
|
||||
// gather possible nature determination seeds until a same-nature PID breaks the unrolling
|
||||
var seeds = getSeedsUntilNature(pidiv, nature);
|
||||
SearchCriteria criteria = SearchCriteria.getSearchCriteria(pk);
|
||||
if (criteria == null)
|
||||
yield break;
|
||||
|
||||
IEnumerable<SeedInfo> seeds = SeedInfo.getSeedsUntilNature(pidiv, criteria);
|
||||
// get game generation criteria
|
||||
bool dppt = v == GameVersion.D || v == GameVersion.D || v == GameVersion.Pt;
|
||||
IEnumerable<SlotResult> info;
|
||||
switch (pidiv.Type)
|
||||
{
|
||||
case PIDType.CuteCharm:
|
||||
info = filterCuteCharm(seeds, pidiv, dppt);
|
||||
info = filterCuteCharm(seeds, pidiv, criteria);
|
||||
break;
|
||||
default:
|
||||
bool canSync = v == GameVersion.E || (int)v > 5; // Emerald and Gen4
|
||||
info = filterNatureSync(seeds, pidiv, nature, dppt, canSync);
|
||||
info = filterNatureSync(seeds, pidiv, criteria);
|
||||
break;
|
||||
}
|
||||
|
||||
// games need to map 0-65535 to 0-99
|
||||
// dppt use /656, hgss&gen3 use %100
|
||||
foreach (var z in info)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static IEnumerable<uint> getSeedsUntilNature(PIDIV pidiv, uint nature)
|
||||
/// <summary>
|
||||
/// Filters the input <see cref="SeedInfo"/> according to a Nature Lock frame generation pattern.
|
||||
/// </summary>
|
||||
/// <param name="seeds">Seed Information for the frame</param>
|
||||
/// <param name="pidiv">PIDIV Info for the frame</param>
|
||||
/// <param name="info">Search Info for the frame</param>
|
||||
/// <returns>Possible matches to the Nature Lock frame generation pattern</returns>
|
||||
private static IEnumerable<SlotResult> filterNatureSync(IEnumerable<SeedInfo> seeds, PIDIV pidiv, SearchCriteria info)
|
||||
{
|
||||
bool reverse = pidiv.Type.IsReversedPID();
|
||||
|
||||
var seed = pidiv.OriginSeed;
|
||||
yield return seed;
|
||||
|
||||
var s1 = pidiv.RNG.Prev(seed);
|
||||
var s2 = pidiv.RNG.Prev(s1);
|
||||
while (true)
|
||||
{
|
||||
var a = s2 >> 16;
|
||||
var b = s1 >> 16;
|
||||
|
||||
var pid = reverse ? b << 16 | a : a << 16 | b;
|
||||
if (pid % 25 == nature)
|
||||
break;
|
||||
|
||||
s1 = pidiv.RNG.Prev(s2);
|
||||
s2 = pidiv.RNG.Prev(s1);
|
||||
|
||||
yield return s1;
|
||||
}
|
||||
}
|
||||
private static IEnumerable<SlotResult> filterNatureSync(IEnumerable<uint> seeds, PIDIV pidiv, uint nature, bool dppt, bool canSync)
|
||||
{
|
||||
foreach (var s in seeds)
|
||||
foreach (var seed in seeds)
|
||||
{
|
||||
var s = seed.Seed;
|
||||
var rand = s >> 16;
|
||||
bool sync = canSync && (rand & 1) == 0;
|
||||
bool reg = (dppt ? rand / 0xA3E : rand % 25) == nature;
|
||||
bool sync = info.CanSync && !seed.Charm3 && (info.DPPt ? rand >> 15 : rand & 1) == 0;
|
||||
bool reg = (info.DPPt ? rand / 0xA3E : rand % 25) == info.Nature;
|
||||
if (!sync && !reg) // doesn't generate nature frame
|
||||
continue;
|
||||
|
||||
uint prev = pidiv.RNG.Prev(s);
|
||||
if (canSync && reg) // check for failed sync
|
||||
if (info.CanSync && reg) // check for failed sync
|
||||
{
|
||||
var failsync = prev >> 31 != 0;
|
||||
var failsync = (info.DPPt ? prev >> 31 : (prev >> 16) & 1) != 1;
|
||||
if (failsync)
|
||||
yield return new SlotResult {Seed = pidiv.RNG.Prev(prev), Sync = false};
|
||||
yield return new SlotResult {Seed = pidiv.RNG.Prev(prev), Sync = true, FailedSync = true};
|
||||
}
|
||||
if (sync)
|
||||
yield return new SlotResult {Seed = prev, Sync = true};
|
||||
if (reg)
|
||||
yield return new SlotResult {Seed = prev, Sync = false};
|
||||
yield return new SlotResult {Seed = prev, Sync = false, CuteCharm = seed.Charm3};
|
||||
}
|
||||
}
|
||||
private static IEnumerable<SlotResult> filterCuteCharm(IEnumerable<uint> seeds, PIDIV pidiv, bool dppt)
|
||||
|
||||
/// <summary>
|
||||
/// Filters the input <see cref="SeedInfo"/> according to a Cute Charm frame generation pattern.
|
||||
/// </summary>
|
||||
/// <param name="seeds">Seed Information for the frame</param>
|
||||
/// <param name="pidiv">PIDIV Info for the frame</param>
|
||||
/// <param name="info">Search Info for the frame</param>
|
||||
/// <returns>Possible matches to the Cute Charm frame generation pattern</returns>
|
||||
private static IEnumerable<SlotResult> filterCuteCharm(IEnumerable<SeedInfo> seeds, PIDIV pidiv, SearchCriteria info)
|
||||
{
|
||||
foreach (var s in seeds)
|
||||
foreach (var seed in seeds)
|
||||
{
|
||||
var s = seed.Seed;
|
||||
|
||||
var rand = s >> 16;
|
||||
bool charmProc = (dppt ? rand / 0x5556 : rand%3) == 0;
|
||||
if (charmProc)
|
||||
yield return new SlotResult {Seed = pidiv.RNG.Prev(s)};
|
||||
var nature = info.DPPt ? rand / 0xA3E : rand % 25;
|
||||
if (nature != info.Nature)
|
||||
continue;
|
||||
|
||||
var prev = pidiv.RNG.Prev(s);
|
||||
var proc = prev >> 16;
|
||||
bool charmProc = (info.DPPt ? proc / 0x5556 : proc % 3) == 0;
|
||||
if (!charmProc)
|
||||
continue;
|
||||
|
||||
yield return new SlotResult {Seed = prev, CuteCharm = true};
|
||||
}
|
||||
}
|
||||
|
||||
public class SlotResult
|
||||
{
|
||||
public uint Seed { get; set; }
|
||||
public bool Sync { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
14
PKHeX.Core/Legality/RNG/SlotResult.cs
Normal file
14
PKHeX.Core/Legality/RNG/SlotResult.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
public class SlotResult
|
||||
{
|
||||
public uint Seed { get; set; }
|
||||
public bool Sync { get; set; }
|
||||
public bool FailedSync { get; set; }
|
||||
public bool CuteCharm { get; set; }
|
||||
|
||||
public bool SuctionCups { get; set; }
|
||||
|
||||
public uint ESV { get; set; }
|
||||
}
|
||||
}
|
|
@ -88,6 +88,7 @@
|
|||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="PKM\DateTestPKM.cs" />
|
||||
<Compile Include="PKM\PIDIVTests.cs" />
|
||||
<Compile Include="PKM\PKMTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Saves\Substructures\MemeCryptoTests.cs" />
|
||||
|
|
144
Tests/PKHeX.Tests/PKM/PIDIVTests.cs
Normal file
144
Tests/PKHeX.Tests/PKM/PIDIVTests.cs
Normal file
|
@ -0,0 +1,144 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
using PKHeX.Core;
|
||||
|
||||
namespace PKHeX.Tests.PKM
|
||||
{
|
||||
[TestClass]
|
||||
public class PIDIVTest
|
||||
{
|
||||
private const string PIDIVTestCategory = "PKM PIDIV Matching Tests";
|
||||
// Note: IVs are stored HP/ATK/DEF/SPE/SPA/SPD
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory(PIDIVTestCategory)]
|
||||
public void PIDIVMatchingTest3()
|
||||
{
|
||||
// Method 1/2/4
|
||||
var pk1 = new PK3 {PID = 0xE97E0000, IVs = new[] {17, 19, 20, 16, 13, 12}};
|
||||
Assert.AreEqual(PIDType.Method_1, MethodFinder.Analyze(pk1)?.Type, "Unable to match PID to Method 1 spread");
|
||||
var pk2 = new PK3 {PID = 0x5271E97E, IVs = new[] {02, 18, 03, 12, 22, 24}};
|
||||
Assert.AreEqual(PIDType.Method_2, MethodFinder.Analyze(pk2)?.Type, "Unable to match PID to Method 2 spread");
|
||||
var pk4 = new PK3 {PID = 0x31B05271, IVs = new[] {02, 18, 03, 05, 30, 11}};
|
||||
Assert.AreEqual(PIDType.Method_4, MethodFinder.Analyze(pk4)?.Type, "Unable to match PID to Method 4 spread");
|
||||
|
||||
// Method 1/2/4, reversed for Unown.
|
||||
var pk1U = new PK3 {PID = 0x815549A2, IVs = new[] {02, 26, 30, 30, 11, 26}, Species = 201}; // Unown-C
|
||||
Assert.AreEqual(PIDType.Method_1_Unown, MethodFinder.Analyze(pk1U)?.Type, "Unable to match PID to Method 1 Unown spread");
|
||||
var pk2U = new PK3 {PID = 0x8A7B5190, IVs = new[] {14, 02, 21, 30, 29, 15}, Species = 201}; // Unown-M
|
||||
Assert.AreEqual(PIDType.Method_2_Unown, MethodFinder.Analyze(pk2U)?.Type, "Unable to match PID to Method 2 Unown spread");
|
||||
var pk4U = new PK3 {PID = 0x5FA80D70, IVs = new[] {02, 06, 03, 26, 04, 19}, Species = 201}; // Unown-A
|
||||
Assert.AreEqual(PIDType.Method_4_Unown, MethodFinder.Analyze(pk4U)?.Type, "Unable to match PID to Method 4 Unown spread");
|
||||
|
||||
// Colosseum / XD
|
||||
var pk3 = new PK3 {PID = 0x0985A297, IVs = new[] {06, 01, 00, 07, 17, 07}};
|
||||
Assert.AreEqual(PIDType.CXD, MethodFinder.Analyze(pk3)?.Type, "Unable to match PID to CXD spread");
|
||||
|
||||
// Channel Jirachi
|
||||
var pkC = new PK3 {PID = 0x9E27D2F6, IVs = new[] {04, 15, 21, 14, 18, 29}};
|
||||
Assert.AreEqual(PIDType.Channel, MethodFinder.Analyze(pkC)?.Type, "Unable to match PID to Channel spread");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory(PIDIVTestCategory)]
|
||||
public void PIDIVMatchingTest3Event()
|
||||
{
|
||||
// Restricted: TID/SID are zero.
|
||||
var pkR = new PK3 {PID = 0x0000E97E, IVs = new[] {17, 19, 20, 16, 13, 12}};
|
||||
Assert.AreEqual(PIDType.BACD_R, MethodFinder.Analyze(pkR)?.Type, "Unable to match PID to BACD-R spread");
|
||||
|
||||
// Restricted Antishiny: PID is incremented 2 times to lose shininess.
|
||||
var pkRA = new PK3 {PID = 0x0000E980, IVs = new[] {17, 19, 20, 16, 13, 12}, TID = 01337, SID = 60486};
|
||||
Assert.AreEqual(PIDType.BACD_R_A, MethodFinder.Analyze(pkRA)?.Type, "Unable to match PID to BACD-R antishiny spread");
|
||||
|
||||
// Unrestricted: TID/SID are zero.
|
||||
var pkU = new PK3 {PID = 0x67DBFC33, IVs = new[] {12, 25, 27, 30, 02, 31}};
|
||||
Assert.AreEqual(PIDType.BACD_U, MethodFinder.Analyze(pkU)?.Type, "Unable to match PID to BACD-U spread");
|
||||
|
||||
// Unrestricted Antishiny: PID is incremented 5 times to lose shininess.
|
||||
var pkUA = new PK3 {PID = 0x67DBFC38, IVs = new[] {12, 25, 27, 30, 02, 31}, TID = 01337, SID = 40657};
|
||||
Assert.AreEqual(PIDType.BACD_U_A, MethodFinder.Analyze(pkUA)?.Type, "Unable to match PID to BACD-U antishiny spread");
|
||||
|
||||
// berry fix zigzagoon: seed 0x0020
|
||||
var pkRS = new PK3 {PID = 0x38CA4EA0, IVs = new[] {00, 20, 28, 11, 19, 00}, TID = 30317, SID = 00000};
|
||||
var a_pkRS = MethodFinder.Analyze(pkRS);
|
||||
Assert.AreEqual(PIDType.BACD_R_S, a_pkRS?.Type, "Unable to match PID to BACD-R shiny spread");
|
||||
Assert.IsTrue(0x0020 == a_pkRS?.OriginSeed, "Unable to match PID to BACD-R shiny spread origin seed");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory(PIDIVTestCategory)]
|
||||
public void PIDIVMatchingTest4()
|
||||
{
|
||||
// Cute Charm: Male Bulbasaur
|
||||
var pkCC = new PK4 {PID = 0x00000037, IVs = new[] {16, 13, 12, 02, 18, 03}, Species = 1, Gender = 0};
|
||||
Assert.AreEqual(PIDType.CuteCharm, MethodFinder.Analyze(pkCC)?.Type, "Unable to match PID to Cute Charm spread");
|
||||
|
||||
// Antishiny Mystery Gift: TID/SID are zero. Original PID of 0x5271E97E is rerolled.
|
||||
var pkASR = new PK4 {PID = 0x07578CB7, IVs = new[] {16, 13, 12, 02, 18, 03}};
|
||||
Assert.AreEqual(PIDType.G4MGAntiShiny, MethodFinder.Analyze(pkASR)?.Type, "Unable to match PID to Antishiny4 spread");
|
||||
|
||||
// Chain Shiny: TID/SID are zero.
|
||||
var pkCS = new PK4 {PID = 0xA9C1A9C6, IVs = new[] {22, 14, 23, 24, 11, 04}};
|
||||
Assert.AreEqual(PIDType.ChainShiny, MethodFinder.Analyze(pkCS)?.Type, "Unable to match PID to Chain Shiny spread");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory(PIDIVTestCategory)]
|
||||
public void PIDIVMatchingTest5()
|
||||
{
|
||||
// Shiny Mystery Gift PGF; IVs are unrelated.
|
||||
var pkS5 = new PK5 {PID = 0xBEEF0037, TID = 01337, SID = 48097};
|
||||
Assert.AreEqual(PIDType.G5MGShiny, MethodFinder.Analyze(pkS5)?.Type, "Unable to match PID to PGF Shiny spread");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory(PIDIVTestCategory)]
|
||||
public void PIDIVPokeSpotTest()
|
||||
{
|
||||
// XD PokeSpots: Check all 3 Encounter Slots (examples are one for each location).
|
||||
var pkPS0 = new PK3 { PID = 0x7B2D9DA7 }; // Zubat (Cave)
|
||||
Assert.IsTrue(MethodFinder.getPokeSpotSeeds(pkPS0, 0).Any(), "PokeSpot encounter info mismatch (Common)");
|
||||
var pkPS1 = new PK3 { PID = 0x3EE9AF66 }; // Gligar (Rock)
|
||||
Assert.IsTrue(MethodFinder.getPokeSpotSeeds(pkPS1, 1).Any(), "PokeSpot encounter info mismatch (Uncommon)");
|
||||
var pkPS2 = new PK3 { PID = 0x9B667F3C }; // Surskit (Oasis)
|
||||
Assert.IsTrue(MethodFinder.getPokeSpotSeeds(pkPS2, 2).Any(), "PokeSpot encounter info mismatch (Rare)");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory(PIDIVTestCategory)]
|
||||
public void PIDIVEncounterSlotTest()
|
||||
{
|
||||
// Modest Method 1
|
||||
var pk = new PK3 {PID = 0x6937DA48, IVs = new[] {31, 31, 31, 31, 31, 31}};
|
||||
var pidiv = MethodFinder.Analyze(pk);
|
||||
Assert.AreEqual(PIDType.Method_1, pidiv?.Type, "Unable to match PID to Method 1 spread");
|
||||
|
||||
// Test for Method J
|
||||
{
|
||||
// Pearl
|
||||
pk.Version = (int) GameVersion.P;
|
||||
var results = SlotFinder.getSlotSeeds(pidiv, pk);
|
||||
const int failSyncCount = 1;
|
||||
const int noSyncCount = 2;
|
||||
const int SyncCount = 37;
|
||||
var r2 = results.ToArray();
|
||||
var failSync = r2.Where(z => z.FailedSync);
|
||||
var noSync = r2.Where(z => !z.Sync);
|
||||
var sync = r2.Where(z => z.Sync && !z.FailedSync);
|
||||
|
||||
Assert.AreEqual(failSync.Count(), failSyncCount, "Failed Sync count mismatch.");
|
||||
Assert.AreEqual(sync.Count(), SyncCount, "Sync count mismatch.");
|
||||
Assert.AreEqual(noSync.Count(z => !z.Sync), noSyncCount, "Non-Sync count mismatch.");
|
||||
|
||||
// var slots = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 9 };
|
||||
}
|
||||
// Test for Method H and K
|
||||
{
|
||||
// Sapphire
|
||||
// pk.Version = (int)GameVersion.S;
|
||||
// var results = SlotFinder.getSlotSeeds(pidiv, pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,6 @@ namespace PKHeX.Tests.PKM
|
|||
public class PKMTests
|
||||
{
|
||||
private const string DateTestCategory = "PKM Date Tests";
|
||||
private const string PIDIVTestCategory = "PKM PIDIV Matching Tests";
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory(DateTestCategory)]
|
||||
|
@ -128,154 +127,5 @@ namespace PKHeX.Tests.PKM
|
|||
Assert.AreEqual(now.Month, pk.EggMetMonth, "Egg_Month was not correctly set");
|
||||
Assert.AreEqual(now.Year - 2000, pk.EggMetYear, "Egg_Year was not correctly set");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory(PIDIVTestCategory)]
|
||||
public void PIDIVMatchingTest()
|
||||
{
|
||||
// IVs are stored HP/ATK/DEF/SPE/SPA/SPD
|
||||
var pk1 = new PK3
|
||||
{
|
||||
PID = 0xE97E0000,
|
||||
IVs = new[] {17, 19, 20, 16, 13, 12}
|
||||
};
|
||||
Assert.AreEqual(PIDType.Method_1, MethodFinder.Analyze(pk1)?.Type, "Unable to match PID to Method 1 spread");
|
||||
var pk2 = new PK3
|
||||
{
|
||||
PID = 0x5271E97E,
|
||||
IVs = new[] {02, 18, 03, 12, 22, 24}
|
||||
};
|
||||
Assert.AreEqual(PIDType.Method_2, MethodFinder.Analyze(pk2)?.Type, "Unable to match PID to Method 2 spread");
|
||||
var pk4 = new PK3
|
||||
{
|
||||
PID = 0x31B05271,
|
||||
IVs = new[] {02, 18, 03, 05, 30, 11}
|
||||
};
|
||||
Assert.AreEqual(PIDType.Method_4, MethodFinder.Analyze(pk4)?.Type, "Unable to match PID to Method 4 spread");
|
||||
|
||||
var pk3 = new PK3
|
||||
{
|
||||
PID = 0x0985A297,
|
||||
IVs = new[] {06, 01, 00, 07, 17, 07}
|
||||
};
|
||||
Assert.AreEqual(PIDType.CXD, MethodFinder.Analyze(pk3)?.Type, "Unable to match PID to CXD spread");
|
||||
|
||||
var pkC = new PK3
|
||||
{
|
||||
PID = 0x9E27D2F6,
|
||||
IVs = new[] {04, 15, 21, 14, 18, 29}
|
||||
};
|
||||
Assert.AreEqual(PIDType.Channel, MethodFinder.Analyze(pkC)?.Type, "Unable to match PID to Channel spread");
|
||||
|
||||
var pkCC = new PK4
|
||||
{
|
||||
PID = 0x00000037,
|
||||
IVs = new[] {16, 13, 12, 02, 18, 03},
|
||||
Species = 1,
|
||||
Gender = 0,
|
||||
};
|
||||
Assert.AreEqual(PIDType.CuteCharm, MethodFinder.Analyze(pkCC)?.Type, "Unable to match PID to Cute Charm spread");
|
||||
|
||||
var pkASR = new PK4
|
||||
{
|
||||
PID = 0x07578CB7, // 0x5271E97E rerolled
|
||||
IVs = new[] {16, 13, 12, 02, 18, 03},
|
||||
};
|
||||
Assert.AreEqual(PIDType.G4MGAntiShiny, MethodFinder.Analyze(pkASR)?.Type, "Unable to match PID to Antishiny4 spread");
|
||||
|
||||
var pkCS = new PK4
|
||||
{
|
||||
PID = 0xA9C1A9C6,
|
||||
// TID = 0,
|
||||
// SID = 0, // already default values, necessary for the forcing of a shiny PID
|
||||
IVs = new[] {22, 14, 23, 24, 11, 04}
|
||||
};
|
||||
Assert.AreEqual(PIDType.ChainShiny, MethodFinder.Analyze(pkCS)?.Type, "Unable to match PID to Chain Shiny spread");
|
||||
|
||||
var pkS5 = new PK5
|
||||
{
|
||||
PID = 0xBEEF0037,
|
||||
TID = 01337,
|
||||
SID = 48097,
|
||||
// IVs = new[] {22, 14, 23, 24, 11, 04} // unnecessary
|
||||
};
|
||||
Assert.AreEqual(PIDType.G5MGShiny, MethodFinder.Analyze(pkS5)?.Type, "Unable to match PID to PGF Shiny spread");
|
||||
|
||||
var pkR = new PK3
|
||||
{
|
||||
PID = 0x0000E97E,
|
||||
// TID = 0,
|
||||
// SID = 0, // already default values, necessary for the forcing of a shiny PID
|
||||
IVs = new[] {17, 19, 20, 16, 13, 12}
|
||||
};
|
||||
Assert.AreEqual(PIDType.BACD_R, MethodFinder.Analyze(pkR)?.Type, "Unable to match PID to BACD-R spread");
|
||||
|
||||
var pkRA = new PK3
|
||||
{
|
||||
PID = 0x0000E980, // +2 of 8 to flip first shiny bit
|
||||
TID = 01337,
|
||||
SID = 60486,
|
||||
IVs = new[] {17, 19, 20, 16, 13, 12}
|
||||
};
|
||||
Assert.AreEqual(PIDType.BACD_R_A, MethodFinder.Analyze(pkRA)?.Type, "Unable to match PID to BACD-R antishiny spread");
|
||||
|
||||
var pkU = new PK3
|
||||
{
|
||||
PID = 0x67DBFC33,
|
||||
// TID = 0,
|
||||
// SID = 0, // already default values, necessary for the forcing of a shiny PID
|
||||
IVs = new[] {12, 25, 27, 30, 02, 31}
|
||||
};
|
||||
Assert.AreEqual(PIDType.BACD_U, MethodFinder.Analyze(pkU)?.Type, "Unable to match PID to BACD-U spread");
|
||||
|
||||
var pkUA = new PK3
|
||||
{
|
||||
PID = 0x67DBFC38, // +5 of 8 to flip first shiny bit
|
||||
TID = 01337,
|
||||
SID = 40657,
|
||||
IVs = new[] {12, 25, 27, 30, 02, 31}
|
||||
};
|
||||
Assert.AreEqual(PIDType.BACD_U_A, MethodFinder.Analyze(pkUA)?.Type, "Unable to match PID to BACD-U antishiny spread");
|
||||
|
||||
var pkRS = new PK3 // berry fix zigzagoon: seed 0x0020
|
||||
{
|
||||
PID = 0x38CA4EA0,
|
||||
TID = 30317,
|
||||
SID = 00000,
|
||||
IVs = new[] { 00, 20, 28, 11, 19, 00 }
|
||||
};
|
||||
var a_pkRS = MethodFinder.Analyze(pkRS);
|
||||
Assert.AreEqual(PIDType.BACD_R_S, a_pkRS?.Type, "Unable to match PID to BACD-R shiny spread");
|
||||
Assert.IsTrue(0x0020 == a_pkRS?.OriginSeed, "Unable to match PID to BACD-R shiny spread origin seed");
|
||||
|
||||
var pkPS0 = new PK3 {PID = 0x7B2D9DA7}; // Zubat (Cave)
|
||||
Assert.IsTrue(MethodFinder.getPokeSpotSeeds(pkPS0, 0).Any(), "PokeSpot encounter info mismatch (Common)");
|
||||
var pkPS1 = new PK3 {PID = 0x3EE9AF66}; // Gligar (Rock)
|
||||
Assert.IsTrue(MethodFinder.getPokeSpotSeeds(pkPS1, 1).Any(), "PokeSpot encounter info mismatch (Uncommon)");
|
||||
var pkPS2 = new PK3 {PID = 0x9B667F3C}; // Surskit (Oasis)
|
||||
Assert.IsTrue(MethodFinder.getPokeSpotSeeds(pkPS2, 2).Any(), "PokeSpot encounter info mismatch (Rare)");
|
||||
|
||||
var pk1U = new PK3
|
||||
{
|
||||
Species = 201, // Unown-C
|
||||
PID = 0x815549A2,
|
||||
IVs = new[] {02, 26, 30, 30, 11, 26}
|
||||
};
|
||||
Assert.AreEqual(PIDType.Method_1_Unown, MethodFinder.Analyze(pk1U)?.Type, "Unable to match PID to Method 1 Unown spread");
|
||||
var pk2U = new PK3
|
||||
{
|
||||
Species = 201, // Unown-M
|
||||
PID = 0x8A7B5190,
|
||||
IVs = new[] {14, 02, 21, 30, 29, 15}
|
||||
};
|
||||
Assert.AreEqual(PIDType.Method_2_Unown, MethodFinder.Analyze(pk2U)?.Type, "Unable to match PID to Method 2 Unown spread");
|
||||
var pk4U = new PK3
|
||||
{
|
||||
Species = 201, // Unown-C
|
||||
PID = 0x5FA80D70,
|
||||
IVs = new[] {02, 06, 03, 26, 04, 19}
|
||||
};
|
||||
Assert.AreEqual(PIDType.Method_4_Unown, MethodFinder.Analyze(pk4U)?.Type, "Unable to match PID to Method 4 Unown spread");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue