From 74a1ef5972f3b868aee3d38960a5e0551dd3e2fb Mon Sep 17 00:00:00 2001 From: Frenchythefry Date: Fri, 27 Jun 2025 18:06:01 -0400 Subject: [PATCH 1/2] Added argument support and other minor changes --- build.bat | 4 -- build.sh | 3 +- src/main.cpp | 169 +++++++++++++++++++++++++++++++++++++++++++++---- src/search.hpp | 26 +++++--- 4 files changed, 172 insertions(+), 30 deletions(-) delete mode 100644 build.bat diff --git a/build.bat b/build.bat deleted file mode 100644 index dca3585..0000000 --- a/build.bat +++ /dev/null @@ -1,4 +0,0 @@ -cmake -G "Visual Studio 17 2022" -A x64 -B .\build -cmake --build .\build --config Release --target ALL_BUILD - -pause \ No newline at end of file diff --git a/build.sh b/build.sh index 2cd0b55..80e5a36 100755 --- a/build.sh +++ b/build.sh @@ -9,5 +9,4 @@ cmake -B build -DCMAKE_BUILD_TYPE=Release # Build the project cmake --build build --config Release --target all -# Pause (optional, can be removed if not needed) -read -p "Press any key to continue..." \ No newline at end of file + diff --git a/src/main.cpp b/src/main.cpp index 5467468..46b73af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,7 @@ #include #include -long filter(Instance inst) { +long filter_double_legendary(Instance inst) { long legendaries = 0; inst.nextPack(1); for (int p = 1; p <= 3; p++) { @@ -135,6 +135,38 @@ long filter_cavendish(Instance inst) { return 5; } +long filter_stencil(Instance inst) +{ + inst.initLocks(1, false, false); + // Check for a Charm Tag (Arcana Pack) + if (inst.nextTag(1) != Item::Charm_Tag) + { + std::cout << "0\n"; + return 0; + } + // Check for a Judgement within that pack + std::vector packContents = inst.nextArcanaPack(5, 1); + bool hasJudgement = false; + for (int i = 0; i < 5; i++) + { + if (packContents[i] == Item::Judgement) + { + hasJudgement = true; + } + } + if (!hasJudgement) + { + std::cout << "1\n"; + return 1; + } + if (inst.nextJoker(ItemSource::Judgement, 1, false).joker != Item::Joker_Stencil) + { + std::cout << "2\n"; + return 2; + } + std::cout << "FOUND SEED AT " << inst.hashedSeed; + return 3; +} long filter_blank(Instance inst) { return 0; } // These won't be permanent filters, just ones I sub in and out while JSON @@ -179,7 +211,7 @@ long filter_test(Instance inst) { // Benchmark function // Runs 1 billion seeds of perkeo observatory // And prints total time and seeds per second -void benchmark() { +void benchmark_perkeo_observatory() { long total = 0; long start = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()) @@ -268,15 +300,124 @@ void benchmark_blank() { << 100000000 / ((end - start) / 1000.0) << "\n"; } -int main() { - /*benchmark_single(); - benchmark_quick(); - benchmark_quick_lucky(); - benchmark_blank(); - benchmark();*/ - Search search(filter_cavendish, "11111J31", 8, 2318107019761); - search.highScore = 5; - search.printDelay = 2318107019761; - search.search(); - return 1; -} \ No newline at end of file +int main(int argc, char *argv[]) { + std::map> filters{ + {"cavendish", filter_cavendish}, + {"stencil", filter_stencil}, + {"test", filter_test}, + {"suas_speedrun", filter_suas_speedrun}, + {"perkeo_observatory", filter_perkeo_observatory}, + {"lucky", filter_lucky}, + {"double_legendary", filter_double_legendary}, + {"negative_tag", filter_negative_tag} + }; + std::map> benchmarks{ + {"perkeo_observatory", benchmark_perkeo_observatory}, + {"quick", benchmark_quick}, + {"quick_lucky", benchmark_quick_lucky}, + {"single", benchmark_single} + }; + + std::string filterKey = "null"; + std::string startSeed = "0"; + long long numSeeds = 2318107019761; + long long highScore = 1; + int threads = 8; + long long printDelay = 10000000; + bool saveToFile = false; + bool stopOnFind = false; + + auto printHelp = []() { + std::cout << "usage: immol [option] arg_name \noptions: \n" + << "-f: Sets the filter used by the search.\n" + << "-b: Sets the benchmark to be ran by the searcher. Incompatible with all other options.\n" + << "-s: Sets the starting seed of the search.\n" + << "-n: Sets the number of seeds to search.\n" + << "-g: Sets the score the filter needs to return for a seed to be printed.\n" + << "-p: Sets how often the seed searcher should report progress.\n" + << "-t: Sets the number of CPU threads created by the searcher.\n" + << "-v: Saves found seeds to ./Immolate/seeds.txt.\n" + << "-x: Stops the program when seed is found.\n" + << "-fl: Lists available filters.\n" + << "-bl: Lists available benchmarks\n" + << "-h: Shows this help text." << std::endl; + }; + + try { + for (int i = 0; i < argc; i++) { + if (argv[i] == std::string("-h")) { + printHelp(); + return 0; + } + if (argv[i] == std::string("-bl")) { + std::cout << "Benchmarks:\n"; + for (const auto& [key, _] : benchmarks) + std::cout << key << " "; + std::cout << std::endl; + return 0; + } + if (argv[i] == std::string("-fl")) { + std::cout << "Filters:\n"; + for (const auto& [key, _] : filters) + std::cout << key << " "; + std::cout << std::endl; + return 0; + } + if (argv[i] == std::string("-f")) { + if (i + 1 >= argc) throw std::invalid_argument("Missing or invalid value for -f"); + filterKey = argv[i + 1]; + } + if (argv[i] == std::string("-b")) { + if (i + 1 >= argc) throw std::invalid_argument("Missing or invalid value for -b"); + if (benchmarks.count(argv[i + 1]) == 0) + throw std::invalid_argument("Unknown benchmark: " + std::string(argv[i + 1])); + benchmarks[argv[i + 1]](); + return 0; + } + if (argv[i] == std::string("-s")) { + if (i + 1 >= argc) throw std::invalid_argument("Missing or invalid value for -s"); + startSeed = argv[i + 1]; + } + if (argv[i] == std::string("-n")) { + if (i + 1 >= argc) throw std::invalid_argument("Missing or invalid value for -n"); + numSeeds = std::stoll(argv[i + 1]); + } + if (argv[i] == std::string("-g")) { + if (i + 1 >= argc) throw std::invalid_argument("Missing or invalid value for -g"); + highScore = std::stoll(argv[i + 1]); + } + if (argv[i] == std::string("-p")) { + if (i + 1 >= argc) throw std::invalid_argument("Missing or invalid value for -p"); + printDelay = std::stoll(argv[i + 1]); + } + if (argv[i] == std::string("-t")) { + if (i + 1 >= argc) throw std::invalid_argument("Missing or invalid value for -t"); + threads = std::stoi(argv[i + 1]); + } + if (argv[i] == std::string("-v")) { + saveToFile = true; + } + if (argv[i] == std::string("-x")) { + stopOnFind = true; + } + } + + if (filters.count(filterKey) == 0 || filterKey == "null") { + throw std::invalid_argument("Missing or invalid value for -f (null or nonexistent filter: " + filterKey + ")"); + printHelp(); + } + + Search search(filters[filterKey], startSeed, threads, numSeeds); + search.highScore = highScore; + search.printDelay = printDelay; + search.saveToFile = saveToFile; + search.exitOnFind = stopOnFind; + search.search(); + return 1; + + } catch (const std::exception& e) { + std::cerr << "ERROR: " << e.what() << "\n\n"; + printHelp(); + return 1; + } +} diff --git a/src/search.hpp b/src/search.hpp index 4c96329..6cb3c38 100644 --- a/src/search.hpp +++ b/src/search.hpp @@ -1,6 +1,6 @@ #ifndef SEARCH_HPP #define SEARCH_HPP - +#include #include "instance.hpp" #include #include @@ -26,29 +26,24 @@ class Search { std::atomic found{false}; // Atomic flag to signal when a solution is found Seed foundSeed; // Store the found seed bool exitOnFind = false; - long long startSeed; - int numThreads; - long long numSeeds; + bool saveToFile = true; + long long startSeed = 0; + int numThreads = 8; + long long numSeeds = 2318107019761; std::mutex mtx; std::atomic nextBlock{0}; // Shared index for the next block to be processed Search(std::function f) { filter = f; - startSeed = 0; - numThreads = 1; - numSeeds = 2318107019761; } Search(std::function f, int t) { filter = f; - startSeed = 0; numThreads = t; - numSeeds = 2318107019761; } Search(std::function f, int t, long long n) { filter = f; - startSeed = 0; numThreads = t; numSeeds = n; }; @@ -70,6 +65,12 @@ class Search { std::lock_guard lock(mtx); highScore = result; foundSeed = s; + if (saveToFile) + { + std::ofstream seeds("seeds.txt", std::ios_base::app); + seeds << s.tostring() + "\n"; + seeds.close(); + } std::cout << "Found seed: " << s.tostring() << " (" << result << ")" << std::endl; if (exitOnFind) { @@ -86,6 +87,11 @@ class Search { } std::string search() { + if (saveToFile) + { + std::ofstream output("seeds.txt", std::ofstream::out | std::ofstream::trunc); + output.close(); + } std::vector threads; long long totalBlocks = (numSeeds + BLOCK_SIZE - 1) / BLOCK_SIZE; for (int t = 0; t < numThreads; t++) { From 0eb1876ec829e28193397edf3587ac29965a9a3a Mon Sep 17 00:00:00 2001 From: Frenchythefry Date: Fri, 27 Jun 2025 18:10:37 -0400 Subject: [PATCH 2/2] Add CLI validation, filters/benchmarks listing, and QOL flags --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 46b73af..f6c9e49 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -135,6 +135,7 @@ long filter_cavendish(Instance inst) { return 5; } +//super simple and fast testing filter I was using long filter_stencil(Instance inst) { inst.initLocks(1, false, false);