#!/usr/bin/env python3 # -*- coding: utf-8 -*- """清图支配性对账重算工具(行动经济 条款⑤ · registry clause5_dominance)。 判式权威 = design/registry/entities.yaml clause5_dominance(挖穿残余池计价): 主判式 Δ_clear = [R_res + C_eff] − [X_res + Δr × s_ref] ≥ 0 保守地板 C_eff(min) ≥ X_res + Δr × s_ref E[踩雷] = |M| × n_s ÷ (n_s + 1) (均匀交错模型) n_s = (1 − ι) × |S| (域守卫 n_s < 1 ⇒ 不评估) R_res = n_s × E_dig;X_res = E[踩雷] × V_mine;Δr = ⌈(n_s + E[踩雷]) ÷ AP_r⌉ s_ref = D_ref;停手侧 RAP 机会收益按零计价(显式假设)。 本工具 2026-09-19 随对账重跑批建立,是难度曲线调参批的常设重跑入口: 所有输入可经命令行覆盖(--d-ref --c-clear --ap-r --iota --m-amb --u ...), 重跑时按当期 .tres 行值更新默认值即可,公式本体不动。 单雷代价 / 单格收益的当量换算严格走 战斗结算「效果档位对照表」单一口径: flat 类 E = 表值;percent 类 E = |层数×行值|÷100 × D_ref(每结算每层); AC 轴换算 = AC 点数 × 5pp(d20 线性)× D_ref(假设登记,见审计报告)。 2026-09-19 起极性矩阵下踩雷惩罚按格型路由(不再固定伏击),故 V_mine 双口径: 甲 = 注册模型连续口径 V_mine = unit_count × m_amb(m_amb = 伏击行 magnitude); 乙 = 现行矩阵加权口径 V_mine = 负向字典按 67 权重池加权(主流读数)。 """ import argparse import math # ============ 现行值链(2026-09-19 快照,出处见各注释;重跑批按当期 .tres 更新) ============ D_REF = 4 # settlement.tres equivalence_ref_damage(2026-09-17 压缩批 12→4) P_PERFECT = 200 # settlement.tres(percent,÷100 = ×2 双份交付) C_MIN, C_MAX = 8, 18 # reward.tres clear_blast power_min/max;期望口径 = 中点 13 AP_R = 6 # action_economy.tres ap_per_round(2026-09-16 压速批 8→6) DIG_COST = 1 # action_economy.tres dig_ap_cost IOTA = 0.88 # board_gen.tres inferability_target(判式 ι 代理) # 效果行值(status_effects.tres,2026-09-19 快照) ATTACK_UP_PCT = 50 # 增伤 +50%,duration 1,hero 侧 AC_UP_POINT = 1 # 护甲强化 +1 AC,duration 1 WEAKEN_PCT = 65 # 削弱 −65%(有效拍 1:duration 2 先兑付后衰减) ENRAGE_PCT = 25 # 暴走 +25%,enemy 侧 side-wide SAPPED_PCT = 25 # 乏力 −25%,hero 侧 # 【2026-09-20 八型批口径注记】伏击机制退役,blast 负向现况 = 警觉(敌方 AC +1,掷点折扣分布型惩罚)—— # 本脚本的伏击暴露当量模型(AMBUSH_MAG/AMBUSH_STACKS)转为历史口径,仅用于旧读数复算; # 新口径(掷点折扣期望建模)归曲线调参批重立后再改模型。 AMBUSH_MAG = 1 # 历史口径:伏击 +1 flat/层(2026-09-17 压缩批 3→1) AMBUSH_STACKS = 2 # reward.tres ambush_double stacks(每雷伏击层数) OFF_GUARD_AC = 2 # 失衡 AC −2(2026-09-18 换装) # 直伤/群伤 flat 值(reward.tres,2026-09-17 ÷3 后) SPARK_AOE = 1 # 爆裂粉尘(全体存活敌) HEAL_MINOR = 1 # 急救敷料 HEAL_BACKLASH = 1 # 反噬震荡(主角直伤) PIERCE_STRIKE = 2 # 穿刺弹(单目标克制直伤,必中全额) MAGIC_BOLT = 2 # 魔法矢(同上) PIERCE_SNARE = 2 # 穿刺陷阱(主角直伤) MAGIC_RECOIL = 2 # 魔法反噬(主角直伤) # 甲效矩阵(settlement.tres,加法核点数):基础值 + 点数,damage_floor=1 ARMOR_EFFECT = { # attack_type → {armor_type: 点数};切片 L1 全轻甲 / L2 除 Boss 全轻甲 "pierce": {"light": -1, "ward": 1, "heavy": 0}, "magic": {"light": 0, "ward": -1, "heavy": 1}, "normal": {"light": 0, "ward": 1, "heavy": -1}, } # 格面资源池正向权重(reward.tres,2026-09-18 伤害道具批后,合计 67) # 类型 → (权重);负向行 weight=0 不参与摇号,类型分布 = 正向权重 POOL_WEIGHTS = {"attack": 14, "defense": 11, "blast": 16, "heal": 2, "weaken": 8, "pierce": 8, "magic": 8} # 板形(|M| 幸存雷 / |S| 安全格)双口径 # 名义 = density×(W×H−9) 初布值(2026-09-14 重算批参考板形口径,连续性参照) # 实测 = smoke/board_stat_probe.gd 200 样本/行均值("先布后删"落地值,主流读数) BOARDS = { "L1前段·名义(10x10)": {"M": 23, "S": 77}, "L1后段·名义(12x12)": {"M": 34, "S": 110}, "L2·名义(12x12)": {"M": 34, "S": 110}, "L1前段·实测(10x10)": {"M": 12.91, "S": 87.09}, "L1后段·实测(12x12)": {"M": 22.61, "S": 121.39}, "L2·实测(12x12)": {"M": 22.39, "S": 121.61}, } def e_dig(u: float, d_ref: float, aoe_per_unit: bool = True) -> float: """单安全格期望收益(当量),格子池 67 权重加权。 u = 敌方单位数。hero 侧单目标效果不随 u 缩放(主角每轮出手一次); enemy 侧 side-wide 效果(ac_up 承伤面 / spark_aoe 群伤 / weaken 全体减伤)随 u 缩放。 """ w = POOL_WEIGHTS total = sum(w.values()) attack = w["attack"] * ATTACK_UP_PCT / 100 * d_ref # 主角下一拍增伤 ac_up = w["defense"] * AC_UP_POINT * 0.05 * d_ref * u # 每个来敌拍 −5pp 命中 spark = w["blast"] * (SPARK_AOE * u if aoe_per_unit else SPARK_AOE) # 全体存活敌 heal = w["heal"] * HEAL_MINOR weaken = w["weaken"] * WEAKEN_PCT / 100 * d_ref * u # 全体敌拍 ×0.35 pierce = w["pierce"] * max(1, PIERCE_STRIKE + ARMOR_EFFECT["pierce"]["light"]) # 轻甲口径 magic = w["magic"] * max(1, MAGIC_BOLT + ARMOR_EFFECT["magic"]["light"]) return (attack + ac_up + spark + heal + weaken + pierce + magic) / total def v_mine_a(u: float, m_amb: float) -> float: """口径甲:注册模型连续口径 V_mine = unit_count × m_amb(registry 公式字面执行)。""" return u * m_amb def v_mine_b(u: float, d_ref: float) -> float: """口径乙:现行极性矩阵加权口径——踩雷兑付 = 该格类型负向行,按 67 权重池加权。 hero 侧固定(直伤三类 heal_backlash/snare/recoil + 乏力 sapped); enemy 侧 side-wide(enrage 每敌拍 / off_guard 每敌拍命中上浮 / ambush_double 每敌拍 +2 flat)随 u 缩放。 """ w = POOL_WEIGHTS total = sum(w.values()) enrage = w["attack"] * ENRAGE_PCT / 100 * d_ref * u off_guard = w["defense"] * OFF_GUARD_AC * 0.05 * d_ref * u # AC−2 → 每敌拍 +10pp 命中 backlash = w["heal"] * HEAL_BACKLASH ambush = w["blast"] * AMBUSH_STACKS * AMBUSH_MAG * u sapped = w["weaken"] * SAPPED_PCT / 100 * d_ref # 主角下一拍 −25% snare = w["pierce"] * PIERCE_SNARE recoil = w["magic"] * MAGIC_RECOIL return (enrage + off_guard + backlash + ambush + sapped + snare + recoil) / total def audit_shape(name: str, m: float, s: float, u: float, c_clear: float, d_ref: float, ap_r: int, iota: float, v_mine: float, e_dig: float, dig_cost: int) -> dict: """单板形单语境全量计算,返回判式各腿与判定。""" n_s = (1 - iota) * s if n_s < 1: return {"name": name, "skip": True} e_mine = m * n_s / (n_s + 1) r_res = n_s * e_dig x_res = e_mine * v_mine dr = math.ceil((n_s + e_mine * dig_cost) / ap_r) c_eff_normal = c_clear c_eff_perfect = c_clear * P_PERFECT / 100 d_normal = (r_res + c_eff_normal) - (x_res + dr * d_ref) d_perfect = (r_res + c_eff_perfect) - (x_res + dr * d_ref) floor_req = x_res + dr * d_ref # 保守地板需求(对 C_eff) return { "name": name, "skip": False, "n_s": n_s, "e_mine": e_mine, "r_res": r_res, "x_res": x_res, "dr": dr, "dr_cost": dr * d_ref, "floor_req": floor_req, "gap_normal": floor_req - c_eff_normal, "gap_perfect": floor_req - c_eff_perfect, "d_normal": d_normal, "d_perfect": d_perfect, } def main() -> None: ap = argparse.ArgumentParser(description="清图支配性(条款⑤)对账重算") ap.add_argument("--d-ref", type=float, default=D_REF) ap.add_argument("--c-clear", type=float, default=None, help="清图奖励当量 C(默认 = (C_MIN+C_MAX)/2 = 13;传 8 得保守地板口径)") ap.add_argument("--ap-r", type=int, default=AP_R) ap.add_argument("--iota", type=float, default=IOTA) ap.add_argument("--m-amb", type=float, default=float(AMBUSH_MAG), help="口径甲的伏击行 magnitude(默认 1;传 2 = ambush_double 双层口径)") ap.add_argument("--e-dig-discount", type=float, default=1.0, help="E_dig 实现率折减(legacy 敏感性口径传 0.6)") args = ap.parse_args() c_clear = args.c_clear if args.c_clear is not None else (C_MIN + C_MAX) / 2 print(f"现行值链快照:D_ref={args.d_ref:g} C={c_clear:g}(min {C_MIN}/max {C_MAX}) " f"AP_r={args.ap_r} ι={args.iota} p_perfect={P_PERFECT} RAP零价假设照旧") print(f"E_dig(67权重池加权当量): u=1 {e_dig(1, args.d_ref):.3f} · u=2 {e_dig(2, args.d_ref):.3f} · " f"u=3 {e_dig(3, args.d_ref):.3f}(折减 ×{args.e_dig_discount:g} 后同乘)") print(f"V_mine 口径甲(u×m_amb, m_amb={args.m_amb:g}): u=1 {v_mine_a(1, args.m_amb):.3f} · " f"u=2 {v_mine_a(2, args.m_amb):.3f} · u=3 {v_mine_a(3, args.m_amb):.3f}") print(f"V_mine 口径乙(极性矩阵加权): u=1 {v_mine_b(1, args.d_ref):.3f} · " f"u=2 {v_mine_b(2, args.d_ref):.3f} · u=3 {v_mine_b(3, args.d_ref):.3f}") print() for vm_label, vm_fn in [("口径甲(注册模型 V_mine=u×m_amb)", lambda u: v_mine_a(u, args.m_amb)), ("口径乙(现行矩阵加权 V_mine)", lambda u: v_mine_b(u, args.d_ref))]: print(f"### 主判式 · {vm_label} · C={c_clear:g}") print("| 板形 | u | n_s | E[踩雷] | R_res | X_res | Δr(代价) | Δ_clear 非完美 | Δ_clear 完美 | 判定 |") print("|---|---|---|---|---|---|---|---|---|---|") for bname, b in BOARDS.items(): for u in (1, 2, 3): ed = e_dig(u, args.d_ref) * args.e_dig_discount r = audit_shape(bname, b["M"], b["S"], u, c_clear, args.d_ref, args.ap_r, args.iota, vm_fn(u), ed, DIG_COST) if r["skip"]: continue verdict = "✓" if r["d_perfect"] >= 0 and r["d_normal"] >= 0 else ( "完美✓" if r["d_perfect"] >= 0 else "✗") print(f"| {bname} | {u} | {r['n_s']:.2f} | {r['e_mine']:.2f} | {r['r_res']:.1f} | " f"{r['x_res']:.1f} | {r['dr']}({r['dr_cost']:.0f}) | {r['d_normal']:+.1f} | " f"{r['d_perfect']:+.1f} | {verdict} |") print() print("### 保守地板(C_eff(min)=C_MIN)需求与缺口 · 口径乙") print("| 板形 | u | 地板需求 X_res+Δr×s_ref | 缺口(对 min) | 缺口(对完美 ×2) |") print("|---|---|---|---|---|") for bname, b in BOARDS.items(): for u in (1, 3): ed = e_dig(u, args.d_ref) * args.e_dig_discount r = audit_shape(bname, b["M"], b["S"], u, float(C_MIN), args.d_ref, args.ap_r, args.iota, v_mine_b(u, args.d_ref), ed, DIG_COST) if r["skip"]: continue print(f"| {bname} | {u} | {r['floor_req']:.1f} | +{r['gap_normal']:.1f} | +{r['gap_perfect']:.1f} |") print() # 护栏 B(防钓鱼——退化板刷清图奖励上界):⌈(|S|min − |R0|max) ÷ AP_r⌉ × s_ref ÷ 2 # |S|min = min_safe_count 当期行集(50/60);|R0|max = 20 经验值(无登记供给方) print("### 护栏 B 复核(防钓鱼上界,D_ref 口径)") for s_min in (50, 60): ub = math.ceil((s_min - 20) / args.ap_r) * args.d_ref / 2 print(f"|S|min={s_min}: 上界 = ⌈({s_min}−20)/{args.ap_r}⌉×{args.d_ref:g}÷2 = {ub:g}" f" → C={c_clear:g} {'✓' if c_clear <= ub else '越 %.1f×' % (c_clear / ub)}" f" / 完美 C_eff={c_clear * P_PERFECT / 100:g} " f"{'✓' if c_clear * P_PERFECT / 100 <= ub else '越 %.1f×' % (c_clear * P_PERFECT / 100 / ub)}") if __name__ == "__main__": main()