slime/show/RANDOM_PROPERTIES.md

470 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 随机数性质:怎样从坐标图案反推种子候选
前面的 01–04 在做同一件事:给定一批种子和坐标,把它们检查得更快。这一章换一个角度:如果我们已经知道哪些坐标应该是史莱姆区块,能否利用随机数公式,先排除大量种子,再求出值得检查的候选?
我们以一个固定坐标的实心 5×5 图案为例。目标是寻找一个世界种子,让这 25 个格子同时满足要求。我们不知道每格产生的随机数具体是多少,只知道它们应该通过史莱姆判断。因此,这里的“反推”是根据多个条件缩小候选范围,结果可能有多个种子。
当前方法分成三步:**筛低 18 位的可能取值,补上中间 17 位,再求出高 13 位的共同解。** 最后执行完整的 Java Random 验证。
下面解释筛选和求解的过程,以及每一步的数学依据。首次输出筛选还没有完整覆盖拒绝重抽的例外;这个限制在文末说明。
## 1. 先区分种子、内部状态和随机输出
对坐标 $(x_i,z_i)$,原始史莱姆公式先计算坐标项:
$$
T(x_i,z_i)=F(x_i)+G(z_i).
$$
坐标项包含平方、乘法和加法,必须遵循原始 Java 的整数回绕与符号扩展规则,完整说明见 [OUTER_SUM.md](video/OUTER_SUM.md)。下面用 $d_i=T(x_i,z_i)$ 表示第 $i$ 格的坐标项。
设世界种子的低 48 位为 $w$,合并史莱姆公式与 Java Random 初始化中的两个 XOR,得到:
$$
A=\mathtt{0x5DEECE66D},\qquad
C=A\mathbin{\mathrm{xor}}987234911=\mathtt{0x5E434E432}.
$$
每个格子的首次随机输出按下面三步产生:
$$
u_i=((w+d_i)\mathbin{\mathrm{xor}}C)\bmod2^{48},
$$
$$
v_i=(Au_i+11)\bmod2^{48},
$$
$$
q_i=\left\lfloor v_i/2^{17}\right\rfloor.
$$
这三个数的含义不同:
| 符号 | 含义 |
| --- | --- |
| $w$ | 待求的世界种子低 48 位 |
| $d_i$ | 第 $i$ 格的坐标项,坐标确定后就能计算 |
| $u_i$ | Random 初始化后的 48 位内部状态 |
| $v_i$ | 内部状态推进一次后的结果 |
| $q_i$ | 取出 $v_i$ 的高 31 位得到的首次输出 |
其中,`mod` 表示取余数。例如 $8194\bmod8192=2$。模 $2^k$ 相当于只保留一个数的低 $k$ 位。
对被接受的首次输出,`nextInt(10)` 返回 $q_i\bmod10$,返回 0 就表示史莱姆区块。我们先利用“$q_i$ 能被 10 整除”的条件生成候选,随后完整验证。
## 2. 为什么只考虑世界种子的低 48 位
Random 初始化时只保留低 48 位。因此,在同一个坐标上,如果两个原始世界种子 $W_1,W_2$ 相差整数倍的 $2^{48}$,初始化状态就相同,以后的随机数序列也相同:
$$
W_2=W_1+k2^{48}
\quad\Longrightarrow\quad
\mathrm{slime}(W_2,x,z)=\mathrm{slime}(W_1,x,z).
$$
这条性质覆盖完整的随机数序列,包括拒绝重抽。搜索时可以先求低 48 位,原始 64 位输入的高 16 位对应同一组史莱姆判断结果。
这里讨论的是史莱姆判断的等价关系,不能据此断言整个 Minecraft 世界相同。
## 3. 把待求的 48 位分成三部分
按通常从高位到低位的书写顺序,这三部分是:
```text
高 13 位 h | 中间 17 位 m | 低 18 位 p
```
对应数值关系:
$$
w=p+2^{18}m+2^{35}h.
$$
各部分的取值范围是:
$$
0\le p<262144,\qquad
0\le m<131072,\qquad
0\le h<8192.
$$
补上中间 17 位后,得到低 35 位:
$$
\ell=p+2^{18}m,\qquad w=\ell+2^{35}h.
$$
这三个部分的处理方式不同:低 18 位先筛选,中间 17 位目前主要枚举,高 13 位通过分段同余条件求解。
## 4. 低 18 位为什么能提前筛选
首次输出是:
$$
q_i=v_i\gg17.
$$
右移 17 位,就是去掉内部状态的低 17 位。于是,**$q_i$ 的最低位,对应 $v_i$ 的第 17 位**,位编号从 0 开始。
一个数要能被 10 整除,首先必须是偶数。我们只要知道 $v_i$ 的低 18 位,就能知道它的第 17 位,从而判断首次输出的奇偶。
为什么计算这 18 位时,可以暂时不管世界种子的高位?因为加法、乘法和逐位 XOR 的低 $k$ 位,只依赖输入的低 $k$ 位。更高位不会反过来改变低位。
因此,令 $p=w\bmod2^{18}$、$d_{i,18}=d_i\bmod2^{18}$,只需要计算:
$$
a_i=(p+d_{i,18})\bmod2^{18},
$$
$$
u_{i,18}=a_i\mathbin{\mathrm{xor}}(C\bmod2^{18}),
$$
$$
v_{i,18}=(Au_{i,18}+11)\bmod2^{18}.
$$
最后检查:
$$
v_{i,18}<2^{17}=131072.
$$
小于这个分界值,说明第 17 位为 0,首次输出是偶数;否则就是奇数。
**坐标项也参与计算。** 这条性质说的是“种子的低 18 位,加上该格坐标项的低 18 位,足以决定首次输出奇偶”。换坐标后,结果可能改变。
## 5. 怎样从一个图案生成低 18 位候选表
只有一个“5×5”的形状还不够,需要知道锚点在哪。已有样例的锚点是:
$$
(x_0,z_0)=(51069,419124).
$$
图案包含的 25 个坐标为:
$$
(x_i,z_i)=(x_0+\Delta x,z_0+\Delta z),
\qquad\Delta x,\Delta z\in\{0,1,2,3,4\}.
$$
生成表的过程可以按下面的顺序理解:
1. 计算 25 个坐标项,分别保留低 18 位。
2. 尝试一种种子的低 18 位取值 $p$。
3. 用这个 $p$ 检查 25 格的首次输出奇偶。
4. 有一格为奇数,就淘汰这个 $p$;全部为偶数,就保存。
5. 对 $p=0,1,\ldots,262143$ 重复这个过程。
这相当于为每格求出一个允许集合,再对 25 个集合求交。
看两个实际取值,就能理解“保留”和“淘汰”是什么意思:
| 种子的低 18 位 $p$ | 检查的格子 | $v_{i,18}$ | 结果 |
| --- | --- | ---: | --- |
| 0 | $(51069,419124)$ | 53282 | 偶数条件通过 |
| 0 | $(51069,419125)$ | 178468 | 失败,整个 $p=0$ 淘汰 |
| 3948 | $(51069,419124)$ | 1118 | 偶数条件通过 |
| 3948 | $(51069,419125)$ | 73664 | 偶数条件通过 |
$p=3948$ 在其余格子上也通过,所以进入最后的候选表。
固定锚点 $(51069,419124)$,把要求通过的图案从 1 格逐步扩大到 5×5。每次保留已有格子,再加入扩大后新增的一圈格子,剩余取值数量如下。表中的 0 表示尚未加入任何格子条件,1 表示只检查锚点这一格:
| 要求通过的图案 | 剩余低 18 位取值数 |
| ---: | ---: |
| 0 | 262144 |
| 1 | 131072 |
| 2×2 | 20383 |
| 3×3 | 3385 |
| 4×4 | 427 |
| 5×5 | 84 |
单格恰好保留一半取值,是因为加坐标项、XOR 和奇数乘法在模 $2^{18}$ 下都是一一对应的变换。继续加入格子,只会增加条件,所以候选数量只能保持不变或减少。
这 84 种取值就是“该坐标图案允许的世界种子低 18 位候选表”。
对固定图案,这一步可以作为预处理,只做一次。后续直接遍历这 84 种取值,给它们补上更高位,不必让所有完整种子先查一次表。
这里的 84 只适用于样例中的具体坐标。移动锚点或改变形状后,需要重新筛选;如果两个图案对应格子的坐标项低 18 位全部相同,就可以复用这张低位候选表,但完整随机输出仍可能不同。
## 6. 中间 17 位目前怎样处理
取出一个通过筛选的 $p$,再枚举:
$$
m=0,1,\ldots,131071.
$$
每次拼出一种低 35 位取值:
$$
\ell=p+2^{18}m.
$$
然后把这个 $\ell$ 交给高 13 位求解器:是否存在某个 $h$,能让所有格子满足首次输出的模 10 条件?如果没有,就淘汰这个 $\ell$。
因此,当前没有另一张能直接消除中间 17 位枚举的通用表。样例需要处理:
$$
84\times2^{17}=11010048
$$
种低 35 位取值。低 18 位筛选避免了大量无效工作,但中间位的枚举成本仍然存在。
## 7. 为什么固定低 35 位后,高位可以单独求解
现在固定一种 $\ell$,世界种子写成:
$$
w=\ell+2^{35}h.
$$
选择 35 的原因是 XOR 常量 $C$ 恰好需要 35 位:
$$
2^{34}\le C<2^{35}.
$$
它只会翻转低 35 位,不会碰到未知的高 13 位。
这里还要保留坐标加法的进位。对第 $i$ 格,把 $h=0$ 时的输入拆成:
$$
(\ell+d_i)\bmod2^{48}=L_i+2^{35}H_i.
$$
$H_i$ 包含坐标加法产生的进位,也包含负坐标项在模 $2^{48}$ 下的表示。加入 $h$ 后,低位 $L_i$ 不变,高位成为 $(H_i+h)\bmod8192$。
XOR 只改动 $L_i$,因此初始化状态满足:
$$
u_i(h)=(u_i(0)+2^{35}h)\bmod2^{48}.
$$
再推进一次状态:
$$
v_i(h)=(v_i(0)+Ah\,2^{35})\bmod2^{48}.
$$
最后取首次输出,去掉状态低 17 位。新增量本来就是 $2^{35}$ 的整数倍,不会改变被去掉的低位余数,所以:
$$
q_i(h)=(q_i(0)+Ah\,2^{18})\bmod2^{31}.
$$
这里的 $18$ 来自 $35-17$。
这是利用不同位域分离得到的平移关系。一般的 XOR 并不具有这种加法性质。若切在 34 位,$C$ 仍会翻转未知部分的一位,上面的直接平移就不成立;切在 36 位等更高位置也可以分离,但剩下可解析的高位就更少了。
## 8. $r_i,b_i$ 是怎样实际算出来的
它们来自一个确定的计算结果。选定 $\ell$ 和第 $i$ 格的坐标,先暂时令 $h=0$,按照原始公式计算:
$$
u_i(0)=((\ell+d_i)\mathbin{\mathrm{xor}}C)\bmod2^{48},
$$
$$
v_i(0)=(Au_i(0)+11)\bmod2^{48},\qquad
q_i(0)=\left\lfloor v_i(0)/2^{17}\right\rfloor.
$$
再把 $q_i(0)$ 除以 $262144=2^{18}$:
$$
r_i=q_i(0)\bmod262144,\qquad
b_i=\left\lfloor q_i(0)/262144\right\rfloor.
$$
$r_i$ 是余数,也就是输出的低 18 位;$b_i$ 是商,也就是输出的高 13 位。例如,如果某格算出 $q_i(0)=524290$:
$$
524290=2+262144\times2,
$$
那么 $r_i=2,b_i=2$。这只是拆分数字的例子,不是前面样例某格的实测输出。
改变 $h$ 后,该格的首次输出就是:
$$
\boxed{q_i(h)=r_i+2^{18}\bigl((b_i+Ah)\bmod8192\bigr).}
$$
**$b_i$ 是随机输出的一部分,$h$ 是待求种子的一部分,不能把两者当成同一个数。** $r_i,b_i$ 在当前 $\ell$ 和坐标下固定,不同格子通常具有不同的 $r_i,b_i$,但所有格子共用同一个未知 $h$。
## 9. 为什么先求 $t$,再换回 $h$
为了让规则更容易处理,令:
$$
t=Ah\bmod8192.
$$
用 $e_i$ 表示换元后该格输出的高 13 位:
$$
e_i=(b_i+t)\bmod8192,\qquad
q_i=r_i+2^{18}e_i.
$$
$A$ 是奇数,和 $8192=2^{13}$ 互质,所以这个换元只是在重新排列 8192 个编号,不会重复或遗漏。
具体来说:
$$
A\bmod8192=1645,\qquad
1645\times4965=997\times8192+1.
$$
因此,求到 $t$ 后,可以直接换回:
$$
\boxed{h=4965t\bmod8192.}
$$
这里用到了“奇数乘数在模 $2^k$ 下有逆元”的性质。如果完整状态 $v$ 已知,同样可以用模逆恢复上一状态:
$$
u=A^{-1}(v-11)\bmod2^{48}.
$$
但首次输出已经丢掉状态低 17 位,而史莱姆观察只提供一个布尔结果。因此,当前搜索仍需组合多个格子的条件来求候选。
## 10. 每格到底对 $t$ 提出什么要求
我们要让首次输出能被 10 整除。偶数条件已经由低 18 位筛选保证,现在还需要能被 5 整除。
因为:
$$
2^{18}\equiv4\equiv-1\pmod5,
$$
所以:
$$
q_i=r_i+2^{18}e_i\equiv r_i-e_i\pmod5.
$$
于是,每格提出的要求是:**$e_i$ 除以 5 的余数,必须与 $r_i$ 相同。**
完整写法为:
$$
q_i\equiv0\pmod{10}
\iff r_i\equiv0\pmod2\ \text{且}\ e_i\equiv r_i\pmod5.
$$
如果高位求解器单独接收一个没有预先筛过的低 35 位取值,发现某格 $r_i$ 为奇数,就会立即返回无候选。
## 11. 回绕点是什么,为什么它会改变规则
考虑:
$$
e_i=(b_i+t)\bmod8192.
$$
可以把它想成一个从 0 数到 8191 的计数器。到 8192 时,就回到 0。
例如 $b_i=8190$:
| $t$ | $b_i+t$ | 取模后的 $e_i$ |
| ---: | ---: | ---: |
| 0 | 8190 | 8190 |
| 1 | 8191 | 8191 |
| 2 | 8192 | 0 |
| 3 | 8193 | 1 |
| 4 | 8194 | 2 |
$t=2$ 就是回绕点。一般来说,回绕点为:
$$
\tau_i=8192-b_i.
$$
点之前,$e_i=b_i+t$;从这个点开始,$e_i=b_i+t-8192$。由于 $0\le b_i,t<8192$,相加最多回绕一次。
把上一节的要求代入,就得到:
$$
\begin{cases}
t\equiv r_i-b_i\pmod5,&0\le t<\tau_i,\\
t\equiv r_i-b_i+2\pmod5,&\tau_i\le t<8192.
\end{cases}
$$
第二种要求多了 2,是因为 $8192\bmod5=2$。若 $b_i=0$,回绕点在 8192,超出 $t$ 的有效整数范围,所以这个格子在整个范围里都不回绕。
## 12. 用两个格子的数值例子,把求解串起来
下面的 $r_i,b_i$ 是用于讲解的示意数值,不是 5×5 样例的实测参数。
第一格取 $r_1=2,b_1=8190$。它要求 $e_1\bmod5=2$,回绕点在 $t=2$:
- $t<2$ 时,要求 $t\bmod5=2$。
- $t\ge2$ 时,要求 $t\bmod5=4$。
第二格取 $r_2=0,b_2=1$。它要求 $e_2\bmod5=0$,回绕点在 $t=8191$:
- $t<8191$ 时,要求 $t\bmod5=4$。
- $t\ge8191$ 时,要求 $t\bmod5=1$。
把两格条件合并:
| $t$ 的区间 | 第一格要求的余数 | 第二格要求的余数 | 共同解 |
| --- | ---: | ---: | --- |
| $[0,2)$ | 2 | 4 | 无 |
| $[2,8191)$ | 4 | 4 | 区间中除以 5 余 4 的数 |
| $[8191,8192)$ | 4 | 1 | 无 |
因此,允许的 $t$ 是:
$$
t=4,9,14,\ldots,8189.
$$
取 $t=4$,换回种子的高位:
$$
h=4965\times4\bmod8192=3476.
$$
检查两个格子的首次输出:
$$
e_1=(8190+4)\bmod8192=2,\qquad
q_1=2+2^{18}\times2=524290,
$$
$$
e_2=(1+4)\bmod8192=5,\qquad
q_2=2^{18}\times5=1310720.
$$
两个输出都能被 10 整除,所以 $h=3476$ 是这两格共同允许的高位取值。真实图案对 25 格做同样的求交,最后拼成完整种子,再验证。
## 13. 最后说明首次输出模型的边界
上面的状态与输出变换恒等式是精确的。覆盖限制来自用“首次输出能被 10 整除”生成候选。
Java `nextInt(10)` 遇到:
$$
q\ge2147483640=2^{31}-8
$$
时,会拒绝这个输出,继续推进内部状态,再取一个输出。例如 $2147483640$ 虽然能被 10 整除,也不会直接被接受。
因此会有两种情况:
- 首次输出符合我们的候选条件,但被拒绝,重抽后失败。最终精确验证会剔除这种假阳性。
- 首次输出不符合候选条件,例如是奇数,但处在拒绝尾部,重抽后成功。它可能在低位筛选阶段就被淘汰,最终验证无法补回这种漏解。
所以,当前流程准确验证所有输出的候选,但不能宣称已经找齐完整 Java Random 语义下的所有解。
低 18 位的 84 种取值、正文中的筛选数量和两个格子的示意例子,都可以按照上面的计算步骤独立核对。