Skip to content

Commit 796c842

Browse files
Major fixes to precalc stuff. Thanks to Riv for putting up with me. Sorry to everyone for being overconfidant.
1 parent 4b3965b commit 796c842

2,381 files changed

Lines changed: 3286 additions & 2417 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ dropsim
66
dropsimbase
77
dropsim.exe
88
dropsim.pdb
9+
dropsolver
10+
dropsolverbase
11+
dropsolver.exe
12+
dropsolver.pdb
913
*.txt
1014
!atomic.txt
1115
!atomicbase.txt

build.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
#!/bin/bash
22
g++ dropsim.cpp -o dropsim -std=c++17 -O3 -pthread -march=native
33
g++ dropsim.cpp -o dropsimbase -D"BASETC=1" -std=c++17 -O3 -pthread -march=native
4+
g++ dropsolver.cpp -o dropsolver -std=c++17 -O3 -pthread -march=native
5+
g++ dropsolver.cpp -o dropsolverbase -D"BASETC=1" -std=c++17 -O3 -pthread -march=native

dropsim.cpp

Lines changed: 91 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
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

112117
long playermod = 1;
113118
int 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
116132
std::vector<std::string> splitByChar(const std::string& str, char delimiter) {
@@ -184,10 +200,6 @@ long calcNodrop(long e, long nd, long d) {
184200
}
185201

186202
void 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
387402
int 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

Comments
 (0)