Hik 108 Posted April 25, 2020 Share Posted April 25, 2020 Hi guys, I need your help! I compile metin2 using visualstudio (server side) and I have a problem with the drop. As you can see, the drop is set to 1% but despite this I continue to drop, at each mob 101 eliminated, at least 2 of the items in the list. On freebsd it didn't happen. Some advice? Group test_dog { type drop mob 101 1 1012 1 1 2 4012 1 1 3 11402 1 1 4 16022 1 1 } Link to comment Share on other sites More sharing options...
Premium WeedHex 635 Posted April 25, 2020 Premium Share Posted April 25, 2020 Group test_dog { type drop mob 101 1 1012 1 0.50 2 4012 1 0.10 3 11402 1 0.05 4 16022 1 0.01 } Link to comment Share on other sites More sharing options...
Hik 108 Posted April 25, 2020 Author Share Posted April 25, 2020 I would like to understand, more than anything else, why there is this difference between visualstudio and freebsd, in order to make a precise proportion. Link to comment Share on other sites More sharing options...
Hik 108 Posted April 27, 2020 Author Share Posted April 27, 2020 UP Link to comment Share on other sites More sharing options...
Hik 108 Posted May 3, 2020 Author Share Posted May 3, 2020 UP2: if (iPercent >= number(1, iRandRange)) iPercent = 100000 | in mob_drop_item the percentage is set to 10 number = 1, 4000000 | random number between 1 and 4000000 I noticed, however, how the random values obtained are very different between the two versions: random = 3894439 random = 229634 random = 1664283 random = 3958197 | BSD VERSION random = 924476 random = 2193081 random = 181074 ----------------------------------------------------------------------------- random = 12851 random = 10165 | WINDOWS VERSION random = 23397 random = 12871 I don't enter all the other values because they follow the same trend. In the first case, having a high random value I will not drop, while having a low one in the second case I will always drop. Any ideas on this? Link to comment Share on other sites More sharing options...
Hik 108 Posted May 8, 2020 Author Share Posted May 8, 2020 up Link to comment Share on other sites More sharing options...
Hik 108 Posted May 14, 2020 Author Share Posted May 14, 2020 up Link to comment Share on other sites More sharing options...
EnneGi 3 Posted March 11, 2022 Share Posted March 11, 2022 On 5/3/2020 at 12:08 PM, Hik said: UP2: if (iPercent >= number(1, iRandRange)) iPercent = 100000 | in mob_drop_item the percentage is set to 10 number = 1, 4000000 | random number between 1 and 4000000 I noticed, however, how the random values obtained are very different between the two versions: random = 3894439 random = 229634 random = 1664283 random = 3958197 | BSD VERSION random = 924476 random = 2193081 random = 181074 ----------------------------------------------------------------------------- random = 12851 random = 10165 | WINDOWS VERSION random = 23397 random = 12871 I don't enter all the other values because they follow the same trend. In the first case, having a high random value I will not drop, while having a low one in the second case I will always drop. Any ideas on this? Hi Hik, your searching was useful to me, as you said every windows server file is affected by this bug. I found the root cause. File: utils.c in libthecore DWORD thecore_random() { #ifdef __WIN32__ return rand(); #else return random(); #endif for Windows, it will use rand(). It has limitations for Windows, the maximum range is 32767. That's why the number extraction in Windows is so low. You have to find another way to random with bigger numbers, or as a workaround you can multiply the rand() value to have a maximum of iRandRange. You can find the multiplier value by dividing iRandRange / 32767. It's working, but it's a really bad workaround if you tell me, because we are not get a random result from 1 to iRandRange. If you want to try this workaround, find item_manager.cpp and change: number(1,iRandRange) To (rand() % 32767) * iMultiplier) Before while (it != g_vec_pkCommonDropItem[bRank].end()) in CreateDropItem add this: int iMultiplier = iRandRange / 32767 Before while sys_log(1, "CreateQuestDropItem victim(%s), killer(%s)", pkChr->GetName(), pkKiller->GetName() ); in CreateDropItem add this: int iMultiplier = iRandRange / 32767 My advise is to work in a good implementation of random for Windows. Cheers 1 Link to comment Share on other sites More sharing options...
Hik 108 Posted March 14, 2022 Author Share Posted March 14, 2022 In the end i used this: int random_drop(int min, int max) { std::random_device device; std::mt19937 generator(device()); std::uniform_int_distribution<int> distribution(min, max); return distribution(generator); } 1 Link to comment Share on other sites More sharing options...
Developer Ikarus_ 2426 Posted March 15, 2022 Developer Share Posted March 15, 2022 (edited) On 3/14/2022 at 10:38 PM, Hik said: In the end i used this: int random_drop(int min, int max) { std::random_device device; std::mt19937 generator(device()); std::uniform_int_distribution<int> distribution(min, max); return distribution(generator); } It works yeah, but it is really slow. I would suggest you something much faster. int number(int v1, int v2) { thread_local std::default_random_engine _Generator; thread_local bool _Init = false; if (!_Init) { _Init = true; std::random_device dev; _Generator.seed(dev()); } std::uniform_int_distribution<int> distribution(v1, v2); return distribution(_Generator); } It can totally replace the old "number" function from libthrecore (you have to remove the macro defined inside libthrecore/inlude/utils.h) Here's a small test showing how my function is faster: https://onlinegdb.com/27jNGeGOlx Execution time in seconds (1.000.000 function calls): number time : 0.0718687 random_drop time : 17.9117 Edited March 16, 2022 by Ikarus_ 2 1 1 My youtube channel on which you can see my works here Link to comment Share on other sites More sharing options...
Hik 108 Posted March 16, 2022 Author Share Posted March 16, 2022 Thank you very much, I will more than gladly replace the code! 2 Link to comment Share on other sites More sharing options...
Active Member ATAG 310 Posted April 22, 2023 Active Member Share Posted April 22, 2023 You have to create (and seed) the generator outside your function, don't want a new random engine every time. That way both of your codes do (near) the same in the same amount of time. number time : 0.0781763 random_drop time : 0.0759912 https://onlinegdb.com/6P2Rb7K9S Btw thanks for the idea, i've choosen a more simple way. libthecore/utilc.c: DWORD thecore_random() { #ifdef _WIN32 // return rand(); //extend the 32767 limit to 2147483645... return rand() * rand() + rand(); #else return random(); #endif } Not faster and not better, but it works Link to comment Share on other sites More sharing options...
Developer Ikarus_ 2426 Posted April 22, 2023 Developer Share Posted April 22, 2023 (edited) 12 minutes ago, ATAG said: You have to create (and seed) the generator outside your function, don't want a new random engine every time. That way both of your codes do (near) the same in the same amount of time. number time : 0.0781763 random_drop time : 0.0759912 https://onlinegdb.com/6P2Rb7K9S Btw thanks for the idea, i've choosen a more simple way. libthecore/utilc.c: DWORD thecore_random() { #ifdef _WIN32 // return rand(); //extend the 32767 limit to 2147483645... return rand() * rand() + rand(); #else return random(); #endif } Not faster and not better, but it works That way u do isn't a uniform distribution. If u want see it with ur eyes try to store 1milion numbers returned by ur functions and print them sorting by count of times they were picked. Larger numbers are more frequently picked than smaller ones. Edited April 22, 2023 by Ikarus_ My youtube channel on which you can see my works here Link to comment Share on other sites More sharing options...
Active Member ATAG 310 Posted April 22, 2023 Active Member Share Posted April 22, 2023 In our case this is not a problem, higher number means less drop 1 1 Link to comment Share on other sites More sharing options...
Premium Syreldar 1875 Posted April 22, 2023 Premium Share Posted April 22, 2023 (edited) 3 hours ago, ATAG said: In our case this is not a problem, higher number means less drop Yeah, let's make 2 kilos of salad with 5% lettuce, 10% tomatoes, 40% pine nuts, 30% olive oil, 15% balsamic vinegar, in the end it's a lot of food, so I'm sure it'll be good!.. right? Edited April 22, 2023 by Syreldar 2 "Nothing's free in this life. Ignorant people have an obligation to make up for their ignorance by paying those who help them. Either you got the brains or cash, if you lack both you're useless." Syreldar Link to comment Share on other sites More sharing options...
Active Member ATAG 310 Posted April 23, 2023 Active Member Share Posted April 23, 2023 Final version, This way the drops are near the same (and fast enough) DWORD thecore_random() { #ifdef _WIN32 double iRand = (double)rand() / RAND_MAX; // 0x7fff return (iRand * (0x7fffffff - 1) + 1); #else return random(); // 0x7fffffff #endif } Link to comment Share on other sites More sharing options...
Developer Ikarus_ 2426 Posted April 23, 2023 Developer Share Posted April 23, 2023 (edited) 6 hours ago, ATAG said: Final version, This way the drops are near the same (and fast enough) DWORD thecore_random() { #ifdef _WIN32 double iRand = (double)rand() / RAND_MAX; // 0x7fff return (iRand * (0x7fffffff - 1) + 1); #else return random(); // 0x7fffffff #endif } Again no xd. It is still not uniform at all. Using the same test (1 milion numbers) you will see that only 65k of numbers are possible to be picked... And 0 will never be picked xd The possible numbers are the ones that comes out using this formula : n = 1 + x * 32K where x can be one random number from 0 to RAND_MAX (65k~) in short, theres a number every 32k of numbers which can be picked, in the range from 1 to 2147483647, which is very far from being a uniform distribution in a range. I guess u know that it cant be tested on onlinegdb since this issue comes out only on Windows (onlinegdb uses linux) Edited April 23, 2023 by Ikarus_ 1 My youtube channel on which you can see my works here Link to comment Share on other sites More sharing options...
Active Member ATAG 310 Posted April 23, 2023 Active Member Share Posted April 23, 2023 (edited) You are wrong. Put this into vs->console app, and run it: #include <iostream> #include <random> #include <limits> int thecore_random() { double iRand = (double)rand() / RAND_MAX; // 0x7fff return (int)(iRand * 0x7fffffff); } int main() { std::cout << "RAND_MAX: " << RAND_MAX << "\n"; std::cout << "INT_MAX: " << INT_MAX << "\n"; for (int i=0; i<100; i++) std::cout << "random: " << thecore_random() << "\n"; } The range was 1-RAND_MAX, changed it to 0... Thank you Edited April 24, 2023 by Metin2 Dev International Core X - External 2 Internal Link to comment Share on other sites More sharing options...
Developer Ikarus_ 2426 Posted April 23, 2023 Developer Share Posted April 23, 2023 (edited) 19 minutes ago, ATAG said: You are wrong. Put this into vs->console app, and run it: #include <iostream> #include <random> #include <limits> int thecore_random() { double iRand = (double)rand() / RAND_MAX; // 0x7fff return (int)(iRand * 0x7fffffff); } int main() { std::cout << "RAND_MAX: " << RAND_MAX << "\n"; std::cout << "INT_MAX: " << INT_MAX << "\n"; for (int i=0; i<100; i++) std::cout << "random: " << thecore_random() << "\n"; } The range was 1-RAND_MAX, changed it to 0... Thank you Store the values into a set, change the for limit to 1milion and call .size on the set at the end. Surprise! The size is around 32k, so it is repeating 1milion of times the same 32k of values. So in short the problem i tried to explain in the previous answer consists in the fact the values are discrete. Are only 32k (RAND_MAX) of values, distributed in the range 0-2kkk I said 65k of values in the previous post because I thought RAND_MAX was 65k, since it is 32k the numbers are more discrete than how i thought xd Edited April 24, 2023 by Metin2 Dev International Core X - External 2 Internal My youtube channel on which you can see my works here Link to comment Share on other sites More sharing options...
Denizeri24 35 Posted April 23, 2023 Share Posted April 23, 2023 Just use the MT engine. We're not encrypting NSA files or running a bank with billions of users. So we don't need quantum-level security or performance. 1 Link to comment Share on other sites More sharing options...
Active Member ATAG 310 Posted April 24, 2023 Active Member Share Posted April 24, 2023 Everything works well here what can generate numbers in 0~4M (?) range Finally I ended up at default_random_engine (which is the mt) for the number_ex... Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now