From 882a2046cff3af397f46df272afcdf16655dae9f Mon Sep 17 00:00:00 2001 From: Kaj Schittecat Date: Mon, 26 Oct 2026 12:29:31 +0100 Subject: [PATCH] lua: wada.sys.random(n) gives 1..n, random(lo, lo) gives lo A single argument landed in lo with hi = 0, and any empty range returned a raw 32-bit value, so the documented random(n) never gave 1..n and a shuffle's last random(1, i) with i = 1 gave a huge index (the Space Invaders crash, #729, worked around in the app). random() alone still returns the raw value, and a reversed range is swapped. Co-Authored-By: Claude Opus 5.5 --- deploy/site/sdk.html | 2 +- src/ui-touch/LuaAppHost.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/deploy/site/sdk.html b/deploy/site/sdk.html index 904569c6..8d468f0e 100644 --- a/deploy/site/sdk.html +++ b/deploy/site/sdk.html @@ -526,7 +526,7 @@ end wada.sys.millis()Milliseconds since boot. wada.sys.board(){w, h, touch, keyboard, trackball, gps}: size and capabilities. wada.sys.toast(msg)Brief on-screen message. - wada.sys.random(n)Integer in 1..n. + wada.sys.random(n)
wada.sys.random(lo, hi)Integer in 1..n, or in lo..hi (both ends included). From hardware randomness, so there is nothing to seed. wada.sys.epoch()Unix time in seconds, or nil when the clock has not been set yet (no GPS fix and no NTP). Always handle the nil. wada.sys.datetime(){year, month, day, hour, min, sec, wday} in local time. wday is 0 for Sunday. wada.ui.emoji(cb)Open the emoji picker and call cb(glyph) with the chosen emoji as a UTF-8 string, or cb(nil) if it was dismissed. For an app that draws its own text entry and keeps the buffer itself; if you use wada.ui.input() you do not need this, the picker is already on its long-press menu. diff --git a/src/ui-touch/LuaAppHost.cpp b/src/ui-touch/LuaAppHost.cpp index fb078d93..dcdd68e7 100644 --- a/src/ui-touch/LuaAppHost.cpp +++ b/src/ui-touch/LuaAppHost.cpp @@ -1273,8 +1273,13 @@ int sysKeepAwake(lua_State* L) { int sysToast(lua_State* L) { luaHostToast(luaL_checkstring(L, 1), (int)luaL_optinteger(L, 2, 1500)); return 0; } int sysRandom(lua_State* L) { // esp_random-backed: apps should not have to seed math.random for games - lua_Integer lo = luaL_optinteger(L, 1, 0), hi = luaL_optinteger(L, 2, 0); - if (hi <= lo) { lua_pushinteger(L, (lua_Integer)esp_random()); return 1; } + // random() = a raw 32-bit value, random(n) = 1..n (as documented), random(lo, hi) = + // lo..hi. An empty range used to return the raw value too, so random(1, 1) at the end + // of a shuffle gave a huge index, and random(n) never returned 1..n at all. + if (lua_isnoneornil(L, 1)) { lua_pushinteger(L, (lua_Integer)esp_random()); return 1; } + lua_Integer lo = luaL_checkinteger(L, 1), hi; + if (lua_isnoneornil(L, 2)) { hi = lo; lo = 1; } else hi = luaL_checkinteger(L, 2); + if (hi < lo) { const lua_Integer t = lo; lo = hi; hi = t; } lua_pushinteger(L, lo + (lua_Integer)(esp_random() % (uint32_t)(hi - lo + 1))); return 1; }