Skip to content

Commit

Permalink
Reduce size of IV tables
Browse files Browse the repository at this point in the history
  • Loading branch information
Admiral-Fish committed Jun 6, 2024
1 parent 5bb3ec0 commit ff14f75
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 135 deletions.
132 changes: 74 additions & 58 deletions Source/Core/Gen5/IVSeedCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,38 +20,26 @@
#include "IVSeedCache.hpp"
#include <Core/Enum/Game.hpp>
#include <Core/Parents/Filters/StateFilter.hpp>
#include <Core/RNG/MTFast.hpp>
#include <Core/Resources/IVs.hpp>
#include <Core/Util/Utilities.hpp>
#include <numeric>

struct IV
enum class CacheType
{
u16 hp : 1;
u16 atk : 5;
u16 def : 1;
u16 spa : 5;
u16 spd : 1;
u16 spe : 2;
Entralink,
Normal,
Roamer
};
static_assert(sizeof(IV) == 2);

#pragma pack(push, 1)
struct IVEntry
{
u32 seed;
IV iv;
};
#pragma pack(pop)
static_assert(sizeof(IVEntry) == 6);

struct IVCache
struct SeedCache
{
std::array<u16, 10> entralinkCount;
std::array<u16, 8> normalCount;
std::array<u16, 6> roamerCount;
IVEntry data[];
u32 seeds[];
};
static_assert(sizeof(IVCache) == 48);
static_assert(sizeof(SeedCache) == 48);

static bool compareIVs(const std::array<u8, 6> &ivs, const StateFilter &filter)
{
Expand All @@ -67,46 +55,68 @@ static bool compareIVs(const std::array<u8, 6> &ivs, const StateFilter &filter)
return filter.compareIV(ivs) && filter.compareHiddenPower(hiddenPower);
}

static std::array<u8, 6> computeIVs(IV iv)
template <CacheType type>
static std::array<u8, 6> computeIVs(u32 seed, u8 advance)
{
// HP maps 0-1 to 30-31
// Atk maps 0-31 to 0-31
// Def maps 0-1 to 30-31
// SpA maps 0-31 to 0-31
// SpD maps 0-1 to 0-31
// Spe maps 0-1 to 30-31 and 2-3 to 0-1
return { static_cast<u8>(30 + iv.hp), static_cast<u8>(iv.atk), static_cast<u8>(30 + iv.def),
static_cast<u8>(iv.spa), static_cast<u8>(30 + iv.spd), static_cast<u8>((30 + iv.spe) & 0x1f) };
std::array<u8, 6> ivs;

if constexpr (type == CacheType::Entralink)
{
advance += 22;
}
else if constexpr (type == CacheType::Roamer)
{
advance += 1;
}

constexpr u16 size = type == CacheType::Entralink ? 37 : type == CacheType::Normal ? 13 : 12;
MTFast<size, true> mt(seed, advance);

ivs[0] = mt.next();
ivs[1] = mt.next();
ivs[2] = mt.next();
if constexpr (type == CacheType::Roamer)
{
ivs[4] = mt.next();
ivs[5] = mt.next();
ivs[3] = mt.next();
}
else
{
ivs[3] = mt.next();
ivs[4] = mt.next();
ivs[5] = mt.next();
}

return ivs;
}

