iter(36): 卡C+卡A 实现——开场行后缀认加算区(六项布尔+三路径断言:白板反向/续玩重建正向,卡片②奖励节点前提缺陷改快照喂入形态代拍2)、营地六处灰字STONE_DEEP+取色/源扫描断言、迷雾测点三关归一后基准+派生校验(T0对拍L2/L3修值L2条款)、文案禁字清扫钉值表13单元+player_copy_sweep新宿主24断言入清单、变异验证全套留痕(对照表证据随实现报告)
This commit is contained in:
1 parent
2931b1f250
commit
9468c70ee2
19 files changed
+489
-31
No files matched your search
@@ -0,0 +1,174 @@
|
||||
# tests/unit/presentation/player_copy_sweep_test.gd — 玩家面文案清扫直建断言宿主(迭代36 卡A)
|
||||
# 断言面 = 玩家面字符串字面量换代钉值(u1–u13 钉值表——分类词/渠道旧话/「雷」族禁字清零):
|
||||
# ① hero 面板两段头(专长/属性值提升——同屏分类撞车消除)
|
||||
# ② 奖励节点三选一头部(冒险牌库/渠道分流三机制事实,零「同权重/同上限/提升池」旧话)
|
||||
# ③ 专长卡兜底(feat_card_text 空行兜底「专长\n???」)
|
||||
# ④ 图例封印行(标空/受挖掘惩罚,零「插错/挖雷」)
|
||||
# ⑤ 状态槽来源名(mine_hit→危险格——tooltip 消费半)
|
||||
# ⑥ 结算来源名(settlement 表值经 ConfigDB 真装载+battle_log 行消费半)
|
||||
# ⑦ 已开危险格字形(glyph「危」+plate+RED_MINE——BoardView rebuild 真实刷新路径)
|
||||
# ⑧ 源 token 扫描一:board_view.gd 零 "雷" 字面量(哨兵族统一钉住)
|
||||
# ⑩ 源 token 扫描二:battle_orchestrator.gd 玩家面字符串字面量零「挖雷」(注释剥离=行首 # 判)
|
||||
# 扫域口径:玩家面字符串字面量(契约 2 保留面——注释/内部常量名与注记/测试消息串不入域)。
|
||||
# 协议照单元侧惯例:extends SceneTree+Kit.check 主通道;--script 模式无 autoload,
|
||||
# ConfigDB 显式实例化构造注入(统一流 master 种子 42 沿源)。
|
||||
# 运行:godot --headless --path game --script res://tests/unit/presentation/player_copy_sweep_test.gd
|
||||
extends SceneTree
|
||||
|
||||
const Kit := preload("res://tests/unit/test_kit.gd")
|
||||
const ConfigDBScript := preload("res://core/config_db.gd")
|
||||
const AutoPlayer := preload("res://sim/auto_player.gd") # 自动玩家策略单一实现(夹具开域驱动)
|
||||
|
||||
var _db
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
_db = ConfigDBScript.new()
|
||||
var load_ok: bool = _db.load_tables("res://data/tables", true)
|
||||
if not load_ok:
|
||||
push_error("[player_copy_sweep_test] 表加载返回失败——诊断如下(红由具体断言落)")
|
||||
for d in _db.diagnostics():
|
||||
if d.severity == "error" or d.severity == "fatal":
|
||||
push_error(" [%s] %s: %s" % [d.severity, d.category, d.message])
|
||||
_sweep_hero_panel()
|
||||
_sweep_narrator()
|
||||
_sweep_legend()
|
||||
_sweep_source_names()
|
||||
_sweep_board_glyph()
|
||||
_sweep_token_scans()
|
||||
quit(Kit.finish("player_copy_sweep_test"))
|
||||
|
||||
|
||||
# ① C 区两段头(u1/u2——直建 hero 面板,adventure_feats_test ⑦c 族同构)
|
||||
func _sweep_hero_panel() -> void:
|
||||
var panel = load("res://presentation/views/hero_info_panel_view.gd").new()
|
||||
var feat_head := _first_label(panel._feat_section)
|
||||
var curio_head := _first_label(panel._curio_section)
|
||||
Kit.check("C 区专长段头==「专长」(u1 换代——段头文案钉值)〔wa1〕",
|
||||
feat_head != null and feat_head.text == "专长")
|
||||
Kit.check("C 区属性值提升段头==「属性值提升」(u2 换代——同屏两段同标撞车消除)〔wa1〕",
|
||||
curio_head != null and curio_head.text == "属性值提升")
|
||||
|
||||
|
||||
# ②③ 奖励节点头部+专长卡兜底(u3/u11——静态直调)
|
||||
func _sweep_narrator() -> void:
|
||||
var narrator = load("res://presentation/battle_narrator.gd")
|
||||
var head := String(narrator.node_curio_header())
|
||||
Kit.check("奖励点头部含「冒险牌库」(u3 机制事实①同库)〔wa4〕", head.contains("冒险牌库"))
|
||||
Kit.check("奖励点头部含「属性值提升与补给」(u3 机制事实②渠道分流)〔wa4〕", head.contains("属性值提升与补给"))
|
||||
Kit.check("奖励点头部含「同库分流」(u3 机制事实②措辞)〔wa4〕", head.contains("同库分流"))
|
||||
Kit.check("奖励点头部零「同权重」旧话(u3 清零)〔wa4〕", not head.contains("同权重"))
|
||||
Kit.check("奖励点头部零「同上限」旧话(u3 清零)〔wa4〕", not head.contains("同上限"))
|
||||
Kit.check("奖励点头部零「提升池」旧话(u3 清零)〔wa4〕", not head.contains("提升池"))
|
||||
Kit.check("专长卡兜底==「专长\n???」(u11 换代——数据缺行真实兜底路径)〔wa3〕",
|
||||
String(narrator.feat_card_text({})) == "专长\n???")
|
||||
|
||||
|
||||
# ④ 图例封印行(u4——直建 LegendOverlay 读 ENTRIES 常量)
|
||||
func _sweep_legend() -> void:
|
||||
load("res://presentation/views/legend_overlay.gd").new() # 直建(_init(rap_cost) 现签名)
|
||||
var seal_row: Array = []
|
||||
for e in load("res://presentation/views/legend_overlay.gd").ENTRIES:
|
||||
if String(e[1]) == "封印":
|
||||
seal_row = e
|
||||
break
|
||||
Kit.check("图例封印行存在(wa5 夹具前提)〔wa5〕", not seal_row.is_empty())
|
||||
Kit.check("图例封印行含「标空」(u4——与「标中」成对)〔wa5〕", String(seal_row[2] if seal_row.size() > 2 else "").contains("标空"))
|
||||
Kit.check("图例封印行含「受挖掘惩罚」(u4 雷字清零换代)〔wa5〕", String(seal_row[2] if seal_row.size() > 2 else "").contains("受挖掘惩罚"))
|
||||
Kit.check("图例封印行零「插错」(u4 旗族遗留词干清零)〔wa5〕", not String(seal_row[2] if seal_row.size() > 2 else "").contains("插错"))
|
||||
Kit.check("图例封印行零「挖雷」(u4 雷字清零)〔wa5〕", not String(seal_row[2] if seal_row.size() > 2 else "").contains("挖雷"))
|
||||
|
||||
|
||||
# ⑤⑥ 来源名双源(u5/u6——状态槽消费半+表值 ConfigDB 真装载+battle_log 行消费半)
|
||||
func _sweep_source_names() -> void:
|
||||
var row_view = load("res://presentation/views/status_slot_row.gd").new()
|
||||
row_view.set_effects([{"effect_id": "alert", "source_class": "mine_hit",
|
||||
"display_name": "危险格受击", "remaining_settlements": 2, "round_index": 1}])
|
||||
var slot: PanelContainer = null
|
||||
for child in row_view.get_children():
|
||||
if child is PanelContainer and child.has_meta("eff"):
|
||||
slot = child
|
||||
break
|
||||
Kit.check("状态槽 mine_hit 效果行在座(wa6 夹具前提)〔wa6〕", slot != null)
|
||||
if slot != null:
|
||||
row_view._on_slot_hover(slot)
|
||||
Kit.check("状态槽来源注记==「危险格」(u5 换代——meta tooltip 消费半)〔wa6〕",
|
||||
row_view._tip_label.text.contains("来源:危险格"))
|
||||
row_view._hide_tip()
|
||||
Kit.check("结算表 source_label_map[mine_hit]==「危险格」(u6 换代——ConfigDB 真装载)〔wa7〕",
|
||||
String(_db.settlement.source_label_map.get("mine_hit", "")) == "危险格")
|
||||
var log_view = load("res://presentation/views/battle_log_view.gd").new(_db)
|
||||
var row_txt := String(log_view._format_row({"type": "effect", "source_class": "mine_hit",
|
||||
"display_name": "挖掘反噬", "value": -5, "pool_value": -5, "round_index": 1}))
|
||||
Kit.check("战斗日志 mine_hit 来源行含「(危险格)」(u6 消费半——_format_row 生产路径)〔wa7〕",
|
||||
row_txt.contains("(危险格)"))
|
||||
|
||||
|
||||
# ⑦⑧ 已开危险格字形族(u7/u8/u9——BoardView rebuild 真实刷新路径+源 token 扫描)
|
||||
func _sweep_board_glyph() -> void:
|
||||
var board_generator = load("res://core/board_generator.gd").new()
|
||||
var b = board_generator.generate(1, 0, _mk_stream("board_gen", 4242), _db)
|
||||
var ae = load("res://core/action_economy.gd").new(_db)
|
||||
var ms = load("res://core/minesweeper_rules.gd").new(_db, ae)
|
||||
ms.install_board(b)
|
||||
ae.notify_round_start()
|
||||
# 邻接雷定位(挖掘面规则=须邻接英雄——novice 驱动开域至危险格入挖掘射程;上限 60 步防冻态)
|
||||
var mine_cell := Vector2i(-1, -1)
|
||||
var glow_steps := 0
|
||||
while glow_steps < 60:
|
||||
for c in b.neighbors8(ms.hero_pos()):
|
||||
if b.is_mine(c) and not ms.is_revealed(c):
|
||||
mine_cell = c
|
||||
break
|
||||
if mine_cell.x >= 0:
|
||||
break
|
||||
var act: Dictionary = AutoPlayer.novice_action(ms)
|
||||
if String(act.get("kind", "stop")) == "stop":
|
||||
break
|
||||
var op := String(act.get("kind", ""))
|
||||
if op == "seal":
|
||||
op = "seal_place"
|
||||
ms.settle_batch([{"action": op, "cell": act.get("cell")}])
|
||||
glow_steps += 1
|
||||
Kit.check("棋盘夹具含挖掘射程内未开危险格(wa8 前提——实测 %d 步)〔wa8〕" % glow_steps, mine_cell.x >= 0)
|
||||
if mine_cell.x >= 0:
|
||||
ms.settle_batch([{"action": "dig", "cell": mine_cell}]) # 挖开危险格(真实规则路径——受击开格)
|
||||
var view = load("res://presentation/views/board_view.gd").new()
|
||||
view.rebuild(b, ms) # theme_projection_test.gd:200 先例式直建(缺素材程序化回退态——fresh checkout 冒烟同纪律)
|
||||
var u: Node2D = view._cells[mine_cell]
|
||||
Kit.check("已开危险格 glyph==「危」(u7 换代)〔wa8〕", u.glyph == "危")
|
||||
Kit.check("已开危险格 plate==true(u9 牌载哨兵包含项随动)〔wa8〕", u.plate == true)
|
||||
Kit.check("已开危险格 glyph_color==RED_MINE(u7 墨色不随字形换代漂移)〔wa8〕",
|
||||
u.glyph_color == UiKit.RED_MINE)
|
||||
|
||||
|
||||
# ⑧⑩ 源 token 扫描(注释剥离=行首 # 判——契约 2 保留面不入域)
|
||||
func _sweep_token_scans() -> void:
|
||||
var board_src := FileAccess.get_file_as_string("res://presentation/views/board_view.gd")
|
||||
Kit.check("board_view.gd 源零 \"雷\" 字面量(u7/u8/u9 哨兵族统一钉住)〔wa8〕",
|
||||
board_src.count("\"雷\"") == 0)
|
||||
var orch_src := FileAccess.get_file_as_string("res://core/battle_orchestrator.gd")
|
||||
var orch_hits := 0
|
||||
for line in orch_src.split("\n"):
|
||||
if line.strip_edges().begins_with("#"):
|
||||
continue
|
||||
if line.contains("挖雷"):
|
||||
orch_hits += 1
|
||||
Kit.check("battle_orchestrator.gd 玩家面字符串字面量零「挖雷」(u13——注释保留面不入域)〔wa12〕",
|
||||
orch_hits == 0)
|
||||
|
||||
|
||||
func _first_label(node: Node) -> Label:
|
||||
for child in node.get_children():
|
||||
if child is Label:
|
||||
return child
|
||||
return null
|
||||
|
||||
|
||||
func _mk_stream(stream_name: String, scope: int) -> RandomNumberGenerator:
|
||||
# stream_name = 调用点自述标签(不参与派生),保留参数零改调用方(theme_projection_test 同构)
|
||||
var rg := RandomNumberGenerator.new()
|
||||
var svc = load("res://core/rng_service.gd").new()
|
||||
svc.set_master_seed(42)
|
||||
rg.seed = svc.derive_at(scope)
|
||||
return rg
|
||||
@@ -1,7 +1,8 @@
|
||||
# tests/unit/presentation/theme_projection_test.gd — 呈现投影与主题单元测试宿主
|
||||
# 断言面 = 十套(批 B 断言迁移自 smoke_all.gd,G11 施工组;十套按源编排序迁入):
|
||||
# 断言面 = 十一套(批 B 断言迁移自 smoke_all.gd,G11 施工组;十套按源编排序迁入+开场行后缀尾接协议扩段):
|
||||
# 未开格类型微光(作用集恒等/九型归组封闭/零玩法写入——board_view 微光数据面)
|
||||
# 战斗日志视图行格式化(行协议 9 类呈现层同步闸——真人试玩卡断 bug 回归)
|
||||
# 开场行后缀尾接协议(level_open_line 第五参布尔直控「(含面板加成)」尾接——签名零变)
|
||||
# UI 全局主题(main_theme.tres 挂载/类型覆盖/滑轨两段对比/退役实现零残留/中文字体防御)
|
||||
# UI 按钮五态矩阵(四工厂五态样式盒逐实例 override)
|
||||
# UI 全局纹理过滤(工程 Nearest+平滑渐变件 LINEAR 白名单+光柱 alpha 结构)
|
||||
@@ -42,6 +43,7 @@ func _init() -> void:
|
||||
# 套执行序沿源编排序(_run_core_smoke 序 + _smoke_meta 薄壳尾序)
|
||||
_smoke_type_glow()
|
||||
_smoke_battle_log_view()
|
||||
_smoke_level_open_line()
|
||||
_smoke_global_theme()
|
||||
_smoke_button_five_states()
|
||||
_smoke_texture_filter()
|
||||
@@ -420,6 +422,19 @@ func _smoke_battle_log_view() -> void:
|
||||
view.parsed_text().length() > before)
|
||||
|
||||
|
||||
# ---- 开场行后缀尾接协议(迭代36 wc1 静态半——level_open_line 第五参布尔直控尾接,签名零变;
|
||||
# 该函数此前零既有断言,尾接行为由此钉住)----
|
||||
func _smoke_level_open_line() -> void:
|
||||
var NarratorScript := load("res://presentation/battle_narrator.gd")
|
||||
Kit.check("开场行 boosted=true 尾接「(含面板加成)」〔wc1〕",
|
||||
String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("(含面板加成)"))
|
||||
Kit.check("开场行 boosted=false 零后缀(白板局不带)〔wc1〕",
|
||||
not String(NarratorScript.level_open_line("第一层", 42, 5, 30, false)).contains("(含面板加成)"))
|
||||
Kit.check("开场行种子/两值带入不受后缀位影响(数值带入回归)〔wc1〕",
|
||||
String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("种子 42")
|
||||
and String(NarratorScript.level_open_line("第一层", 42, 5, 30, true)).contains("攻击 5 / 生命 30"))
|
||||
|
||||
|
||||
# ---- UI 全局主题冒烟(需求卡片 §7 验收清单 V1-V6)----
|
||||
# V1 挂载覆盖 / V2 滑轨两段 / V3 预盖件运行时证词 / V4 旧形态零残留 /
|
||||
# V5 回归(本冒烟全绿即回归网)/ V6 中文字体防御(挂主题后 default_font 顶掉 custom_font 也不丢字形)
|
||||
|
||||
@@ -17,6 +17,7 @@ func _init() -> void:
|
||||
if f != null:
|
||||
Kit.check("中文字形在集(攻/雷/旗/封)", f.has_char("攻".unicode_at(0)) and f.has_char("雷".unicode_at(0)) \
|
||||
and f.has_char("旗".unicode_at(0)) and f.has_char("封".unicode_at(0)))
|
||||
Kit.check("中文字形在集(危——已开危险格字形换代前置,迭代36 u12/wa9)", f.has_char("危".unicode_at(0)))
|
||||
Kit.check("ASCII/数字字形在集(A/0/%)", f.has_char("A".unicode_at(0)) and f.has_char("0".unicode_at(0)) and f.has_char("%".unicode_at(0)))
|
||||
var sz := 18
|
||||
var w_cn: float = f.get_string_size("战斗胜利", HORIZONTAL_ALIGNMENT_LEFT, -1, sz).x
|
||||
|
||||
Reference in new issue
Block a user