From e824e9023f078da0051c54c29aaacf23eb6a6e95 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Wed, 10 Jan 2024 20:08:00 +0100 Subject: [PATCH] Simplify LuaPseudoRandom::l_next and fix docs Also extends the allowed range on the C++ side. This has no side-effects. --- doc/lua_api.md | 11 +++++++---- games/devtest/mods/unittests/misc.lua | 2 ++ src/noise.h | 2 +- src/script/lua_api/l_noise.cpp | 25 +++++++++++-------------- src/unittest/test_random.cpp | 2 +- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index c4e1265c5..8afe2b78d 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -8061,7 +8061,9 @@ A 32-bit pseudorandom number generator. Uses PCG32, an algorithm of the permuted congruential generator family, offering very strong randomness. -It can be created via `PcgRandom(seed)` or `PcgRandom(seed, sequence)`. +* constructor `PcgRandom(seed, [seq])` + * `seed`: 64-bit unsigned seed + * `seq`: 64-bit unsigned sequence, optional ### Methods @@ -8156,14 +8158,15 @@ Can be obtained using `player:get_meta()`. A 16-bit pseudorandom number generator. Uses a well-known LCG algorithm introduced by K&R. -It can be created via `PseudoRandom(seed)`. +* constructor `PseudoRandom(seed)` + * `seed`: 32-bit signed number ### Methods * `next()`: return next integer random number [`0`...`32767`] * `next(min, max)`: return next integer random number [`min`...`max`] - * `((max - min) == 32767) or ((max-min) <= 6553))` must be true - due to the simple implementation making bad distribution otherwise. + * Either `max - min == 32767` or `max - min <= 6553` must be true + due to the simple implementation making a bad distribution otherwise. `Raycast` --------- diff --git a/games/devtest/mods/unittests/misc.lua b/games/devtest/mods/unittests/misc.lua index fd6c0a058..e96103319 100644 --- a/games/devtest/mods/unittests/misc.lua +++ b/games/devtest/mods/unittests/misc.lua @@ -6,6 +6,8 @@ local function test_random() local pr2 = PseudoRandom(-101) assert(pr2:next(0, 100) == 35) + -- unusual case that is normally disallowed: + assert(pr2:next(10000, 42767) == 12485) end unittests.register("test_random", test_random) diff --git a/src/noise.h b/src/noise.h index 6c17afd68..d9b7a6521 100644 --- a/src/noise.h +++ b/src/noise.h @@ -70,7 +70,7 @@ public: PcgRandom, we cannot modify this RNG's range as it would change the output of this RNG for reverse compatibility. */ - if ((u32)(max - min) > (RANDOM_RANGE + 1) / 10) + if ((u32)(max - min) > (RANDOM_RANGE + 1) / 5) throw PrngException("Range too large"); return (next() % (max - min + 1)) + min; diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp index 16eb1de43..03f78c960 100644 --- a/src/script/lua_api/l_noise.cpp +++ b/src/script/lua_api/l_noise.cpp @@ -405,25 +405,22 @@ int LuaPseudoRandom::l_next(lua_State *L) NO_MAP_LOCK_REQUIRED; LuaPseudoRandom *o = checkObject(L, 1); - int min = 0; - int max = 32767; - lua_settop(L, 3); + int min = 0, max = PseudoRandom::RANDOM_RANGE; if (lua_isnumber(L, 2)) min = luaL_checkinteger(L, 2); if (lua_isnumber(L, 3)) max = luaL_checkinteger(L, 3); - if (max < min) { - errorstream<<"PseudoRandom.next(): max="<m_pseudo.next() + min; + } else { + try { + val = o->m_pseudo.range(min, max); + } catch (PrngException &e) { + throw LuaError(e.what()); + } } - if(max - min != 32767 && max - min > 32767/5) - throw LuaError("PseudoRandom.next() max-min is not 32767" - " and is > 32768/5. This is disallowed due to" - " the bad random distribution the" - " implementation would otherwise make."); - PseudoRandom &pseudo = o->m_pseudo; - int val = pseudo.next(); - val = (val % (max-min+1)) + min; lua_pushinteger(L, val); return 1; } diff --git a/src/unittest/test_random.cpp b/src/unittest/test_random.cpp index 9dd88d07e..5b9bbddcf 100644 --- a/src/unittest/test_random.cpp +++ b/src/unittest/test_random.cpp @@ -81,7 +81,7 @@ void TestRandom::testPseudoRandomRange() { PseudoRandom pr((int)time(NULL)); - EXCEPTION_CHECK(PrngException, pr.range(2000, 6000)); + EXCEPTION_CHECK(PrngException, pr.range(2000, 8600)); EXCEPTION_CHECK(PrngException, pr.range(5, 1)); for (u32 i = 0; i != 32768; i++) {