namespace IVSeedCache
{
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getNormalCache(u32 initialAdvance, u32 maxAdvance, Game version,
const StateFilter &filter)
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getEntralinkCache(u32 initialAdvance, u32 maxAdvance,
const StateFilter &filter)
{
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> cache;

bool bw = (version & Game::BW) != Game::None;

u32 size;
u8 *data = Utilities::decompress(IVS.data(), IVS.size(), size);
const auto *ivCache = reinterpret_cast<const IVCache *>(data);
const auto *seedCache = reinterpret_cast<const SeedCache *>(data);

u32 index = std::accumulate(ivCache->entralinkCount.begin(), ivCache->entralinkCount.end(), 0);
u32 index = 0;

for (u32 i = initialAdvance; i <= (initialAdvance + maxAdvance) && i < cache.size(); i++)
{
u16 count = ivCache->normalCount[i + (bw ? 0 : 2)];
u16 count = seedCache->entralinkCount[i];

cache[i].reserve(count);

const IVEntry *entry = &ivCache->data[index];
for (u16 j = 0; j < count; j++, entry++)
for (u16 j = 0; j < count; j++)
{
auto ivs = computeIVs(entry->iv);
u32 seed = seedCache->seeds[index + j];
auto ivs = computeIVs<CacheType::Entralink>(seed, i);
if (compareIVs(ivs, filter))
{
cache[i].emplace(entry->seed, ivs);
cache[i].emplace(seed, ivs);
}
}
cache[i].max_load_factor(cache[i].max_load_factor_upper_limit());
Expand All @@ -119,30 +129,36 @@ namespace IVSeedCache
return cache;
}

std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getRoamerCache(u32 initialAdvance, u32 maxAdvance, const StateFilter &filter)
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getNormalCache(u32 initialAdvance, u32 maxAdvance, Game version,
const StateFilter &filter)
{
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> cache;

bool bw = (version & Game::BW) != Game::None;

u32 size;
u8 *data = Utilities::decompress(IVS.data(), IVS.size(), size);
const auto *ivCache = reinterpret_cast<const IVCache *>(data);
const auto *seedCache = reinterpret_cast<const SeedCache *>(data);

u32 index = std::accumulate(ivCache->normalCount.begin(), ivCache->normalCount.end(),
std::accumulate(ivCache->entralinkCount.begin(), ivCache->entralinkCount.end(), 0));
u32 index = std::accumulate(seedCache->entralinkCount.begin(), seedCache->entralinkCount.end(), 0);
if (!bw)
{
index += seedCache->normalCount[0] + seedCache->normalCount[1];
}

for (u32 i = initialAdvance; i <= (initialAdvance + maxAdvance) && i < cache.size(); i++)
{
u16 count = ivCache->roamerCount[i];
u16 count = seedCache->normalCount[i + (bw ? 0 : 2)];

cache[i].reserve(count);

const IVEntry *entry = &ivCache->data[index];
for (u16 j = 0; j < count; j++, entry++)
for (u16 j = 0; j < count; j++)
{
auto ivs = computeIVs(entry->iv);
u32 seed = seedCache->seeds[index + j];
auto ivs = computeIVs<CacheType::Normal>(seed, i + (bw ? 0 : 2));
if (compareIVs(ivs, filter))
{
cache[i].emplace(entry->seed, ivs);
cache[i].emplace(seed, ivs);
}
}
cache[i].max_load_factor(cache[i].max_load_factor_upper_limit());
Expand All @@ -155,30 +171,30 @@ namespace IVSeedCache
return cache;
}

std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getEntralinkCache(u32 initialAdvance, u32 maxAdvance,
const StateFilter &filter)
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getRoamerCache(u32 initialAdvance, u32 maxAdvance, const StateFilter &filter)
{
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> cache;

u32 size;
u8 *data = Utilities::decompress(IVS.data(), IVS.size(), size);
const auto *ivCache = reinterpret_cast<const IVCache *>(data);
const auto *seedCache = reinterpret_cast<const SeedCache *>(data);

u32 index = 0;
u32 index = std::accumulate(seedCache->normalCount.begin(), seedCache->normalCount.end(),
std::accumulate(seedCache->entralinkCount.begin(), seedCache->entralinkCount.end(), 0));

for (u32 i = initialAdvance; i <= (initialAdvance + maxAdvance) && i < cache.size(); i++)
{
u16 count = ivCache->entralinkCount[i];
u16 count = seedCache->roamerCount[i];

cache[i].reserve(count);

const IVEntry *entry = &ivCache->data[index];
for (u16 j = 0; j < count; j++, entry++)
for (u16 j = 0; j < count; j++)
{
auto ivs = computeIVs(entry->iv);
u32 seed = seedCache->seeds[index + j];
auto ivs = computeIVs<CacheType::Roamer>(seed, i);
if (compareIVs(ivs, filter))
{
cache[i].emplace(entry->seed, ivs);
cache[i].emplace(seed, ivs);
}
}
cache[i].max_load_factor(cache[i].max_load_factor_upper_limit());
Expand Down
18 changes: 9 additions & 9 deletions Source/Core/Gen5/IVSeedCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,40 +33,40 @@ enum class Game : u32;
namespace IVSeedCache
{
/**
* @brief Returns the IV caches for most encounter types
* @brief Returns the IV caches for entralink
*
* @param initialAdvance Initial IV advances
* @param maxAdvance Maximum IV advances
* @param version Game version
* @param filter IV filter
*
* @return IV caches
*/
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getNormalCache(u32 initialAdvance, u32 maxAdvance, Game version,
const StateFilter &filter);
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getEntralinkCache(u32 initialAdvance, u32 maxAdvance,
const StateFilter &filter);

/**
* @brief Returns the IV caches for roamers
* @brief Returns the IV caches for most encounter types
*
* @param initialAdvance Initial IV advances
* @param maxAdvance Maximum IV advances
* @param version Game version
* @param filter IV filter
*
* @return IV caches
*/
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getRoamerCache(u32 initialAdvance, u32 maxAdvance, const StateFilter &filter);
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getNormalCache(u32 initialAdvance, u32 maxAdvance, Game version,
const StateFilter &filter);

/**
* @brief Returns the IV caches for entralink
* @brief Returns the IV caches for roamers
*
* @param initialAdvance Initial IV advances
* @param maxAdvance Maximum IV advances
* @param filter IV filter
*
* @return IV caches
*/
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getEntralinkCache(u32 initialAdvance, u32 maxAdvance,
const StateFilter &filter);
std::array<fph::DynamicFphMap<u32, std::array<u8, 6>>, 6> getRoamerCache(u32 initialAdvance, u32 maxAdvance, const StateFilter &filter);
};

#endif // IVSEEDCACHE_HPP
Binary file modified Source/Core/Resources/IVs/ivs.bin
Binary file not shown.
Loading

0 comments on commit ff14f75

Please sign in to comment.