diff --git a/Source/Core/Gen3/Searchers/GameCubeSearcher.cpp b/Source/Core/Gen3/Searchers/GameCubeSearcher.cpp index 9cda10fe5..4ca26f6ea 100644 --- a/Source/Core/Gen3/Searchers/GameCubeSearcher.cpp +++ b/Source/Core/Gen3/Searchers/GameCubeSearcher.cpp @@ -42,7 +42,7 @@ static bool isShiny(u16 high, u16 low, u16 tsv) * @return true Seed passes the menu pattern * @return false Seed does not pass the menu pattern */ -static bool validateMenu(XDRNGR rng) +static bool validateMenu(XDRNGR &rng) { u8 target = rng.getSeed() >> 30; @@ -74,7 +74,7 @@ static bool validateMenu(XDRNGR rng) * @return true Seed passes the Jirachi pattern * @return false Seed does not pass the Jirachi pattern */ -static bool validateJirachi(u32 seed) +static bool validateJirachi(u32 &seed) { XDRNGR rng(seed); @@ -82,29 +82,35 @@ static bool validateJirachi(u32 seed) u16 num2 = rng.nextUShort(); u16 num3 = rng.nextUShort(); - rng.advance(3); - if (num1 <= 0x4000) // 6 advances + if (num3 > 0x4000 && num2 > 0x547a) // 8 advances { - if (validateMenu(rng)) + XDRNGR test(rng); + test.advance(5); + if (validateMenu(test)) { + seed = test.advance(2); return true; } } - rng.advance(1); if (num2 > 0x4000 && num1 <= 0x547a) // 7 advances { - if (validateMenu(rng)) + XDRNGR test(rng); + test.advance(4); + if (validateMenu(test)) { + seed = test.advance(2); return true; } } - rng.advance(1); - if (num3 > 0x4000 && num2 > 0x547a) // 8 advances + if (num1 <= 0x4000) // 6 advances { - if (validateMenu(rng)) + XDRNGR test(rng); + test.advance(3); + if (validateMenu(test)) { + seed = test.advance(2); return true; } } @@ -261,13 +267,14 @@ void GameCubeSearcher::searchChannel(u8 minSpd, u8 maxSpd, const StaticTemplate continue; } - if (!validateJirachi(rng.next())) + u32 origin = rng.next(); + if (!validateJirachi(origin)) { continue; } - SearcherState state(rng.getSeed(), pid, ivs, pid & 1, 2, staticTemplate->getLevel(), nature, - Utilities::getShiny(pid, tid ^ sid), info); + SearcherState state(origin, pid, ivs, pid & 1, 2, staticTemplate->getLevel(), nature, Utilities::getShiny(pid, tid ^ sid), + info); if (filter.compareState(static_cast(state))) { std::lock_guard guard(mutex); @@ -494,9 +501,10 @@ std::vector GameCubeSearcher::searchNonLock(u8 hp, u8 atk, u8 def } XDRNG test(temp); + temp.advance(2); tsv = temp.nextUShort() ^ temp.nextUShort(); - seed = temp.next(); + seed = temp.advance(3); // This TSV better end up on the original Umbreon PID we found // The only reason this wouldn't be true is if we get some extra rerolls from a PID being shiny diff --git a/Source/Core/Gen3/ShadowLock.cpp b/Source/Core/Gen3/ShadowLock.cpp index bd8c961af..bfa8028af 100644 --- a/Source/Core/Gen3/ShadowLock.cpp +++ b/Source/Core/Gen3/ShadowLock.cpp @@ -93,7 +93,13 @@ namespace ShadowLock // Check if we end on the same PID as first non-shadow going backwards if (pidOriginal == pid) { - seed = backward.advance(8); + // Compute origin seed that would give the first occurence of the spread + do + { + pid = getPIDBackward(backward); + } while (!shadowTemplate->getLock(0).compare(pid)); + + seed = backward.advance(6); return true; } @@ -144,7 +150,13 @@ namespace ShadowLock // Checks if PID matches original if (pid == readerPID) { - seed = backward.advance(8); + // Compute origin seed that would give the first occurence of the spread + do + { + pid = getPIDBackward(backward); + } while (!shadowTemplate->getLock(0).compare(pid)); + + seed = backward.advance(6); return true; } return false; @@ -197,7 +209,13 @@ namespace ShadowLock // Check if we end on the same PID as first non-shadow going backwards if (pidOriginal == pid) { - seed = backward.advance(8); + // Compute origin seed that would give the first occurence of the spread + do + { + pid = getPIDBackward(backward); + } while (!shadowTemplate->getLock(0).compare(pid) || isShiny(pid, tsv)); + + seed = backward.advance(6); return true; } @@ -251,7 +269,13 @@ namespace ShadowLock // Check if we end on the same PID as first non-shadow going backwards if (pidOriginal == pid) { - seed = backward.advance(8); + // Compute origin seed that would give the first occurence of the spread + do + { + pid = getPIDBackward(backward); + } while (!shadowTemplate->getLock(0).compare(pid) || isShiny(pid, tsv)); + + seed = backward.advance(6); return true; } @@ -316,7 +340,13 @@ namespace ShadowLock // Check if we end on the same PID as first non-shadow going backwards if (pidOriginal == pid) { - seed = backward.advance(8); + // Compute origin seed that would give the first occurence of the spread + do + { + pid = getPIDBackward(backward); + } while (!shadowTemplate->getLock(0).compare(pid) || isShiny(pid, tsv)); + + seed = backward.advance(6); return true; } @@ -334,7 +364,13 @@ namespace ShadowLock // Backwards nature lock check if (shadowTemplate->getLock(0).compare(pid) && !isShiny(pid, tsv)) { - seed = backward.advance(8); + // Compute origin seed that would give the first occurence of the spread + do + { + pid = getPIDBackward(backward); + } while (!shadowTemplate->getLock(0).compare(pid) || isShiny(pid, tsv)); + + seed = backward.advance(6); return true; } @@ -363,7 +399,13 @@ namespace ShadowLock // Backwards nature lock check if (shadowTemplate->getLock(0).compare(pid) && !isShiny(pid, tsv)) { - seed = backward.advance(8); + // Compute origin seed that would give the first occurence of the spread + do + { + pid = getPIDBackward(backward); + } while (!shadowTemplate->getLock(0).compare(pid) || isShiny(pid, tsv)); + + seed = backward.advance(6); return true; } @@ -381,7 +423,13 @@ namespace ShadowLock // Backwards nature lock check if (shadowTemplate->getLock(0).compare(pid) && !isShiny(pid, tsv)) { - seed = backward.advance(8); + // Compute origin seed that would give the first occurence of the spread + do + { + pid = getPIDBackward(backward); + } while (!shadowTemplate->getLock(0).compare(pid) || isShiny(pid, tsv)); + + seed = backward.advance(6); return true; } diff --git a/Source/Test/Gen3/GameCubeSearcherTest.cpp b/Source/Test/Gen3/GameCubeSearcherTest.cpp index 96388f05a..a372ff245 100644 --- a/Source/Test/Gen3/GameCubeSearcherTest.cpp +++ b/Source/Test/Gen3/GameCubeSearcherTest.cpp @@ -50,27 +50,16 @@ static bool operator==(const SearcherState &left, const GeneratorState &right) } } -static bool operator==(const SearcherState &left, const json &right) -{ - return left.getPID() == right["pid"].get() && left.getStats() == right["stats"].get>() - && left.getAbilityIndex() == right["abilityIndex"].get() && left.getIVs() == right["ivs"].get>() - && left.getAbility() == right["ability"].get() && left.getGender() == right["gender"].get() - && left.getHiddenPower() == right["hiddenPower"].get() - && left.getHiddenPowerStrength() == right["hiddenPowerStrength"].get() && left.getLevel() == right["level"].get() - && left.getNature() == right["nature"].get() && left.getShiny() == right["shiny"].get() - && left.getSeed() == right["seed"].get(); -} - void GameCubeSearcherTest::searchChannel_data() { QTest::addColumn("min"); QTest::addColumn("max"); - QTest::addColumn("results"); + QTest::addColumn("results"); json data = readData("gamecube", "gamecubesearcher", "searchChannel"); for (const auto &d : data) { - QTest::newRow(d["name"].get().data()) << d["min"].get() << d["max"].get() << d["results"].get().dump(); + QTest::newRow(d["name"].get().data()) << d["min"].get() << d["max"].get() << d["results"].get(); } } @@ -78,9 +67,7 @@ void GameCubeSearcherTest::searchChannel() { QFETCH(IVs, min); QFETCH(IVs, max); - QFETCH(std::string, results); - - json j = json::parse(results); + QFETCH(int, results); std::array natures; natures.fill(true); @@ -96,12 +83,16 @@ void GameCubeSearcherTest::searchChannel() searcher.startSearch(min, max, staticTemplate); auto states = searcher.getResults(); - QCOMPARE(states.size(), j.size()); + QCOMPARE(states.size(), results); - for (int i = 0; i < states.size(); i++) + for (const auto &state : states) { - const auto &state = states[i]; - QVERIFY(state == j[i]); + // Ensure generator agrees + GameCubeGenerator generator(0, 0, 0, Method::Channel, false, profile, filter); + auto generatorStates = generator.generate(state.getSeed(), staticTemplate); + + QCOMPARE(generatorStates.size(), 1); + QVERIFY(state == generatorStates[0]); } } @@ -221,13 +212,13 @@ void GameCubeSearcherTest::searchNonLock_data() QTest::addColumn("max"); QTest::addColumn("version"); QTest::addColumn("pokemon"); - QTest::addColumn("results"); + QTest::addColumn("results"); json data = readData("gamecube", "gamecubesearcher", "searchNonLock"); for (const auto &d : data) { - QTest::newRow(d["name"].get().data()) << d["min"].get() << d["max"].get() << d["version"].get() - << d["pokemon"].get() << d["results"].get().dump(); + QTest::newRow(d["name"].get().data()) + << d["min"].get() << d["max"].get() << d["version"].get() << d["pokemon"].get() << d["results"].get(); } } @@ -237,9 +228,7 @@ void GameCubeSearcherTest::searchNonLock() QFETCH(IVs, max); QFETCH(Game, version); QFETCH(int, pokemon); - QFETCH(std::string, results); - - json j = json::parse(results); + QFETCH(int, results); std::array natures; natures.fill(true); @@ -255,11 +244,15 @@ void GameCubeSearcherTest::searchNonLock() searcher.startSearch(min, max, staticTemplate); auto states = searcher.getResults(); - QCOMPARE(states.size(), j.size()); + QCOMPARE(states.size(), results); - for (int i = 0; i < states.size(); i++) + for (const auto &state : states) { - const auto &state = states[i]; - QVERIFY(state == j[i]); + // Ensure generator agrees + GameCubeGenerator generator(0, 0, 0, Method::None, false, profile, filter); + auto generatorStates = generator.generate(state.getSeed(), staticTemplate); + + QCOMPARE(generatorStates.size(), 1); + QVERIFY(state == generatorStates[0]); } } diff --git a/Source/Test/Gen3/gamecube.json b/Source/Test/Gen3/gamecube.json index 506058a54..48d2c8fa8 100644 --- a/Source/Test/Gen3/gamecube.json +++ b/Source/Test/Gen3/gamecube.json @@ -4053,40 +4053,11 @@ 31, 31, 31, - 31, + 0, 31, 31 ], - "results": [ - { - "ability": 0, - "abilityIndex": 32, - "gender": 2, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 5, - "nature": 2, - "pid": 3566706802, - "seed": 3474027399, - "shiny": 0, - "stats": [ - 26, - 17, - 16, - 16, - 16, - 14 - ] - } - ] + "results": 0 } ], "searchColoShadow": [ @@ -4272,7 +4243,7 @@ "name": "Colo Umbreon", "min": [ 31, - 31, + 0, 31, 31, 31, @@ -4288,182 +4259,13 @@ ], "version": "Colosseum", "pokemon": 0, - "results": [ - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 26, - "nature": 10, - "pid": 3276922610, - "seed": 2826084811, - "shiny": 0, - "stats": [ - 93, - 41, - 70, - 44, - 80, - 50 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 26, - "nature": 19, - "pid": 1129406194, - "seed": 678601163, - "shiny": 0, - "stats": [ - 93, - 46, - 70, - 48, - 72, - 46 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 26, - "nature": 24, - "pid": 1752334399, - "seed": 2414474238, - "shiny": 0, - "stats": [ - 93, - 46, - 70, - 44, - 80, - 46 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 26, - "nature": 4, - "pid": 3899785279, - "seed": 266990590, - "shiny": 0, - "stats": [ - 93, - 50, - 70, - 44, - 72, - 46 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 26, - "nature": 0, - "pid": 227811725, - "seed": 2002863665, - "shiny": 0, - "stats": [ - 93, - 46, - 70, - 44, - 80, - 46 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 26, - "nature": 16, - "pid": 2375328141, - "seed": 4150347313, - "shiny": 0, - "stats": [ - 93, - 46, - 63, - 48, - 80, - 46 - ] - } - ] + "results": 142 }, { "name": "Colo Espeon", "min": [ 31, - 31, + 0, 31, 31, 31, @@ -4479,182 +4281,13 @@ ], "version": "Colosseum", "pokemon": 1, - "results": [ - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 25, - "nature": 10, - "pid": 3276922610, - "seed": 571827620, - "shiny": 0, - "stats": [ - 75, - 40, - 42, - 77, - 60, - 73 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 25, - "nature": 19, - "pid": 1129406194, - "seed": 2719311268, - "shiny": 0, - "stats": [ - 75, - 45, - 42, - 84, - 54, - 67 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 25, - "nature": 24, - "pid": 1752334399, - "seed": 1271304163, - "shiny": 0, - "stats": [ - 75, - 45, - 42, - 77, - 60, - 67 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 25, - "nature": 4, - "pid": 3899785279, - "seed": 3418787811, - "shiny": 0, - "stats": [ - 75, - 49, - 42, - 77, - 54, - 67 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 25, - "nature": 0, - "pid": 227811725, - "seed": 1970780706, - "shiny": 0, - "stats": [ - 75, - 45, - 42, - 77, - 60, - 67 - ] - }, - { - "ability": 0, - "abilityIndex": 28, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 25, - "nature": 16, - "pid": 2375328141, - "seed": 4118264354, - "shiny": 0, - "stats": [ - 75, - 45, - 37, - 84, - 60, - 67 - ] - } - ] + "results": 126 }, { "name": "Ageto Celebi", "min": [ 31, - 31, + 0, 31, 31, 31, @@ -4670,176 +4303,7 @@ ], "version": "Colosseum", "pokemon": 3, - "results": [ - { - "ability": 0, - "abilityIndex": 30, - "gender": 2, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 10, - "pid": 3276922610, - "seed": 2425274879, - "shiny": 0, - "stats": [ - 43, - 25, - 28, - 28, - 28, - 30 - ] - }, - { - "ability": 0, - "abilityIndex": 30, - "gender": 2, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 19, - "pid": 1129406194, - "seed": 277791231, - "shiny": 0, - "stats": [ - 43, - 28, - 28, - 30, - 25, - 28 - ] - }, - { - "ability": 0, - "abilityIndex": 30, - "gender": 2, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 24, - "pid": 1752334399, - "seed": 4274828322, - "shiny": 0, - "stats": [ - 43, - 28, - 28, - 28, - 28, - 28 - ] - }, - { - "ability": 0, - "abilityIndex": 30, - "gender": 2, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 4, - "pid": 3899785279, - "seed": 2127344674, - "shiny": 0, - "stats": [ - 43, - 30, - 28, - 28, - 25, - 28 - ] - }, - { - "ability": 0, - "abilityIndex": 30, - "gender": 2, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 0, - "pid": 227811725, - "seed": 1829414469, - "shiny": 0, - "stats": [ - 43, - 28, - 28, - 28, - 28, - 28 - ] - }, - { - "ability": 0, - "abilityIndex": 30, - "gender": 2, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 16, - "pid": 2375328141, - "seed": 3976898117, - "shiny": 0, - "stats": [ - 43, - 28, - 25, - 30, - 28, - 28 - ] - } - ] + "results": 142 }, { "name": "Gales Eevee", @@ -4847,7 +4311,7 @@ 31, 31, 31, - 31, + 0, 31, 31 ], @@ -4861,182 +4325,13 @@ ], "version": "Gales", "pokemon": 5, - "results": [ - { - "ability": 1, - "abilityIndex": 91, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 10, - "pid": 3276922610, - "seed": 2826084811, - "shiny": 0, - "stats": [ - 34, - 17, - 18, - 17, - 21, - 20 - ] - }, - { - "ability": 1, - "abilityIndex": 91, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 19, - "pid": 1129406194, - "seed": 678601163, - "shiny": 0, - "stats": [ - 34, - 19, - 18, - 18, - 18, - 19 - ] - }, - { - "ability": 1, - "abilityIndex": 91, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 24, - "pid": 1752334399, - "seed": 2414474238, - "shiny": 0, - "stats": [ - 34, - 19, - 18, - 17, - 21, - 19 - ] - }, - { - "ability": 1, - "abilityIndex": 91, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 4, - "pid": 3899785279, - "seed": 266990590, - "shiny": 0, - "stats": [ - 34, - 20, - 18, - 17, - 18, - 19 - ] - }, - { - "ability": 0, - "abilityIndex": 50, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 0, - "pid": 227811725, - "seed": 2002863665, - "shiny": 0, - "stats": [ - 34, - 19, - 18, - 17, - 21, - 19 - ] - }, - { - "ability": 0, - "abilityIndex": 50, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 10, - "nature": 16, - "pid": 2375328141, - "seed": 4150347313, - "shiny": 0, - "stats": [ - 34, - 19, - 16, - 18, - 21, - 19 - ] - } - ] + "results": 138 }, { "name": "Gales Chikorita", "min": [ 31, - 31, + 0, 31, 31, 31, @@ -5052,176 +4347,7 @@ ], "version": "Gales", "pokemon": 6, - "results": [ - { - "ability": 0, - "abilityIndex": 65, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 5, - "nature": 10, - "pid": 3276922610, - "seed": 2425274879, - "shiny": 0, - "stats": [ - 21, - 9, - 13, - 11, - 13, - 12 - ] - }, - { - "ability": 0, - "abilityIndex": 65, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 5, - "nature": 19, - "pid": 1129406194, - "seed": 277791231, - "shiny": 0, - "stats": [ - 21, - 11, - 13, - 12, - 11, - 11 - ] - }, - { - "ability": 0, - "abilityIndex": 65, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 5, - "nature": 24, - "pid": 1752334399, - "seed": 4274828322, - "shiny": 0, - "stats": [ - 21, - 11, - 13, - 11, - 13, - 11 - ] - }, - { - "ability": 0, - "abilityIndex": 65, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 5, - "nature": 4, - "pid": 3899785279, - "seed": 2127344674, - "shiny": 0, - "stats": [ - 21, - 12, - 13, - 11, - 11, - 11 - ] - }, - { - "ability": 0, - "abilityIndex": 65, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 5, - "nature": 0, - "pid": 227811725, - "seed": 1829414469, - "shiny": 0, - "stats": [ - 21, - 11, - 13, - 11, - 13, - 11 - ] - }, - { - "ability": 0, - "abilityIndex": 65, - "gender": 0, - "hiddenPower": 15, - "hiddenPowerStrength": 70, - "ivs": [ - 31, - 31, - 31, - 31, - 31, - 31 - ], - "level": 5, - "nature": 16, - "pid": 2375328141, - "seed": 3976898117, - "shiny": 0, - "stats": [ - 21, - 11, - 11, - 12, - 13, - 11 - ] - } - ] + "results": 142 } ] }