Skip to content

Commit

Permalink
Further Gamecube searcher improvements
Browse files Browse the repository at this point in the history
Fixes #325
  • Loading branch information
Admiral-Fish committed Aug 8, 2023
1 parent 8afac47 commit d03bf51
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 938 deletions.
36 changes: 22 additions & 14 deletions Source/Core/Gen3/Searchers/GameCubeSearcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -74,37 +74,43 @@ 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);

u16 num1 = rng.nextUShort();
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;
}
}
Expand Down Expand Up @@ -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<const SearcherState &>(state)))
{
std::lock_guard<std::mutex> guard(mutex);
Expand Down Expand Up @@ -494,9 +501,10 @@ std::vector<SearcherState> 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
Expand Down
64 changes: 56 additions & 8 deletions Source/Core/Gen3/ShadowLock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down
53 changes: 23 additions & 30 deletions Source/Test/Gen3/GameCubeSearcherTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,37 +50,24 @@ static bool operator==(const SearcherState &left, const GeneratorState &right)
}
}

static bool operator==(const SearcherState &left, const json &right)
{
return left.getPID() == right["pid"].get<u32>() && left.getStats() == right["stats"].get<std::array<u16, 6>>()
&& left.getAbilityIndex() == right["abilityIndex"].get<u16>() && left.getIVs() == right["ivs"].get<std::array<u8, 6>>()
&& left.getAbility() == right["ability"].get<u8>() && left.getGender() == right["gender"].get<u8>()
&& left.getHiddenPower() == right["hiddenPower"].get<u8>()
&& left.getHiddenPowerStrength() == right["hiddenPowerStrength"].get<u8>() && left.getLevel() == right["level"].get<u8>()
&& left.getNature() == right["nature"].get<u8>() && left.getShiny() == right["shiny"].get<u8>()
&& left.getSeed() == right["seed"].get<u32>();
}

void GameCubeSearcherTest::searchChannel_data()
{
QTest::addColumn<IVs>("min");
QTest::addColumn<IVs>("max");
QTest::addColumn<std::string>("results");
QTest::addColumn<int>("results");

json data = readData("gamecube", "gamecubesearcher", "searchChannel");
for (const auto &d : data)
{
QTest::newRow(d["name"].get<std::string>().data()) << d["min"].get<IVs>() << d["max"].get<IVs>() << d["results"].get<json>().dump();
QTest::newRow(d["name"].get<std::string>().data()) << d["min"].get<IVs>() << d["max"].get<IVs>() << d["results"].get<int>();
}
}

void GameCubeSearcherTest::searchChannel()
{
QFETCH(IVs, min);
QFETCH(IVs, max);
QFETCH(std::string, results);

json j = json::parse(results);
QFETCH(int, results);

std::array<bool, 25> natures;
natures.fill(true);
Expand All @@ -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]);
}
}

Expand Down Expand Up @@ -221,13 +212,13 @@ void GameCubeSearcherTest::searchNonLock_data()
QTest::addColumn<IVs>("max");
QTest::addColumn<Game>("version");
QTest::addColumn<int>("pokemon");
QTest::addColumn<std::string>("results");
QTest::addColumn<int>("results");

json data = readData("gamecube", "gamecubesearcher", "searchNonLock");
for (const auto &d : data)
{
QTest::newRow(d["name"].get<std::string>().data()) << d["min"].get<IVs>() << d["max"].get<IVs>() << d["version"].get<Game>()
<< d["pokemon"].get<int>() << d["results"].get<json>().dump();
QTest::newRow(d["name"].get<std::string>().data())
<< d["min"].get<IVs>() << d["max"].get<IVs>() << d["version"].get<Game>() << d["pokemon"].get<int>() << d["results"].get<int>();
}
}

Expand All @@ -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<bool, 25> natures;
natures.fill(true);
Expand All @@ -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]);
}
}
Loading

0 comments on commit d03bf51

Please sign in to comment.