@@ -147,7 +147,7 @@ void pickAtomic(std::string tcname, int magic, int rare, int set, int unique, st
147147 int picknum = dis (gen);
148148
149149 for (auto item : atc.items ) {
150- if (picknum < item.prob ) {
150+ if (item. prob > 0 && picknum < item.prob ) {
151151 drops.push_back ({item.name , magic, rare, set, unique});
152152 #ifdef DEBUG
153153 std::cout << " Added " << item.name << std::endl;
@@ -237,7 +237,7 @@ void pick(std::string tcname, int magic, int rare, int set, int unique, std::vec
237237 }
238238
239239 for (auto item : tc.items ) {
240- if (item.prob ) {
240+ if (item.prob > 0 ) {
241241 if (picknum < item.prob ) {
242242 #ifdef DEBUG
243243 std::cout << item.name << " picked" << std::endl;
@@ -274,10 +274,86 @@ void pick(std::string tcname, int magic, int rare, int set, int unique, std::vec
274274 }
275275}
276276
277+ void populateAtomic (std::string tcname, int magic, int rare, int set, int unique, std::unordered_map<Drop, long >& drops) {
278+ if (atomic.find (tcname) == atomic.end ()) {
279+ drops[{tcname, magic, rare, set, unique}] = 0 ;
280+ return ;
281+ }
282+
283+ AtomicTC& atc = atomic[tcname];
284+
285+ if (atc.total == 0 ) {
286+ return ;
287+ }
288+
289+ for (auto item : atc.items ) {
290+ if (item.prob > 0 ) {
291+ drops[{item.name , magic, rare, set, unique}] = 0 ;
292+ }
293+ }
294+ }
295+
296+ void populate (std::string tcname, int magic, int rare, int set, int unique, std::unordered_map<Drop, long >& drops) {
297+ if (treasureClasses.find (tcname) == treasureClasses.end ()) {
298+ populateAtomic (tcname, magic, rare, set, unique, drops);
299+ return ;
300+ }
301+
302+ TC& tc = treasureClasses[tcname];
303+
304+ magic = std::max (magic, tc.magic );
305+ rare = std::max (rare, tc.rare );
306+ set = std::max (set, tc.set );
307+ unique = std::max (unique, tc.unique );
308+
309+ if (tc.picks == 0 ) {
310+ return ;
311+ }
312+
313+ if (tc.total == 0 ) {
314+ return ;
315+ }
316+
317+ if (tc.picks > 0 ) {
318+ for (auto item : tc.items ) {
319+ if (item.prob > 0 ) {
320+ populate (item.name , magic, rare, set, unique, drops);
321+ }
322+ }
323+ }
324+ else {
325+ int picks = -tc.picks ;
326+
327+ for (auto item : tc.items ) {
328+ for (int i = 0 ; i < item.prob ; i++) {
329+ if (picks <= 0 ) {
330+ return ;
331+ }
332+
333+ populate (item.name , magic, rare, set, unique, drops);
334+ picks--;
335+ }
336+ }
337+ }
338+ }
339+
277340std::string realpath (std::string path) {
278341 return std::filesystem::canonical (std::filesystem::absolute (path)).string ();
279342}
280343
344+ /* *
345+ * Trim leading and trailing whitespace from a string.
346+ * This is a simple implementation and may not cover all Unicode whitespace characters.
347+ */
348+ std::string trim (const std::string& str) {
349+ size_t first = str.find_first_not_of (" \t\n\r\f\v " );
350+ if (first == std::string::npos) {
351+ return " " ; // String is all whitespace
352+ }
353+ size_t last = str.find_last_not_of (" \t\n\r\f\v " );
354+ return str.substr (first, (last - first + 1 ));
355+ }
356+
281357// Main takes first parameter as treasure class name
282358int main (int argc, char * argv[]) {
283359 if (argc < 2 ) {
@@ -298,7 +374,7 @@ int main(int argc, char* argv[]) {
298374 std::string simulationsPath = realpath (path + " simulations" ) + DIRECTORY_SEPARATOR_STRING;
299375
300376 std::string tcname = argv[1 ];
301- int dropcycles = 100000 ;
377+ int dropcycles = 300000 ;
302378
303379 if (argc >= 3 ) {
304380 playermod = atoi (argv[2 ]);
@@ -312,7 +388,7 @@ int main(int argc, char* argv[]) {
312388 }
313389
314390 dropcycles = std::max (1 , dropcycles);
315- dropcycles = std::min (1000000 , dropcycles);
391+ dropcycles = std::min (20000000 , dropcycles);
316392
317393 std::cout << tcname << " [" << playermod << " ]" << std::endl;
318394
@@ -338,7 +414,7 @@ int main(int argc, char* argv[]) {
338414 if (tokens.empty ()) continue ;
339415
340416 TC tc;
341- tc.name = tokens[0 ];
417+ tc.name = trim ( tokens[0 ]) ;
342418
343419 if (tokens.size () > 1 ) {
344420 tc.group = atoi (tokens[1 ].c_str ());
@@ -409,7 +485,7 @@ int main(int argc, char* argv[]) {
409485 if (tokens.empty ()) continue ;
410486
411487 AtomicTC atc;
412- std::string tcBaseName = tokens[0 ];
488+ std::string tcBaseName = trim ( tokens[0 ]) ;
413489 atomic[tcBaseName] = atc;
414490
415491 for (long i = 1 ; i < tokens.size () - 1 ; i += 2 ) {
@@ -433,7 +509,7 @@ int main(int argc, char* argv[]) {
433509 #else
434510 // Get CPU count.
435511 int thread_count = std::thread::hardware_concurrency (); // Use 2/3 of available threads to avoid overloading the system
436- thread_count = std::max (1 , thread_count - 4 );
512+ thread_count = std::max (1 , thread_count - 6 );
437513 #endif
438514
439515 if (thread_count < 1 ) {
@@ -446,21 +522,30 @@ int main(int argc, char* argv[]) {
446522 }
447523 }
448524
449- long mindropcount = thread_count ;
525+ long mindropcount = 676 ;
450526
451527 if (argc >= 5 ) {
452528 mindropcount = atoi (argv[4 ]);
453529 }
454530
455531 mindropcount = std::max (1L , mindropcount);
456532
533+ mindropcount /= thread_count;
534+
457535 std::vector<std::thread> threads;
458536
537+ std::unordered_map<Drop, long > dropsToFind;
538+ populate (tcname, 0 , 0 , 0 , 0 , dropsToFind);
539+
459540 for (int i = 0 ; i < thread_count; i++) {
460- threads.emplace_back ([i, thread_count, &tcname, dropcycles, mindropcount, &simulationsPath]() {
541+ threads.emplace_back ([i, thread_count, &tcname, &dropsToFind, dropcycles, mindropcount, &simulationsPath]() {
461542 long totalruns = 0 ;
462543 long totalpicks = 0 ;
463544 std::unordered_map<Drop, long > totaldrops;
545+
546+ for (const auto & drop : dropsToFind) {
547+ totaldrops[drop.first ] = 0 ;
548+ }
464549
465550 for (size_t seq = 0 ; true ; seq++) {
466551 long runs = 0 ;
@@ -524,21 +609,20 @@ int main(int argc, char* argv[]) {
524609 out << " ]\n " ;
525610 out << " }\n " ;
526611
527- if (seq * dropcycles >= 400000 ) {
528- // Check if all items have at least mindropcount drops, and if so, break the loop to finish this thread's execution.
529- bool allAboveMin = true ;
530- for (const auto & drop : totaldrops) {
531- if (drop.second < mindropcount) {
532- allAboveMin = false ;
533- printf (" Thread %d: Item \' %s\' has %ld drops left...\n " , i, drop.first .name .c_str (), mindropcount - drop.second );
534- break ;
535- }
536- }
537-
538- if (allAboveMin) {
612+ // Check if all items have at least mindropcount drops, and if so, break the loop to finish this thread's execution.
613+ bool allAboveMin = true ;
614+ for (const auto & drop : totaldrops) {
615+ long dropsLeft = mindropcount - drop.second ;
616+
617+ if (dropsLeft > 0 ) {
618+ allAboveMin = false ;
539619 break ;
540620 }
541621 }
622+
623+ if (allAboveMin) {
624+ break ;
625+ }
542626 }
543627 });
544628 }
0 commit comments