Skip to content

Commit

Permalink
Simplify LuaPseudoRandom::l_next and fix docs
Browse files Browse the repository at this point in the history
Also extends the allowed range on the C++ side. This has no side-effects.
  • Loading branch information
sfan5 committed Jan 14, 2024
1 parent d20f118 commit e824e90
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 20 deletions.
11 changes: 7 additions & 4 deletions doc/lua_api.md
Expand Up @@ -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

Expand Down Expand Up @@ -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`
---------
Expand Down
2 changes: 2 additions & 0 deletions games/devtest/mods/unittests/misc.lua
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion src/noise.h
Expand Up @@ -70,7 +70,7 @@ class PseudoRandom {
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;
Expand Down
25 changes: 11 additions & 14 deletions src/script/lua_api/l_noise.cpp
Expand Up @@ -405,25 +405,22 @@ int LuaPseudoRandom::l_next(lua_State *L)
NO_MAP_LOCK_REQUIRED;

LuaPseudoRandom *o = checkObject<LuaPseudoRandom>(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="<<max<<" min="<<min<<std::endl;
throw LuaError("PseudoRandom.next(): max < min");

int val;
if (max - min == PseudoRandom::RANDOM_RANGE) {
val = o->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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/unittest/test_random.cpp
Expand Up @@ -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++) {
Expand Down

0 comments on commit e824e90

Please sign in to comment.