merge: U2返工批落地——C1两刀终态+AC v1硬梯度重投+节点图池两规则重生成(模板0随重排)+完美L1杠杆提案+终态双窗读数(普通L2 10.6/13.6%完美L2 22/32.3%越带待批点丙);冒烟576/0五探针PASS doc三闸零新增 熵增闸PASS(design/qa图像白名单收编)

This commit is contained in:
DKChan committed 2026-09-29 05:22:27 +08:00
commit 910d74cc89
32 files changed
+1094 -78

No files matched your search

+3 -1
View File
@@ -26,8 +26,10 @@ TOP_DIRS = {"archive", "artwork", "design", "game", "sim-data", "tools"}
ROOT_FILES = {"CLAUDE.md", "active.md", "roadmap.md", "stage.txt", "review-mode.txt",
".gitignore", ".zcodeignore"}
# 3) 图像允许目录(相对路径前缀;archive/ 为归档 zip 不扫)
# design/qa/ 收编(迭代 5 返工批 2026-09-29——U2 目检预览图/QA 呈现产物归位,commit 留痕)
IMAGE_EXTS = {".png", ".jpg", ".jpeg", ".webp", ".gif", ".svg", ".pxo", ".psd", ".bmp"}
IMAGE_PREFIXES = ("artwork/", "game/assets/", "design/art/references/", "design/dev/architecture/")
IMAGE_PREFIXES = ("artwork/", "game/assets/", "design/art/references/", "design/dev/architecture/",
"design/qa/")
# 4) 退役路径(目录或文件任一再现即 FAIL)
RETIRED = ["production", "docs", "tests", "qa-data",
"design/art/candidates", "production/mockups",
+73 -33
View File
@@ -2,7 +2,9 @@
# -*- coding: utf-8 -*-
"""T5 骨架池生成器(M-3 迭代 5——一次性内容批工具,生成 game/data/tables/level.tres 模板池)。
15 张骨架 = 3 关 × 5(拍板点④),模板 0 = 现行固定图(回滚档成员)。
15 张骨架 = 3 关 × 5(拍板点④)。U2 目检返工(2026-09-29)两条新规则:
① L1 单链前三位纯战斗(奖励/休整禁入前三——用户目检裁决);
② L2/L3 网状图 BFS 同深度层节点数上限 5,新池应用足宽度(每张最大层宽 ≥4——分支加宽)。
约束:战斗/Boss node_depth = 遭遇表行;图形态 id = node_depth → L2/L3 战斗 ∈ {0,1,4,5,6,7}、Boss=9;
L1 图形态两不可全(Boss 须最大 id vs 深度 4)→ L1 单链排列变体(战斗深度序单调)。
商店房每关恰 1、Boss 前必经位(L1 设计态 = 零商店——商店房批教学期修订面)。
@@ -32,54 +34,77 @@ def graph(spec):
return nodes
# 前三位纯战斗(U2 规则①)——位 4-6 = {战斗3, 奖励, 休整} 排列变体,末位 Boss
L1_TEMPLATES = [
("地精洞窟·主线洞道(现行)", chain([("battle", 0), ("battle", 1), ("reward", None),
("battle", 2), ("battle", 3), ("rest", None), ("boss", 4)])),
("地精洞窟·休整前移", chain([("battle", 0), ("battle", 1), ("rest", None),
("battle", 2), ("reward", None), ("battle", 3), ("boss", 4)])),
("地精洞窟·先赏后战", chain([("battle", 0), ("reward", None), ("battle", 1), ("rest", None),
("battle", 2), ("battle", 3), ("boss", 4)])),
("地精洞窟·连战直入", chain([("battle", 0), ("battle", 1), ("reward", None), ("rest", None),
("battle", 2), ("battle", 3), ("boss", 4)])),
("地精洞窟·缓入长坡", chain([("battle", 0), ("rest", None), ("battle", 1), ("reward", None),
("battle", 2), ("battle", 3), ("boss", 4)])),
("地精洞窟·主线洞道(现行)", chain([("battle", 0), ("battle", 1), ("battle", 2), ("battle", 3),
("reward", None), ("rest", None), ("boss", 4)])),
("地精洞窟·先赏后整", chain([("battle", 0), ("battle", 1), ("battle", 2), ("reward", None),
("rest", None), ("battle", 3), ("boss", 4)])),
("地精洞窟·先整后赏", chain([("battle", 0), ("battle", 1), ("battle", 2), ("rest", None),
("reward", None), ("battle", 3), ("boss", 4)])),
("地精洞窟·赏战整", chain([("battle", 0), ("battle", 1), ("battle", 2), ("reward", None),
("battle", 3), ("rest", None), ("boss", 4)])),
("地精洞窟·整战赏", chain([("battle", 0), ("battle", 1), ("battle", 2), ("rest", None),
("battle", 3), ("reward", None), ("boss", 4)])),
]
def w0():
return graph({0: ("battle", 0, [1, 2]), 1: ("battle", 1, [3, 4]), 2: ("reward", 2, [4, 5]),
3: ("rest", 3, [6]), 4: ("battle", 4, [6, 7]), 5: ("battle", 5, [7]),
return graph({0: ("battle", 0, [1, 2, 3, 4, 5]), 1: ("battle", 1, [6]), 2: ("reward", 2, [6, 7]),
3: ("rest", 3, [6]), 4: ("battle", 4, [7]), 5: ("battle", 5, [6, 7]),
6: ("battle", 6, [8]), 7: ("battle", 7, [8]), 8: ("shop", 8, [9]), 9: ("boss", 9, [])})
def w1():
return graph({0: ("battle", 0, [1, 2]), 1: ("battle", 1, [3, 4]), 2: ("reward", 2, [4]),
3: ("rest", 3, [5]), 4: ("battle", 4, [5, 6]), 5: ("battle", 5, [7]),
return graph({0: ("battle", 0, [1, 2, 3, 4]), 1: ("battle", 1, [5]), 2: ("reward", 2, [5, 6]),
3: ("rest", 3, [6, 7]), 4: ("battle", 4, [7]), 5: ("battle", 5, [8]),
6: ("battle", 6, [8]), 7: ("battle", 7, [8]), 8: ("shop", 8, [9]), 9: ("boss", 9, [])})
def w2():
return graph({0: ("battle", 0, [1, 2]), 1: ("battle", 1, [4]), 2: ("reward", 2, [3, 4]),
3: ("rest", 3, [6]), 4: ("battle", 4, [5, 6]), 5: ("battle", 5, [7]),
6: ("battle", 6, [7]), 7: ("battle", 7, [8]), 8: ("shop", 8, [9]), 9: ("boss", 9, [])})
return graph({0: ("battle", 0, [1, 2]), 1: ("battle", 1, [3, 4, 5, 6]), 2: ("reward", 2, [3, 4]),
3: ("rest", 3, [7]), 4: ("battle", 4, [7]), 5: ("battle", 5, [7]), 6: ("battle", 6, [7]),
7: ("battle", 7, [8]), 8: ("shop", 8, [9]), 9: ("boss", 9, [])})
def w3():
return graph({0: ("battle", 0, [1, 2]), 1: ("battle", 1, [2, 4]), 2: ("reward", 2, [3]),
3: ("rest", 3, [6]), 4: ("battle", 4, [5, 6]), 5: ("battle", 5, [7]),
return graph({0: ("battle", 0, [1, 3, 4, 5]), 1: ("battle", 1, [2, 6]), 2: ("reward", 2, [7]),
3: ("rest", 3, [6]), 4: ("battle", 4, [6, 7]), 5: ("battle", 5, [7]),
6: ("battle", 6, [8]), 7: ("battle", 7, [8]), 8: ("shop", 8, [9]), 9: ("boss", 9, [])})
def w4():
return graph({0: ("battle", 0, [1, 2]), 1: ("battle", 1, [3]), 2: ("reward", 2, [3, 4]),
3: ("rest", 3, [4, 5]), 4: ("battle", 4, [6]), 5: ("battle", 5, [6]),
6: ("battle", 6, [7]), 7: ("battle", 7, [8]), 8: ("shop", 8, [9]), 9: ("boss", 9, [])})
return graph({0: ("battle", 0, [1, 2]), 1: ("battle", 1, [4, 5, 6]), 2: ("reward", 2, [3, 4, 5]),
3: ("rest", 3, [6]), 4: ("battle", 4, [6, 7]), 5: ("battle", 5, [7]),
6: ("battle", 6, [8]), 7: ("battle", 7, [8]), 8: ("shop", 8, [9]), 9: ("boss", 9, [])})
L2_WIRINGS = [("幽暗地域·四岔环廊(现行)", w0()), ("幽暗地域·奖励窄门", w1()),
("幽暗地域·直入深层", w2()), ("幽暗地域·休整远路", w3()), ("幽暗地域·双线归束", w4())]
L3_WIRINGS = [("灰矮人矿城·主竖井(现行)", w0()), ("灰矮人矿城·奖励窄门", w1()),
("灰矮人矿城·直入深层", w2()), ("灰矮人矿城·休整远路", w3()), ("灰矮人矿城·双线归束", w4())]
L2_WIRINGS = [("幽暗地域·五岔环廊(现行)", w0()), ("幽暗地域·四岔宽门", w1()),
("幽暗地域·深层四岔", w2()), ("幽暗地域·宽门赏后置", w3()), ("幽暗地域·双干汇流", w4())]
L3_WIRINGS = [("灰矮人矿城·五岔主竖井(现行)", w0()), ("灰矮人矿城·四岔宽门", w1()),
("灰矮人矿城·深层四岔", w2()), ("灰矮人矿城·宽门赏后置", w3()), ("灰矮人矿城·双干汇流", w4())]
def bfs_widths(nodes):
"""BFS 分层(图形态)→ 各层宽度列表。"""
ids = [n["node_depth"] for n in nodes]
adj = {n["node_depth"]: list(n.get("next", [])) for n in nodes}
inbound = set()
for nxt in adj.values():
inbound |= set(nxt)
entry = [i for i in ids if i not in inbound][0]
layer = {entry: 0}
frontier = [entry]
while frontier:
cur = frontier.pop(0)
for t in adj[cur]:
if t not in layer:
layer[t] = layer[cur] + 1
frontier.append(t)
widths = {}
for i in ids:
widths[layer[i]] = widths.get(layer[i], 0) + 1
return [widths[d] for d in sorted(widths)]
def validate(name, nodes, battles, boss_depth, has_shop):
@@ -117,6 +142,17 @@ def validate(name, nodes, battles, boss_depth, has_shop):
frontier += list(adj.get(cur, []))
if reach != set(ids):
errs.append("存在不可达节点: %s" % (set(ids) - reach))
# U2 规则②:BFS 同层 ≤5,且最大层宽 ≥4(分支应用足)
ws = bfs_widths(nodes)
if max(ws) > 5:
errs.append("层宽越上限 5: %s" % ws)
if max(ws) < 4:
errs.append("分支不足(最大层宽 %d < 4——U2 加宽裁决)" % max(ws))
else:
# U2 规则①:单链前三位纯战斗
for i in range(3):
if nodes[i]["type"] != "battle":
errs.append("第 %d 位非战斗(前三位纯战斗)" % (i + 1))
bt = sorted(n["node_depth"] for n in nodes if n["type"] in ("battle", "boss"))
if bt != sorted(battles + [boss_depth]):
errs.append("战斗深度集合不符: %s" % bt)
@@ -140,7 +176,7 @@ for name, nodes in L1_TEMPLATES:
all_ok &= not e
for name, nodes in L2_WIRINGS + L3_WIRINGS:
e = validate(name, nodes, L2_BATTLES, 9, True)
print(("PASS" if not e else "FAIL"), name, e)
print(("PASS" if not e else "FAIL"), name, "层宽=%s" % bfs_widths(nodes), e)
all_ok &= not e
print("ALL OK" if all_ok else "HAS FAILURES")
if not all_ok:
@@ -186,13 +222,17 @@ footer = (
"\n]\n"
"\n"
"; 关卡节点图生成 v0.4 台阶一内容批(M-3 迭代 5 T5,2026-09-28——15 张骨架 = 3 关 × 5,拍板点④):\n"
"; 模板 0 = 现行固定图(回滚档成员——首次冒险脚本/池缩 N=1 时逐位等价迁移前行为);\n"
"; L1 五模板 = 单链排列变体(图形态两不可全:Boss 须最大编号 vs Boss 遭遇深度 4——战斗深度序单调\n"
"; 保持难度坡,变化面 = 奖励/恢复位次);L2/L3 五模板 = 网状图变体(战斗节点编号恒 ∈ 遭遇表行集\n"
"; {0,1,4,5,6,7}、Boss 9 最大编号、商店房 8→Boss 必经位承袭;遭遇表按编号共用——零新增敌人数值)。\n"
"; L2/L3 网状图约束(承袭):战斗节点编号恒 ∈ 遭遇表行集 {0,1,4,5,6,7}、Boss 9 最大编号、\n"
"; 商店房 8→Boss 必经位承袭;遭遇表按编号共用——零新增敌人数值。L1 五模板 = 单链排列变体\n"
"; (战斗深度序单调保难度坡,变化面 = 奖励/恢复位次)。\n"
"; 池内全模板加载期校验(level_table.gd validate + config_db 跨表校验模板感知);\n"
"; 行为读 LevelRunner._resolve_template_row(node_map 标签恰一 scope 抽签 / template_pick 强制)。\n"
"; 生成器 = tools/t5_build_templates.py(生成前自校验,一次性内容批工具随批入库留档)。\n")
"; 生成器 = tools/t5_build_templates.py(生成前自校验,一次性内容批工具随批入库留档)。\n"
"; U2 目检返工(M-3 迭代 5 返工批,2026-09-29——U2 目检 15/15 不过两规则缺口,全池重生成):\n"
"; ① L1 奖励/休整禁入前三位(用户目检裁决)——五链全部前三位纯战斗,位 4-6 = {战斗3,奖励,休整} 排列;\n"
"; ② L2/L3 BFS 同深度层上限 5 且应用足(每张最大层宽 4-5,旧池层宽最大 3 被否);模板 0 一并重排\n"
"; (待批点甲按推荐=随新规则重生成——首次冒险/钉固断言期望随新图更新;模板 0 名保持「(现行)」后缀=新现行图锚)。\n"
"; 加载校验两规则同落 level_table.gd validate(单链前三纯战斗/图形态层宽 ≤5)。\n")
with open("game/data/tables/level.tres", "w", encoding="utf-8", newline="\n") as f:
f.write(header + ",\n".join(rows) + footer)