fix(runtime): Random.* in any program; value_* called directly brings the value tree
The seeded random numbers lived in the ECS runtime, so a tool or a program of test blocks got "unknown function rng_range". They are runtime/native/rng.ludic now, spliced on Random.* or a bare rng_*/seed call nobody defines, and imported by core.ludic for a game. A bare value_*/json_* call nothing in the program defines splices the value tree the way Value.* does. Reseed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
bf73f7edaf
commit
f5e7fe4245
13 changed files with 52262 additions and 51500 deletions
|
|
@ -27,7 +27,6 @@ var rt_fb: words = null # framebuffer, one i32 (0x00RRGGBB) per pixel
|
|||
var rt_fbw: int = 320
|
||||
var rt_fbh: int = 240
|
||||
var rt_regs: words = null # the 64 general-purpose game registers
|
||||
var rt_rng: int = 305419896 # xorshift32 state
|
||||
var rt_alive: int = 1 # platform still running?
|
||||
|
||||
# ---- renderer state (camera / clip / blend) -------------------------------
|
||||
|
|
@ -455,53 +454,6 @@ function rt_set_reg(i: int, v: int) -> void {
|
|||
rt_regs[i] = v
|
||||
}
|
||||
|
||||
# ---- rng (xorshift32) -----------------------------------------------------
|
||||
function rt_seed(s: int) -> void {
|
||||
if s == 0 {
|
||||
rt_rng = 305419896
|
||||
return
|
||||
}
|
||||
rt_rng = s
|
||||
}
|
||||
|
||||
# xorshift32 (Marsaglia). Runs on the raw 32-bit pattern, so the sign bit is
|
||||
# masked off only when a caller asks for a number.
|
||||
function rt_next_rand() -> int {
|
||||
var x = rt_rng
|
||||
x = (x ^ (x << 13))
|
||||
x = (x ^ (x >> 17))
|
||||
x = (x ^ (x << 5))
|
||||
rt_rng = x
|
||||
return (x & 2147483647)
|
||||
}
|
||||
|
||||
function rt_rng_range(lo: int, hi: int) -> int {
|
||||
if hi <= lo { return lo }
|
||||
return lo + rt_next_rand() % (hi - lo + 1)
|
||||
}
|
||||
|
||||
function rt_rng_chance(pct: int) -> bool {
|
||||
return rt_next_rand() % 100 < pct
|
||||
}
|
||||
|
||||
# a deterministic fixed-point value in [0, 1) — the raw 0..65535 is exactly the
|
||||
# Q16.16 fraction (fixed and int share the i32 representation).
|
||||
function rt_rng_value() -> fixed {
|
||||
return rt_rng_range(0, 65535)
|
||||
}
|
||||
|
||||
# a deterministic integer in [0, max) — 0 when max <= 0
|
||||
function rt_rng_int(max: int) -> int {
|
||||
if max <= 0 { return 0 }
|
||||
return rt_rng_range(0, max - 1)
|
||||
}
|
||||
|
||||
# a deterministic +1 or -1
|
||||
function rt_rng_sign() -> int {
|
||||
if rt_rng_chance(50) { return 1 }
|
||||
return -1
|
||||
}
|
||||
|
||||
# ---- platform: input ------------------------------------------------------
|
||||
function rt_poll() -> int {
|
||||
if is_windowed() {
|
||||
|
|
@ -590,6 +542,7 @@ function rt_dump_ppm(path: string) -> void {
|
|||
free(hdr)
|
||||
}
|
||||
|
||||
import "rng.ludic"
|
||||
import "inflate.ludic"
|
||||
import "image.ludic"
|
||||
import "truetype.ludic"
|
||||
|
|
@ -712,25 +665,6 @@ function rt_bar(x: int, y: int, w: int, h: int, value: int, max: int, color: int
|
|||
if filled > 0 { rt_fill_rect(x, y, filled, h, color) }
|
||||
}
|
||||
|
||||
# Random.weighted(weights): an index drawn in proportion to its weight (0 = never);
|
||||
# -1 when every weight is 0. Deterministic, from the seeded RNG.
|
||||
function rt_rng_weighted(weights: []int) -> int {
|
||||
var total = 0
|
||||
var i = 0
|
||||
while i < len(weights) { if weights[i] > 0 { total += weights[i] }; i += 1 }
|
||||
if total <= 0 { return -1 }
|
||||
var roll = rt_rng_range(0, total - 1)
|
||||
i = 0
|
||||
while i < len(weights) {
|
||||
if weights[i] > 0 {
|
||||
if roll < weights[i] { return i }
|
||||
roll -= weights[i]
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
# List.sample(pool, count): `count` picks from an int slice, distinct while the
|
||||
# pool has enough, repeating a valid pick when it does not; empty in -> zeros
|
||||
function rt_list_sample(pool: []int, count: int) -> []int {
|
||||
|
|
|
|||
70
runtime/native/rng.ludic
Normal file
70
runtime/native/rng.ludic
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# rng.ludic — the engine's seeded random numbers (Random.*, seed, rng_*): xorshift32, the same
|
||||
# stream on every machine. Its own file so a program with no ECS - a tool, a test program - gets
|
||||
# Random.* too: the compiler splices it on demand, and core.ludic imports it for a game.
|
||||
var rt_rng: int = 305419896 # xorshift32 state
|
||||
|
||||
# ---- rng (xorshift32) -----------------------------------------------------
|
||||
function rt_seed(s: int) -> void {
|
||||
if s == 0 {
|
||||
rt_rng = 305419896
|
||||
return
|
||||
}
|
||||
rt_rng = s
|
||||
}
|
||||
|
||||
# xorshift32 (Marsaglia). Runs on the raw 32-bit pattern, so the sign bit is
|
||||
# masked off only when a caller asks for a number.
|
||||
function rt_next_rand() -> int {
|
||||
var x = rt_rng
|
||||
x = (x ^ (x << 13))
|
||||
x = (x ^ (x >> 17))
|
||||
x = (x ^ (x << 5))
|
||||
rt_rng = x
|
||||
return (x & 2147483647)
|
||||
}
|
||||
|
||||
function rt_rng_range(lo: int, hi: int) -> int {
|
||||
if hi <= lo { return lo }
|
||||
return lo + rt_next_rand() % (hi - lo + 1)
|
||||
}
|
||||
|
||||
function rt_rng_chance(pct: int) -> bool {
|
||||
return rt_next_rand() % 100 < pct
|
||||
}
|
||||
|
||||
# a deterministic fixed-point value in [0, 1) — the raw 0..65535 is exactly the
|
||||
# Q16.16 fraction (fixed and int share the i32 representation).
|
||||
function rt_rng_value() -> fixed {
|
||||
return rt_rng_range(0, 65535)
|
||||
}
|
||||
|
||||
# a deterministic integer in [0, max) — 0 when max <= 0
|
||||
function rt_rng_int(max: int) -> int {
|
||||
if max <= 0 { return 0 }
|
||||
return rt_rng_range(0, max - 1)
|
||||
}
|
||||
|
||||
# a deterministic +1 or -1
|
||||
function rt_rng_sign() -> int {
|
||||
if rt_rng_chance(50) { return 1 }
|
||||
return -1
|
||||
}
|
||||
|
||||
# Random.weighted(weights): an index drawn in proportion to its weight (0 = never);
|
||||
# -1 when every weight is 0. Deterministic, from the seeded RNG.
|
||||
function rt_rng_weighted(weights: []int) -> int {
|
||||
var total = 0
|
||||
var i = 0
|
||||
while i < len(weights) { if weights[i] > 0 { total += weights[i] }; i += 1 }
|
||||
if total <= 0 { return -1 }
|
||||
var roll = rt_rng_range(0, total - 1)
|
||||
i = 0
|
||||
while i < len(weights) {
|
||||
if weights[i] > 0 {
|
||||
if roll < weights[i] { return i }
|
||||
roll -= weights[i]
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue