diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f2b8e8..0def394 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,28 +6,46 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +include(FetchContent) +option(TRACY_ENABLE "" ON) +include_directories( + ${PROJECT_SOURCE_DIR}/tracy +) + # Define sources for the library set(LIB_SOURCES src/functions.hpp src/instance.hpp + src/filters.cpp src/items.cpp src/rng.cpp src/search.cpp src/seed.cpp src/util.cpp src/functions.cpp + tracy/tracy/Tracy.hpp +) + +FetchContent_Declare ( + tracy + GIT_REPOSITORY https://github.com/wolfpld/tracy.git + GIT_TAG master + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE ) +FetchContent_MakeAvailable(tracy) # Define sources for the executable set(EXECUTABLE_SOURCES src/main.cpp + tracy/TracyClient.cpp ) # Set optimization flags based on the compiler if(MSVC) set(OPTIMIZATION_FLAGS "/Ox") # Full optimization for MSVC else() - set(OPTIMIZATION_FLAGS "-O3 -g -std=c++20 -Wall -Wextra -Wpedantic -Wno-c++17-extensions -gdwarf-3 -ldl") # Full optimization for GCC/Clang, plus debugging info + set(OPTIMIZATION_FLAGS "-O3 -g -std=c++20 -Wall -Wextra -Wpedantic -Wno-c++17-extensions -gdwarf-3 -march=native -lpthread -ldl") # Full optimization for GCC/Clang, plus debugging info endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPTIMIZATION_FLAGS}") @@ -61,4 +79,4 @@ generate_export_header(${PROJECT_NAME} ) add_executable(immol ${EXECUTABLE_SOURCES}) -target_link_libraries(immol ${PROJECT_NAME}) \ No newline at end of file +target_link_libraries(immol ${PROJECT_NAME} TracyClient) \ No newline at end of file diff --git a/src/filters.cpp b/src/filters.cpp new file mode 100644 index 0000000..d18dbf7 --- /dev/null +++ b/src/filters.cpp @@ -0,0 +1,243 @@ +#include "filters.hpp" +#include +#include + +void Filter::parseJSON(std::string input) { + //Populate Lists with variables from the Json + return; +} + + +long searchWithFilter(Instance inst, Filter &filter) { + int searchSize = filter.searchList.size(); + int modSize = filter.instanceModList.size(); + int amountFoundList[MAX_SEARCH_LIST_SIZE] = {0}; + + for (int ante = 1; ante <= filter.maxAnte; ante++) { + for(int m = 1; m <= modSize; m++) { + if(m >= filter.instanceModList[m-1].startAnte && m <= filter.instanceModList[m-1].endAnte) { + inst.unlock(filter.instanceModList[m].modifier); + } + } + for (int i = 0; i < searchSize; i++) { + if (ante > filter.searchList[i].maxAnte) { continue; } + amountFoundList[i] += searchWithObject(inst, filter.searchList[i], ante); + } + } + + //Check if you have found all the items in a list + int correct_amounts = 0; + for (int i = 0; i < searchSize; i++) { + if (amountFoundList[i] >= filter.searchList[i].amount) { + correct_amounts++; + } + } + if (correct_amounts == searchSize) { + return 1; + } + + return 0; + +} + +inline long searchWithObject(Instance inst, SearchObject &searchObject, int ante){ + switch (searchObject.searchType) { + case SearchableType::Joker: + return searchForJoker(inst, searchObject, ante); + case SearchableType::Tarot: + return searchForTarot(inst, searchObject, ante); + case SearchableType::Planet: + return searchForPlanet(inst, searchObject, ante); + case SearchableType::Spectral: + return searchForSpectral(inst, searchObject, ante); + case SearchableType::Card: + return searchForCard(inst, searchObject, ante); + case SearchableType::Tag: + return searchForTag(inst, searchObject, ante); + case SearchableType::Voucher: + return searchForVoucher(inst, searchObject, ante); + default: + return 0; + } +} + +long searchForJoker(Instance inst, SearchObject &searchObject, int ante) { + int amount_found = 0; + int max_packs = 4; + if (ante > 1) max_packs = 6; + + //I created nextJokerOnly to save on mem + //for now we'll just use storedepth given + + for(int s = 1; s <= searchObject.storeDepth; s++) { + if (inst.nextJokerOnly(ItemSource::Shop, ante) == searchObject.item) { + amount_found++; + } + } + + for (int p = 1; p <= max_packs; p++) { + if (inst.nextJokerOnly(ItemSource::Buffoon_Pack, ante) == searchObject.item) { + amount_found++; + } + } + + return amount_found; +} + +long searchForTarot(Instance inst, SearchObject &searchObject, int ante) { + int amount_found = 0; + int max_packs = 4; + if (ante > 1) max_packs = 6; + int max_store_items = 10; + if (ante > 1) max_store_items = 50; + + //Check packs + for (int p = 1; p <= max_packs; p++) { + Pack pack = packInfo(inst.nextPack(ante)); + if (pack.type == Item::Arcana_Pack || + pack.type == Item::Jumbo_Arcana_Pack || + pack.type == Item::Mega_Arcana_Pack) { + auto packContents = inst.nextArcanaPack(pack.size, 1); + for (int x = 0; x < pack.size; x++) { + if (packContents[x] == searchObject.item) { + amount_found++; + } + } + } + continue; + } + + //Check shop + for (int s = 1; s <= max_store_items; s++) { + ShopItem shop_item = inst.nextShopItem(ante); + if (shop_item.item == searchObject.item) { + amount_found++; + } + } + + return amount_found; +} + +long searchForPlanet(Instance inst, SearchObject &searchObject, int ante) { + int amount_found = 0; + int max_packs = 4; + if (ante > 1) max_packs = 6; + int max_store_items = 10; + if (ante > 1) max_store_items = 50; + + //Check packs + for (int p = 1; p <= max_packs; p++) { + Pack pack = packInfo(inst.nextPack(ante)); + if (pack.type == Item::Celestial_Pack || + pack.type == Item::Jumbo_Celestial_Pack || + pack.type == Item::Mega_Celestial_Pack) { + auto packContents = inst.nextArcanaPack(pack.size, 1); + for (int x = 0; x < pack.size; x++) { + if (packContents[x] == searchObject.item) { + amount_found++; + } + } + } + continue; + } + + //Check shop + for (int s = 1; s <= max_store_items; s++) { + ShopItem shop_item = inst.nextShopItem(ante); + if (shop_item.item == searchObject.item) { + amount_found++; + } + } + + return amount_found; +} + +long searchForSpectral(Instance inst, SearchObject &searchObject, int ante) { + int amount_found = 0; + int max_packs = 4; + if (ante > 1) max_packs = 6; + // int max_store_items = 10; + // if (ante > 1) max_store_items = 50; + + //Check packs + for (int p = 1; p <= max_packs; p++) { + Pack pack = packInfo(inst.nextPack(ante)); + if (pack.type == Item::Spectral_Pack || + pack.type == Item::Jumbo_Spectral_Pack || + pack.type == Item::Mega_Spectral_Pack) { + auto packContents = inst.nextArcanaPack(pack.size, 1); + for (int x = 0; x < pack.size; x++) { + if (packContents[x] == searchObject.item) { + amount_found++; + } + } + } + continue; + } + + //Check shop TODO: Setup instance + /*for (int s = 1; s <= max_store_items; s++) { + ShopItem shop_item = inst.nextShopItem(ante); + if (shop_item.item == &searchObject.item) { + amount_found++; + } + }*/ + + return amount_found; +} + +long searchForCard(Instance inst, SearchObject &searchObject, int ante) { + int amount_found = 0; + int max_packs = 4; + if (ante > 1) max_packs = 6; + // int max_store_items = 10; + // if (ante > 1) max_store_items = 50; + + //Check packs + for (int p = 1; p <= max_packs; p++) { + Pack pack = packInfo(inst.nextPack(ante)); + if (pack.type == Item::Standard_Pack || + pack.type == Item::Jumbo_Standard_Pack || + pack.type == Item::Mega_Standard_Pack) { + auto packContents = inst.nextArcanaPack(pack.size, 1); + for (int x = 0; x < pack.size; x++) { + if (packContents[x] == searchObject.item) { + amount_found++; + } + } + } + continue; + } + + //Check shop TODO: Setup instance + /*for (int s = 1; s <= max_store_items; s++) { + ShopItem shop_item = inst.nextShopItem(ante); + if (shop_item.item == &searchObject.item) { + amount_found++; + } + }*/ + + return amount_found; +} + + +long searchForTag(Instance inst, SearchObject &searchObject, int ante) { + int amount_found = 0; + + for(int i = 1; i <=2; i++) { + if(inst.nextTag(ante) == searchObject.item) { + amount_found++; + } + } + + return amount_found; +} + +//TODO: Setup instance prior to calling this +// May want to seperate ante 1 loop for examples like perkeo_observatory +long searchForVoucher(Instance inst, SearchObject &searchObject, int ante) { + if(inst.nextVoucher(ante) == searchObject.item) { + return 1; + } + return 0; +} \ No newline at end of file diff --git a/src/filters.hpp b/src/filters.hpp new file mode 100644 index 0000000..5388028 --- /dev/null +++ b/src/filters.hpp @@ -0,0 +1,80 @@ +#ifndef FILTERS_HPP +#define FILTERS_HPP + +#include "functions.hpp" +#include +#include + +//Defining searchable types here +enum class SearchableType { +//Objects + Joker, + Voucher, + Tag, + Tarot, + Planet, + Spectral, + Card, + Booster_Pack, +//Modifiers + Suit, + Rank, + Enhancement, + Seal, + Edition, +//Other + Deck, + Hand, + Blind + +}; + +struct SearchObject { + Item item; + SearchableType searchType; + int8_t storeDepth; + int8_t maxAnte; + int8_t amount; +}; + +struct InstanceModifier { + Item modifier; + int8_t startAnte; + int8_t endAnte; +}; + +//Possible optimizations for bigger searchList +//Generating all the items before searching +class Filter { +public: + bool orderedSearch = true; + bool preGenItems = false; + int maxAnte = 1; + + std::vector searchList; + std::vector instanceModList; + + void parseJSON(std::string input); + long generateObjects(Instance inst); +}; + +#define MAX_SEARCH_LIST_SIZE 10 + +long searchWithFilter(Instance inst, Filter &filter); +long searchWithObject(Instance inst, SearchObject &searchObject, int ante); + +//Appear in shop & packs +//TODO: Possibly combine some of these functions (They use similar code) +long searchForJoker(Instance inst, SearchObject &searchObject, int ante); +long searchForTarot(Instance inst, SearchObject &searchObject, int ante); +long searchForPlanet(Instance inst, SearchObject &searchObject, int ante); + +//Appear in packs (mostly) +long searchForSpectral(Instance inst, SearchObject &searchObject, int ante); +long searchForCard(Instance inst, SearchObject &searchObject, int ante); + +//Appears on ante +long searchForTag(Instance inst, SearchObject &searchObject, int ante); +long searchForVoucher(Instance inst, SearchObject &searchObject, int ante); + +#endif \ No newline at end of file diff --git a/src/functions.hpp b/src/functions.hpp index f9599bd..42bf693 100644 --- a/src/functions.hpp +++ b/src/functions.hpp @@ -231,6 +231,42 @@ inline Item Instance::nextSpectral(std::string source, int ante, return randchoice(RandomType::Spectral + source + anteStr, SPECTRALS); } +inline Item Instance::nextJokerOnly(std::string source, int ante) { + std::string anteStr = anteToString(ante); + + // Get rarity + Item rarity; + double rarityPoll = random(RandomType::Joker_Rarity + anteStr + source); + if (rarityPoll > 0.95) + rarity = Item::Rare; + else if (rarityPoll > 0.7) + rarity = Item::Uncommon; + else + rarity = Item::Common; + + // Get next joker + Item joker; + if (rarity == Item::Legendary) { + if (params.version > 10099) { + joker = randchoice(RandomType::Joker_Legendary, LEGENDARY_JOKERS); + } else { + joker = randchoice(RandomType::Joker_Legendary + source + anteStr, + LEGENDARY_JOKERS); + } + } else if (rarity == Item::Rare) { + joker = randchoice(RandomType::Joker_Rare + source + anteStr, + RARE_JOKERS); + } else if (rarity == Item::Uncommon) { + joker = randchoice(RandomType::Joker_Uncommon + source + anteStr, + UNCOMMON_JOKERS); + } else if (rarity == Item::Common) { + joker = randchoice(RandomType::Joker_Common + source + anteStr, + COMMON_JOKERS); + } + + return joker; +} + inline JokerData Instance::nextJoker(std::string source, int ante, bool hasStickers) { std::string anteStr = anteToString(ante); diff --git a/src/instance.hpp b/src/instance.hpp index 4489a81..4d2ae89 100644 --- a/src/instance.hpp +++ b/src/instance.hpp @@ -116,6 +116,7 @@ struct Instance { Item nextPlanet(std::string source, int ante, bool soulable); Item nextSpectral(std::string source, int ante, bool soulable); JokerData nextJoker(std::string source, int ante, bool hasStickers); + Item nextJokerOnly(std::string source, int ante); ShopInstance getShopInstance(); ShopItem nextShopItem(int ante); Item nextPack(int ante); diff --git a/src/main.cpp b/src/main.cpp index f8dba31..8beac4d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,12 @@ #include "functions.hpp" #include "search.hpp" +#include "filters.hpp" #include #include #include +#include "tracy/Tracy.hpp" + +Filter globalFilter; long filter(Instance inst) { long legendaries = 0; @@ -147,11 +151,15 @@ long filter_test(Instance inst) { return 0; } +long filter_custom(Instance inst) { + return searchWithFilter(inst, globalFilter); +} + // Benchmark function // Runs 1 billion seeds of perkeo observatory // And prints total time and seeds per second void benchmark() { - long total = 0; + //long total = 0; long start = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); @@ -169,7 +177,7 @@ void benchmark() { } void benchmark_quick() { - long total = 0; + //long total = 0; long start = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); @@ -187,7 +195,7 @@ void benchmark_quick() { } void benchmark_quick_lucky() { - long total = 0; + //long total = 0; long start = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); @@ -205,7 +213,7 @@ void benchmark_quick_lucky() { } void benchmark_single() { - long total = 0; + //long total = 0; long start = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); @@ -223,7 +231,7 @@ void benchmark_single() { } void benchmark_blank() { - long total = 0; + //long total = 0; long start = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) .count(); @@ -239,11 +247,42 @@ void benchmark_blank() { << 100000000 / ((end - start) / 1000.0) << "\n"; } +#define TEMP_TEST_SIZE 10000000 + +void benchmark_custom() { + //long total = 0; + long start = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + Search search(filter_custom, "IMMOLATE", 12, TEMP_TEST_SIZE); + search.highScore = 10; // No output + search.printDelay = 100000000000; + search.search(); + long end = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + std::cout << "----CUSTOM FILTER----\n"; + std::cout << "Total time: " << end - start << "ms\n"; + std::cout << "Seeds per second: " << std::fixed << std::setprecision(0) + << TEMP_TEST_SIZE / ((end - start) / 1000.0) << "\n"; +} + +void setup_custom_filter() { + globalFilter.maxAnte = 2; + globalFilter.searchList = std::vector(); + globalFilter.searchList.push_back({Item::Blueprint, SearchableType::Joker, 5, 1, 1}); + //globalFilter.searchList.push_back({Item::Telescope, SearchableType::Voucher, 1, 1, 1}); + //globalFilter.searchList.push_back({Item::Observatory, SearchableType::Voucher, 1, 2, 1}); + //globalFilter.instanceModList.push_back({Item::Observatory, 2, 2}); +} + int main() { - benchmark_single(); - benchmark_quick(); - benchmark_quick_lucky(); + setup_custom_filter(); benchmark_blank(); - benchmark(); + //benchmark_single(); + benchmark_quick(); + benchmark_custom(); + //benchmark_quick_lucky(); + //benchmark(); return 1; } \ No newline at end of file diff --git a/src/util.hpp b/src/util.hpp index 4fbbe4e..8435d44 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -4,6 +4,7 @@ #include #include #include +#include "tracy/Tracy.hpp" const uint64_t MAX_UINT64 = 18446744073709551615ull;