使用方法
- 「种子」默认
3-7,任意文字都可以:字符码逐字累加后作为线性同余发生器的初值。同一种子永远得到同一批房间,把种子写进团务记录,队友照抄就能复现同一座地城。 - 「房间数量」默认 5,只接受 1~12 的整数;数量只决定生成几间,不改变前几间。
- 点「生成房间」出结果;光标放在种子或数量输入框里按 Enter 同样触发。
- 「换一批」不是重新随机,只把批次号加 1:种子 3-7 第 2 批的第一间变成八角形小间 · 宴会厅大小(约 60 平米)。按钮上会显示当前是第几批。
- 结果区第一行是统计:共几间、种子、第几批、含危险几间、黑暗几间;下面每间房一行,九类素材按固定顺序排列。
- 速查表列的是当前种子与批次下前 20 间房,默认显示 12 行,点「加载更多」展开余下 8 行,点「导出 CSV」存成带字节序标记的文件,Excel 直接打开不乱码。
- 「复制结果」带走当前这批房间全文;「复制推演表」复制 LCG 前 12 步推演的 TSV,可贴进表格软件逐步核对算法。
- 两个判定都是纯文本匹配:危险看第九类素材是否落在 5 条危险项里,黑暗看光线素材是否含「全黑」或「完全没有光」。
这个随机地下城房间生成器能解决什么问题
第一类是跑团临场要一间房。翻到地图上没准备的一格,点一次就有九类素材拼成的完整描写:穹顶圆形大厅 · 篮球场大小 · 粗凿花岗岩 · 塌出大洞看得见楼下 · 被杂草顶开的排水沟盖板 · 天花板垂下一盏锈蚀的铁吊灯 · 烧焦的毛皮味。念出来就能用,再加 NPC 和宝藏就是一个小遭遇。
第二类是密室与剧本杀缺房间文本。写手卡在「二楼左手第一间房什么样」的时候,让生成器出三版挑一版,比对着空白文档发呆快;黑暗与危险两列还能直接当成机关提示用——第 3 间「完全没有光,眼睛还没适应」就是天然的火把戏开场。
第三类是要一个能复现的随机源。多数随机生成器刷新一次换一批,玩家对不上账。这个随机地下城房间生成器把种子和批次号钉进输出:同种子同批次必然同结果,没有 Date.now()、没有时间因子,写进剧本或团务记录都能原样复现。它不做地图绘制、遭遇难度配比和掉落表——那些需要约束求解,不是查表拼句能解决的。
计算原理与变量说明
种子先折成一个 31 位整数。累加规则是 s=(s+str.charCodeAt(i))&0x7fffffff,逐字取字符码相加再截到 31 位。默认种子串是 3-7|0(种子与批次号用竖线相接),字符码依次是 51、45、55、124、48,累加得 323,这就是随机流的起点。
每一步推进用线性同余发生器。s=(Math.imul(s,1103515245)+12345)&0x7fffffff,乘数 1103515245、增量 12345、模数 231。从 323 推进一次得 2100634560,取素材用 Math.floor(s/2147483647*len)%len:2100634560 除以 2147483647 约 0.978,乘池长 10 得 9.78,向下取整为 9,形状池第 9 项正是「半圆形壁龛室」。
取素材为什么不写 s%len。线性同余发生器的低 k 位周期不超过 2k。从 323 起连续推进 20 次,取每次状态的低 4 位:0、9、14、15、12、5、10、11、8、1、6、7、4、13、2、3、0、9、14、15——第 17 个值回到第 1 个,周期恰好 16。若直接用 s%10,20 间房的形状会陷进这个 16 步循环;改成除以 2147483647(即 231−1)取高位比例,用满全部 31 位,同样 20 步看不到循环。公式末尾的 %len 只在 s 取到 0x7fffffff 时兜底。
一间房固定消费 9 次推进。九类素材顺序写死:形状、大小、墙面、地面、家具、光线、气味、声音、危险。前八类池长都是 10,危险池只有 9 条,所以第 9 次推进除的是 9 而不是 10。5 间房共 45 次推进,第 10 次推进(1369816625)取到第 2 间的形状「穹顶圆形大厅」。
批次号是拼进种子串的,不是多跳几步。第 1 批的种子串是 3-7|0,累加值 323;第 2 批是 3-7|1,累加值 324。初值只差 1,但线性同余对初值极其敏感,两批输出毫无共同之处。反过来,「换一批」也完全可以由别人复现:告诉他种子 3-7、第 2 批就行。
组合空间是 108×9 = 900000000(9 亿)。八类各 10 条、危险类 9 条相乘即得。同一个种子下批次号还能继续分岔,实际可寻址的房间数远大于 9 亿。
两个判定规则。危险:9 条危险素材里 SAFE 白名单 4 条(索引 0、1、2、4),命中算安全,其余 5 条(地板翻板、门后插销、触手、暗处的眼睛、掉砂的天花板)算危险。黑暗:光线素材文本含「全黑」或「完全没有光」即计,默认 5 间里第 3 间的「完全没有光,眼睛还没适应」是唯一命中。
完整示例(数值仅作演示)
默认一组:种子 3-7、第 1 批、5 间。统计行为「共 5 个房间,种子 3-7,第 1 批;含危险 2 个,黑暗 1 个。」第一间全文是:半圆形壁龛室 · 双层挑高 · 木板钉成的隔墙 · 磨得发亮的岩石 · 裂了缝的石棺 · 墙角一堆荧石泛着冷绿的光 · 潮湿的霉味 · 某处风穿过缝隙的哨音 · 墙缝里伸出的触手只够到你脚踝。它的九次推进依次取到索引 9、8、5、3、7、1、1、1、6。
数量改 1:输出只剩第一间,与上面那一行逐字相同——前几间不随后面加房间而改变。数量改 12:前 5 间不变,第 6 间是穹顶圆形大厅 · 壁橱大小,速查表第 6 行可见它是 12 间里的第二间黑暗房。
换一批:点一次「换一批」,批次号变 2,第一间变成八角形小间 · 宴会厅大小(约 60 平米)· 木板钉成的隔墙 · 石板拼缝长草 · 拴过动物的铁环 · 四角各插一支白烛,都短得快灭了 · 劣质灯油的呛味 · 沉重的呼吸声,一进一出 · 火把余光里有一双眼睛,没动。种子没动,只是 3-7|1 换了随机流起点。
批次速查表与 LCG 推演
第一张表是当前种子与批次下前 20 间房的速查,列分别是序号、形状、大小、危险项与明暗;默认 12 行,「加载更多」补上 13~20 行,「导出 CSV」导出全部 20 行。
| 步数 | 推进后状态 s | 维度 | 池长 | 索引 | 取到素材 |
|---|---|---|---|---|---|
| 1 | 2100634560 | 形状 | 10 | 9 | 半圆形壁龛室 |
| 2 | 1728375033 | 大小 | 10 | 8 | 双层挑高 |
| 3 | 1168719934 | 墙面 | 10 | 5 | 木板钉成的隔墙 |
| 4 | 681012895 | 地面 | 10 | 3 | 磨得发亮的岩石 |
| 5 | 1512618988 | 家具 | 10 | 7 | 裂了缝的石棺 |
| 6 | 287447989 | 光线 | 10 | 1 | 墙角一堆荧石泛着冷绿的光 |
| 7 | 318054986 | 气味 | 10 | 1 | 潮湿的霉味 |
| 8 | 302929339 | 声音 | 10 | 1 | 某处风穿过缝隙的哨音 |
| 9 | 1474013912 | 危险 | 9 | 6 | 墙缝里伸出的触手只够到你脚踝 |
| 10 | 1369816625 | 形状 | 10 | 6 | 穹顶圆形大厅 |
| 11 | 1315641622 | 大小 | 10 | 6 | 篮球场大小 |
| 12 | 37917335 | 墙面 | 10 | 0 | 粗凿花岗岩 |
第二张表是 LCG 的前 12 步推演,每一步都能拿计算器复算:把上一行的状态代入 s=(Math.imul(s,1103515245)+12345)&0x7fffffff,再按 Math.floor(s/2147483647*len)%len 取索引。第 9 步池长是 9,其余是 10,这张表同时也解释了为什么危险类只有 9 条素材。
输入范围、边界与适用说明
- 房间数量 1~12 的整数。填 0、13、1.5 或留空都会报错并说明原因,不会悄悄取一个默认值继续生成。
- 种子最长 16 个字符。超长部分输不进去;种子被清空时点「生成房间」会自动填回
3-7,不会输出空结果。 - 素材池固定 89 条,不联网扩展。八类各 10 条、危险类 9 条,全部写在页面脚本里;本页没有自定义素材的入口,也不需要。
- 没有地图、没有坐标、没有难度。输出只是九段文本,不画平面图、不定遭遇等级、不掉落——把它当成描写素材库,而不是遭遇生成系统。
- 危险与黑暗是文本判定,不是游戏规则。「安全」只表示该条素材不含危险描写,DM 该加的陷阱照加。
- 确定性是特性也是限制。同种子同批次永远同结果,适合复现与留档;要「真随机」抽奖请用带密码学随机源的工具,本页的线性同余序列可被推导。
- 刷新页面恢复默认。批次号、种子与数量都不保存,关掉标签页即回到种子 3-7、5 间房、第 1 批。
- 导出格式。CSV 带字节序标记,Excel 打开不乱码;「复制推演表」走剪贴板 API,被拦截时请手动选中复制。
常见问题
同一个种子为什么每次结果都一样?
因为随机源是种子折成的 31 位整数推进线性同余序列,每一步只依赖当前状态,没有 Math.random(),也没有任何时间因子;刷新、换设备、换浏览器,结果都逐字相同。
换一批和改种子有什么区别?
改种子是换一条随机流,累加初值整个变掉;换一批只把批次号从 0 变 1,种子串从 3-7|0 变成 3-7|1,累加值从 323 变 324,输出同样完全改观。两者都可复现。
为什么不用 Math.random,这样还算随机吗?
算,但算「可复现的伪随机」。线性同余序列拼房间完全够用;选它的理由恰恰是不要不可复现——记录里写下「种子 3-7 第 1 批」,一个月后还能原样重建。抽奖、发券请用带密码学随机源的工具。
9 亿种组合会很快重复吗?
不会。组合空间 108×9 = 900000000,一批 12 间也只占千万分之一。真正的重复风险来自种子本身:总用同一个种子加同一批次才会拿到同一批房间,而批次号可以一直往上加。
危险和黑暗是怎么判定的,能改吗?
不能改。危险:第九类素材命中 4 条安全白名单算安全,其余 5 条算危险;黑暗:光线素材含「全黑」或「完全没有光」即计。两条规则都是纯文本匹配,统计行里直接可见。
把数量从 5 改成 12,前 5 间会变吗?
不会。随机流按顺序消费,第 i 间房只消费第 9i−8 到 9i 次推进,与总数无关:数量 3 和数量 12 的前 3 间逐字相同。可以先出 3 间看风格,满意了再加到 12 间。
生成的房间可以直接写进剧本或模组吗?
可以,输出是九段中文描写;但素材池只有 89 条,容易和别人撞句,建议生成后再改写一轮,或换种子多抽几批挑着用。
数据会上传到服务器吗?
不会。查表、推进、统计与导出全部在本页完成,没有发起任何网络请求;种子、数量与批次号都不写入浏览器存储,刷新即恢复默认值。