3939#include < fstream>
4040#include < filesystem>
4141#include < cmath>
42+ #include < functional>
4243
4344#ifdef DEBUG
4445
@@ -66,6 +67,8 @@ struct TC {
6667
6768 Entry items[10 ];
6869
70+ std::string condition = " " ;
71+
6972 int total = 0 ;
7073};
7174
@@ -91,11 +94,13 @@ namespace std {
9194 template <>
9295 struct hash <Drop> {
9396 std::size_t operator ()(const Drop& d) const {
94- return ((std::hash<std::string>()(d.name )
95- ^ (std::hash<int >()(d.magic ) << 1 )) >> 1 )
96- ^ (std::hash<int >()(d.rare ) << 1 )
97- ^ (std::hash<int >()(d.set ) << 1 )
98- ^ (std::hash<int >()(d.unique ) << 1 );
97+ std::size_t h1 = std::hash<std::string>()(d.name );
98+ std::size_t h2 = std::hash<int >()(d.magic );
99+ std::size_t h3 = std::hash<int >()(d.rare );
100+ std::size_t h4 = std::hash<int >()(d.set );
101+ std::size_t h5 = std::hash<int >()(d.unique );
102+
103+ return h1 ^ (h2 << 1 ) ^ (h3 << 2 ) ^ (h4 << 3 ) ^ (h5 << 4 );
99104 }
100105 };
101106}
@@ -111,6 +116,17 @@ std::unordered_map<std::string, TC> treasureClasses;
111116
112117long playermod = 1 ;
113118int finditem = 0 ;
119+ int heraldtier = 1 ;
120+ int difficulty = 0 ;
121+
122+ std::unordered_map<std::string, std::function<bool ()>> conditionFunctions = {
123+ {" \" cond('Difficulty', normal)\" " , []() { return difficulty == 0 ; }},
124+ {" \" cond('Difficulty', nightmare)\" " , []() { return difficulty == 1 ; }},
125+ {" \" cond('Difficulty', hell)\" " , []() { return difficulty == 2 ; }},
126+ {" \" cond('MonsterTestElite', herald)*(stat('heraldtier'.accr) >3) \" " , []() { return heraldtier > 3 ; }},
127+ {" (stat('heraldtier'.accr)>1) * (stat('heraldtier'.accr) < 4)" , []() { return heraldtier > 1 && heraldtier < 4 ; }},
128+ {" (stat('heraldtier'.accr) >=4) " , []() { return heraldtier >= 4 ; }},
129+ };
114130
115131// Helper function to split string by tab delimiter, keeping empty strings between tabs
116132std::vector<std::string> splitByChar (const std::string& str, char delimiter) {
@@ -184,10 +200,6 @@ long calcNodrop(long e, long nd, long d) {
184200}
185201
186202void pick (std::mt19937& gen, std::string tcname, int magic, int rare, int set, int unique, std::vector<Drop>& drops, int depth = 0 ) {
187- if (drops.size () >= 6 ) {
188- return ;
189- }
190-
191203 if (treasureClasses.find (tcname) == treasureClasses.end ()) {
192204 pickAtomic (gen, tcname, magic, rare, set, unique, drops);
193205 return ;
@@ -247,14 +259,6 @@ void pick(std::mt19937& gen, std::string tcname, int magic, int rare, int set, i
247259
248260 if (tc.picks > 0 ) {
249261 for (int i = 0 ; i < picks; i++) {
250- if (drops.size () >= 6 ) {
251- #ifdef DEBUG
252- std::cout << tc.name << " drop cap reached" << std::endl;
253- wait ();
254- #endif
255- return ;
256- }
257-
258262 long picknum = dis (gen) - nodrop;
259263
260264 if (picknum < 0 ) {
@@ -273,6 +277,12 @@ void pick(std::mt19937& gen, std::string tcname, int magic, int rare, int set, i
273277 wait ();
274278 #endif
275279 pick (gen, item.name , magic, rare, set, unique, drops, depth + 1 );
280+
281+ if (drops.size () >= 6 ) {
282+ // Game can only drop 6, so stop recursion early if we hit that limit to save time.
283+ return ;
284+ }
285+
276286 break ;
277287 }
278288
@@ -284,7 +294,7 @@ void pick(std::mt19937& gen, std::string tcname, int magic, int rare, int set, i
284294 else {
285295 for (auto item : tc.items ) {
286296 for (int i = 0 ; i < item.prob ; i++) {
287- if (picks <= 0 || drops. size () >= 6 ) {
297+ if (picks <= 0 ) {
288298 #ifdef DEBUG
289299 std::cout << tc.name << " is out of picks" << std::endl;
290300 wait ();
@@ -297,6 +307,11 @@ void pick(std::mt19937& gen, std::string tcname, int magic, int rare, int set, i
297307 wait ();
298308 #endif
299309 pick (gen, item.name , magic, rare, set, unique, drops, depth + 1 );
310+ if (drops.size () >= 6 ) {
311+ // Game can only drop 6, so stop recursion early if we hit that limit to save time.
312+ return ;
313+ }
314+
300315 picks--;
301316 }
302317 }
@@ -386,7 +401,7 @@ std::string trim(const std::string& str) {
386401// Main takes first parameter as treasure class name
387402int main (int argc, char * argv[]) {
388403 if (argc < 2 ) {
389- std::cerr << " Usage: " << argv[0 ] << " <treasure_class_name> <player_mod> <find_item_percent>\n " ;
404+ std::cerr << " Usage: " << argv[0 ] << " <treasure_class_name> <player_mod> <find_item_percent> <difficulty> <herald_tier> \n " ;
390405 return 1 ;
391406 }
392407
@@ -414,6 +429,14 @@ int main(int argc, char* argv[]) {
414429 finditem = atoi (argv[3 ]);
415430 }
416431
432+ if (argc >= 5 ) {
433+ difficulty = atoi (argv[4 ]);
434+ }
435+
436+ if (argc >= 6 ) {
437+ heraldtier = atoi (argv[5 ]);
438+ }
439+
417440 // Open the treasure class file at: txt/treasureclassex.txt
418441 FILE* tex = fopen ((txtDir + (BASETC ? " base/treasureclassex.txt" : " treasureclassex.txt" )).c_str (), " r" );
419442 if (!tex) {
@@ -483,11 +506,52 @@ int main(int argc, char* argv[]) {
483506
484507 }
485508
509+ if (tokens.size () > 32 ) {
510+ tc.condition = tokens[32 ];
511+ }
512+
486513 treasureClasses[tc.name ] = tc;
487514 }
488515
489516 fclose (tex);
490517
518+ for (auto &[name, tc] : treasureClasses) {
519+ if (!tc.condition .empty ()) {
520+ if (conditionFunctions.find (tc.condition ) == conditionFunctions.end ()) {
521+ std::cerr << " Error: No function found for condition on treasure class: " << name << " .\n " ;
522+ return 1 ;
523+ }
524+
525+ if (!conditionFunctions[tc.condition ]()) {
526+ std::cerr << " Condition not met for treasure class: " << name << " , disabling it.\n " ;
527+ tc.total = 0 ; // Effectively disable this treasure class by setting total to 0
528+ for (auto &item : tc.items ) {
529+ item.prob = 0 ; // Set all item probabilities to 0 as well
530+ }
531+ }
532+ }
533+
534+ for (auto &[itemName, itemProb] : tc.items ) {
535+ auto targetName = itemName;
536+ // Check if itemName is a treasure class.
537+ if (treasureClasses.find (itemName) != treasureClasses.end ()) {
538+ // If so, we need to check if that treasure class has a condition that would disable it, and if so, disable this item as well by setting its probability to 0.
539+ TC& targetTC = treasureClasses[itemName];
540+ if (!targetTC.condition .empty ()) {
541+ if (conditionFunctions.find (targetTC.condition ) == conditionFunctions.end ()) {
542+ std::cerr << " Error: No function found for condition on nested treasure class: " << itemName << " .\n " ;
543+ return 1 ;
544+ }
545+
546+ if (!conditionFunctions[targetTC.condition ]()) {
547+ tc.total -= itemProb; // Remove this item's probability from the total
548+ itemProb = 0 ;
549+ }
550+ }
551+ }
552+ }
553+ }
554+
491555 // Open the file at: atomic.txt
492556 FILE* atomicbase = fopen ((path + (BASETC ? " atomicbase.txt" : " atomic.txt" )).c_str (), " r" );
493557
@@ -616,13 +680,17 @@ int main(int argc, char* argv[]) {
616680 std::cout << " \" tc\" : \" " << tcname << " \" ,\n " ;
617681 std::cout << " \" playermod\" : " << playermod << " ,\n " ;
618682 std::cout << " \" runs\" : " << finalSims << " ,\n " ;
619- std::cout << " \" picks\" : " << finalPicks << " ,\n " ;
620- std::cout << " \" avgpicks\" : " << std::fixed << std::setprecision (6 ) << (double )finalPicks / finalSims << " ,\n " ;
683+ std::cout << " \" finditem\" : " << finditem << " ,\n " ;
621684 std::cout << " \" drops\" : [\n " ;
622685
686+ // Convert to vector and sort by count descending
687+ std::vector<std::pair<Drop, long >> sortedDrops (finaldrops.begin (), finaldrops.end ());
688+ std::sort (sortedDrops.begin (), sortedDrops.end (),
689+ [](const auto & a, const auto & b) { return a.second > b.second ; });
690+
623691 long count = 0 ;
624692
625- for (const auto & drop : finaldrops ) {
693+ for (const auto & drop : sortedDrops ) {
626694 std::string escapedDrop = drop.first .name ;
627695 // Escape backslashes and double quotes in the drop name
628696 size_t pos = 0 ;
@@ -636,7 +704,7 @@ int main(int argc, char* argv[]) {
636704 pos += 2 ; // Move past the escaped quote
637705 }
638706 std::cout << " [\" " + trim (escapedDrop) + " \" , " << drop.second << " , " << drop.first .magic << " , " << drop.first .rare << " , " << drop.first .set << " , " << drop.first .unique << " ]" ;
639- if (++count < finaldrops .size ()) {
707+ if (++count < sortedDrops .size ()) {
640708 std::cout << " ," ;
641709 }
642710 std::cout << " \n " ;
0 commit comments