Files
gplan-2/game/tests/unit/data_config/rng_service_test.gd
T
DKChan 6c2dbc37c1 docs: ADR 体系废除 + architecture.md 确立为架构唯一事实源(2026-10-15 用户令:决策记录归 git commit log,不另存决策文档)
- 删除 design/dev/architecture/adr-0001~0007 共 7 份文件(内容留 git 历史可查)
- architecture.md:删「ADR 审计」「ADR 立项清单」两节;清除全文 ADR-000X 注记、QQ 表/S 表 ADR 引用;未决表关闭已落定项(QQ-01/02/03),立项清单在途事项转登记 QQ-11~14;补 A1 生成姿态事实、autoload 四件清单、board_generator 性能姿态;文档状态立「事实源地位」条
- CLAUDE.md:恢复 RNG 单点硬性红线(去 ADR-0007 引用);新增「架构事实唯一源」红线;规范导航架构行标注唯一事实源
- doc-conventions:§5 增「架构事实唯一源」行;§11 活文档清单补架构文档
- registry:architecture.yaml 删 18 处 adr 字段、autoload_set 补 SaveManager/MetaProgression、board_rending 更新为 Node2D 已落地事实;entities.yaml 12 处引用清除
- game/ 代码注释约 60 处清 ADR-000X 引用(事实与日期保留);豁免标记 ADR-0007-exempt → rng-seed-exempt(main.gd/static_scan.sh/architecture.md/06/iter27 五处同步)
- GDD/qa 实现报告/research 卡片/roadmap/tests README 引用全清;死链校验 1206 链接 0 死链、gdd_lint 0 不通过
- 代码中 adr/adr5 等为 adventure_runner 既有局部变量名(非 ADR 引用),未动
2026-10-15 23:52:30 +08:00

80 lines
3.4 KiB
GDScript
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.
# tests/unit/data_config/rng_service_test.gd — 统一随机流单元测试:单盐派生确定性/计数器账本/标签词表封闭
# 运行:godot --headless --path game --script res://tests/unit/data_config/rng_service_test.gd
# 红线:零自建 RNG——本测试只经 RngService 统一流取数(确定性契约:同种子逐位复现)。
# 测试种子为夹具基建值(非玩法数值),与冒烟黄金向量锚(smoke_all m=42 scope 0-4)分工:本文件测
# 「同种子两实例逐位一致」的相对确定性,绝对向量锚归冒烟单点,避免双处维护同一常量。
extends SceneTree
const RngServiceScript := preload("res://core/rng_service.gd")
const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:_check/汇总退出样板单点
const TEST_SEED := 20260928 # 夹具种子(任意固定值;语义 = 可复现性,非玩法数值)
func _init() -> void:
_test_derive_determinism()
_test_counter_ledger()
_test_stream_draw_determinism()
_test_negative_seed_normalization()
quit(Kit.finish("rng_service_test"))
func _fresh_service():
var rng = RngServiceScript.new()
rng.set_master_seed(TEST_SEED)
return rng
# 单盐派生纯函数:两全新实例同种子逐位一致(derive_at 不推计数器——纯函数契约)
func _test_derive_determinism() -> void:
var a = _fresh_service()
var b = _fresh_service()
var same := true
for scope in range(8):
if a.derive_at(scope) != b.derive_at(scope):
same = false
Kit.check("同种子两实例 derive_at(0..7) 逐位一致", same)
var a2 = _fresh_service()
var before: int = a2.counter()
a2.derive_at(0)
Kit.check("derive_at 为纯函数不推计数器", a2.counter() == before)
# 全局取数计数器:唯一账本——open_stream 逐次 +1(scope 单调)
func _test_counter_ledger() -> void:
var rng = _fresh_service()
var c0: int = rng.counter()
rng.open_stream("armor_roll")
var c1: int = rng.counter()
rng.open_stream("armor_roll")
var c2: int = rng.counter()
Kit.check("open_stream 逐次推进全局计数器(+1/次)", c1 == c0 + 1 and c2 == c0 + 2)
# 用途标签只进事件日志不参与派生——同 scope 同派生种子(2026-09-27 统一流裁决口径)
var rng_x = _fresh_service()
var rng_y = _fresh_service()
var s1: int = int(rng_x.open_stream("board_gen").seed)
var s2: int = int(rng_y.open_stream("reward_roll").seed)
Kit.check("同 scope 异用途标签派生种子一致(标签不参与派生)", s1 == s2)
# 同种子两实例同标签流的实际取数序列逐位一致(回放确定性契约——存档快照=主种子+计数器的前提)
func _test_stream_draw_determinism() -> void:
var faces := 20 # d20 探针面数(夹具值,非玩法表值——只用于产生可比较序列)
var a = _fresh_service()
var b = _fresh_service()
var same := true
for i in range(12):
var ra: int = a.open_stream("armor_roll").randi_range(1, faces)
var rb: int = b.open_stream("armor_roll").randi_range(1, faces)
if ra != rb:
same = false
Kit.check("同种子两实例同标签流取数 12 次逐位一致", same)
# 负输入 abs 归一化(警告通道)——|−s| 与 s 同派生
func _test_negative_seed_normalization() -> void:
var pos = _fresh_service()
var neg = RngServiceScript.new()
neg.set_master_seed(-TEST_SEED)
Kit.check("负种子 abs 归一化后派生与正种子一致", pos.derive_at(0) == neg.derive_at(0))