Skip to content

Class "RNG"⚓︎

Info

RNG 类提供了一种生成带种子的随机数的机制。该类被游戏本体和模组广泛使用。

你可以通过构造函数或以下函数获取该类的实例:

示例代码
1
local myRNG = RNG()

构造函数⚓︎

RNG ()⚓︎

RNG RNG ( )⚓︎

新建的 RNG 对象总是以种子 2853650767 初始化。因此,在调用构造函数后,你必须将新 RNG 对象的种子设置为你想要的初始种子。在某些情况下,这个种子可以是 1 到 4294967295 之间的任意新随机数。此时可用 Random 全局函数获取初始种子(但要确保不能为 0,否则会导致游戏崩溃)。然而,在大多数情况下,使用完全随机的种子会导致你的模组出现 bug,因为以撒的所有行为都应当基于开局种子、关卡种子或房间种子等确定性种子。

设置种子时,推荐使用 shift index 35,这是大多数游戏内部函数采用的值。建议将该数字以 SHOUTING_SNAKE_CASE 常量形式记录,避免在程序中出现魔数

示例代码
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- 这是 Blade 在审查游戏内部函数后推荐的 ShiftIdx。
-- 0 到 80(含)之间的任意值都可以正常工作。
-- https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
local RECOMMENDED_SHIFT_IDX = 35

local game = Game()
local seeds = game:GetSeeds()
local startSeed = seeds:GetStartSeed()
local rng = RNG()
rng:SetSeed(startSeed, RECOMMENDED_SHIFT_IDX)
local myRandomNumber = rng:RandomInt(4) -- 结果为 0、1、2 或 3。

Functions⚓︎

Get·Seed ()⚓︎

int GetSeed ( )⚓︎

返回当前 RNG 对象的种子。

获取Shift index引示例代码

以撒的API没有提供获取Shift Index的方法。Repentogon可以,但如果你没有访问权限,那么你可以使用以下函数来查找游戏的默认的shift index值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
local function getShiftIdx(rng)
  local seed = rng:GetSeed()
  local nexts = {}
  -- 18 seems to be the magic number here so you don't get false positives
  -- at 17, rng with seed=1,shiftIdx=53 returns a false positive of 52
  for i = 1, 18 do
    table.insert(nexts, rng:Next())
  end
  for i = 0, 80 do
    local rng2 = RNG()
    rng2:SetSeed(seed, i)
    for j, v in ipairs(nexts) do
      if v ~= rng2:Next() then
        break
      end
      if j == #nexts then
        -- reset the rng since it was modified with Next
        rng:SetSeed(seed, i)
        return i
      end
    end
  end
end

print(getShiftIdx(Game():GetLevel():GetDevilAngelRoomRNG())) -- 打印: 2

Next ()⚓︎

int Next ( )⚓︎

将 RNG 的种子“迭代”到伪随机序列中的下一个随机数。(内部使用的 PRNG 算法为 Xorshift。)


Random·Float ()⚓︎

float RandomFloat ( )⚓︎

返回一个 0 到 1 之间的数。包含下限 0,不包含上限 1。

注意:调用此方法会自动调用 RNG.Next,因此会改变 RNG 对象的状态,需谨慎使用。

示例代码
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
-- 这是 Blade 推荐的 ShiftIdx。
-- 0 到 80(含)之间的任意值都可以正常工作。
-- https://www.jstatsoft.org/article/view/v008i14/xorshift.pdf
local RECOMMENDED_SHIFT_IDX = 35
local MY_ENTITY_CHANCE = 0.3 -- 30%

function shouldEntityDoThing(entity)
  local rng = RNG()
  rng:SetSeed(entity.InitSeed, RECOMMENDED_SHIFT_IDX)
  local randomChance = myRNG:RandomFloat()
  return randomChance < MY_ENTITY_CHANCE
end

Random·Int ()⚓︎

int RandomInt ( int Max )⚓︎

返回一个 0 到最大值之间的整数。包含下限 0,不包含上限 Max。

注意:调用此方法会自动调用 RNG.Next,因此会改变 RNG 对象的状态,需谨慎使用。

示例代码
1
2
3
4
5
6
7
local RECOMMENDED_SHIFT_IDX = 35

function getZeroOneTwoOrThree(seed)
  local rng = RNG()
  rng:SetSeed(seed, RECOMMENDED_SHIFT_IDX)
  return rng:RandomInt(4) -- 结果为 0、1、2 或 3。
end

Set·Seed ()⚓︎

void SetSeed ( int Seed, int ShiftIdx )⚓︎

设置指定 RNG 对象的种子。Seed 必须为正整数且不能为 0,否则会导致崩溃。ShiftIdx 必须在 0 到 80(含)之间,否则也会导致崩溃。

Shift index 对照表见:https://gist.github.com/bladecoding/17b341ed08ff94d2deb704ebda8ffc5f

Bug

如果 RNG 对象的种子被设置为 0,调用 Next()RandomInt() 等方法时会导致游戏崩溃。

示例代码
1
2
local myRNG = RNG()
myRNG:SetSeed(Random(), 1)


Last update: January 12, 2026