diff options
author | Fedja Beader <fedja@protonmail.ch> | 2025-01-23 01:39:08 +0100 |
---|---|---|
committer | Fedja Beader <fedja@protonmail.ch> | 2025-01-24 01:14:30 +0100 |
commit | 1ba5b02cb9ffa83a0e8ff283f4d01d0044eb533e (patch) | |
tree | 24df2acf4790d8b1ece6e32886db653650149da3 | |
parent | d8782a82fc0cbc6b52d2f7385229cbe832562b95 (diff) | |
download | tmwa-1ba5b02cb9ffa83a0e8ff283f4d01d0044eb533e.tar.gz tmwa-1ba5b02cb9ffa83a0e8ff283f4d01d0044eb533e.tar.bz2 tmwa-1ba5b02cb9ffa83a0e8ff283f4d01d0044eb533e.tar.xz tmwa-1ba5b02cb9ffa83a0e8ff283f4d01d0044eb533e.zip |
Ensure that a continuous rise in drop rate boosts results in a continuous rise in actual drop rate.
-rw-r--r-- | src/generic/random.cpp | 4 | ||||
-rw-r--r-- | src/generic/random.hpp | 14 | ||||
-rw-r--r-- | src/generic/random.t.hpp | 5 | ||||
-rw-r--r-- | src/map/mob.cpp | 42 |
4 files changed, 53 insertions, 12 deletions
diff --git a/src/generic/random.cpp b/src/generic/random.cpp index e37a3d1..d29c984 100644 --- a/src/generic/random.cpp +++ b/src/generic/random.cpp @@ -25,6 +25,8 @@ namespace tmwa { namespace random_ { - std::mt19937 generate{std::random_device()()}; + std::random_device seed_class; + std::mt19937 generate{seed_class()};//std::random_device()()}; + std::mt19937_64 generate64{ ((uint64_t)seed_class() << 32) + seed_class()}; } // namespace random_ } // namespace tmwa diff --git a/src/generic/random.hpp b/src/generic/random.hpp index 897ad43..7310e21 100644 --- a/src/generic/random.hpp +++ b/src/generic/random.hpp @@ -33,8 +33,10 @@ namespace random_ { /// Get a random number from 0 .. 2**32 - 1 extern std::mt19937 generate; + extern std::mt19937_64 generate64; /// Get a random number from 0 .. bound - 1 + // TODO: Deduplicate this. inline int to(int bound) { @@ -42,6 +44,13 @@ namespace random_ return dist(generate); } + inline + int64_t to(int64_t bound) + { + std::uniform_int_distribution<int64_t> dist(0, bound - 1); + return dist(generate64); + } + /// Get a random number from low .. high (inclusive!) inline int in(int low, int high) @@ -58,8 +67,9 @@ namespace random_ return dist(generate); } + template<typename T = int> inline - bool chance(Fraction f) + bool chance(Fraction<T> f) { if (f.num <= 0) return false; @@ -75,7 +85,7 @@ namespace random_ template<class C> auto choice(C&& c) -> decltype(*c.begin()) { - return *(c.begin() + random_::to(c.size())); + return *(c.begin() + random_::to((int64_t)c.size())); } // allow bare braces diff --git a/src/generic/random.t.hpp b/src/generic/random.t.hpp index b4c4764..985ba3b 100644 --- a/src/generic/random.t.hpp +++ b/src/generic/random.t.hpp @@ -25,9 +25,10 @@ namespace tmwa { namespace random_ { + template<class T = int> struct Fraction { - int num, den; + T num, den; }; template<class T, T den> @@ -35,7 +36,7 @@ namespace random_ { T num; - operator Fraction() + operator Fraction<T>() { return {num, den}; } diff --git a/src/map/mob.cpp b/src/map/mob.cpp index fc41d19..6224b82 100644 --- a/src/map/mob.cpp +++ b/src/map/mob.cpp @@ -67,10 +67,11 @@ namespace map { constexpr interval_t MIN_MOBTHINKTIME = 100_ms; +// TODO: template type deduction is a C++17+ feature. // Move probability in the negligent mode MOB (rate of 1000 minute) -constexpr random_::Fraction MOB_LAZYMOVEPERC {50, 1000}; +constexpr random_::Fraction<int> MOB_LAZYMOVEPERC {50, 1000}; // Warp probability in the negligent mode MOB (rate of 1000 minute) -constexpr random_::Fraction MOB_LAZYWARPPERC {20, 1000}; +constexpr random_::Fraction<int> MOB_LAZYWARPPERC {20, 1000}; struct mob_db_& get_mob_db(Species s) { @@ -2735,16 +2736,43 @@ int mob_damage(dumb_ptr<block_list> src, dumb_ptr<mob_data> md, int damage, const auto& drop_info = mob_info.dropitem[i]; if (!drop_info.nameid) continue; - random_::Fixed<int, 10000> drop_rate = drop_info.p; + + // WARNING: possible overflows. + // maximum denominator: 10000*100*4*100 = 20% of INT_MAX + // maximum numerator is hard to predict as it depends on + // config/GM settings. In future, rares beyond 1:10000 + // might be supported and so let's just use 64 bit fractions. + random_::Fraction<int64_t> f; + f.num = drop_info.p.num; + f.den = 10000; + if (sd && battle_config.drops_by_luk > 0) - drop_rate.num += (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk) / 100; // drops affected by luk [Valaris] + { + // You are reading this correctly, this is an additive boost. + // MLHerc has a multiplicative one as well. + //drop_rate.num += (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk) / 100; // drops affected by luk [Valaris] + // n += (L*DL) / 100 => n := n + (L*DL)/100 = 100*n/100 + (L*DL)/100 + // = (100*n + (L*DL)) / 100 + // drops affected by luk [Valaris] + f.num = 100*f.num + (sd->status.attrs[ATTR::LUK] * battle_config.drops_by_luk); + f.den *= 100; + } + + int64_t den_scale = 100; // avoids a division. if (sd && battle_config.pk_mode == 1 && (mob_info.lv - sd->status.base_level >= 20)) - drop_rate.num *= 1.25; // pk_mode increase drops if 20 level difference [Valaris] + { + //drop_rate.num *= 1.25; // pk_mode increase drops if 20 level difference [Valaris] + // p = (1.25 * n)/d = 5/4 * n/d = n/(4/5*d) + den_scale = 100/5;// Denominator is always divisible by 5 + f.den *= 4; + } // server-wide drop rate scaling - drop_rate.num = (drop_rate.num * battle_config.drop_rate) / 100; - if (!random_::chance(drop_rate)) + f.num *= battle_config.drop_rate; + f.den *= den_scale; + + if (!random_::chance(f)) continue; struct delay_item_drop ditem {}; |