# -*- coding: utf-8 -*- """ 关卡怪物成长 × 永久成长 对齿模型(game-balancer 工作流 step 2-3) 链条模型:逐节点 击杀轮=t_kill=敌总血/我方DPS;承伤/轮=实测口径;池血衰减+战斗治疗; 裕度 m=进场池血/承伤每轮 − t_kill → 经验分段映射胜率(用第 6 轮 MC 实测校准,±10~15pp)。 阶段 S0-S3 = 永久锻造累计(atk+ / hp+ / ac+),ac 每点 ≈ 承伤 -7%(近似,标 provisional)。 输出:阶段×关卡 到达boss率/通关率 矩阵(v1=第6轮现役怪=校准组;v2=阶段拔高提案=设计组)。 """ DPS_DIG = {1: 5.9, 2: 7.1, 3: 6.3} # 实测输出/轮 − 主角免费攻2(第6轮 normal) HEAL_K = 0.85 # 治疗每战 ≈ 0.85×击杀轮(第6轮实测拟合) # (关, 节点, 数量期望, 单位血v1, 单位血v2, atk v1, atk v2, 承伤/轮v1实测, boss) NODES = [ (1, 0, 1.5, 8, 8, 2, 2, 0.79, False), (1, 1, 2.5, 4, 4, 2, 2, 0.65, False), (1, 2, 1.0, 50, 50, 2, 2, 1.09, False), (1, 3, 2.5, 14, 14, 2, 2, 1.94, False), (1, 4, 1.0, 72, 72, 2, 2, 1.12, True), (2, 0, 1.0, 45, 50, 2, 2, 1.08, False), (2, 1, 2.5, 18, 20, 2, 2, 1.99, False), (2, 4, 2.0, 20, 22, 2, 2, 1.80, False), (2, 5, 1.0, 68, 85, 2, 3, 1.32, False), (2, 6, 2.5, 18, 20, 1, 1, 1.62, False), (2, 7, 2.5, 18, 20, 2, 2, 1.80, False), (2, 9, 1.0, 80,105, 2, 3, 1.32, True), (3, 0, 1.0, 50, 60, 2, 3, 1.03, False), (3, 1, 2.0, 25, 28, 2, 3, 1.53, False), (3, 4, 2.5, 20, 22, 2, 3, 1.90, False), (3, 5, 1.0, 76, 95, 2, 3, 1.40, False), (3, 6, 2.5, 20, 22, 2, 3, 2.15, False), (3, 7, 2.5, 20, 22, 2, 3, 2.15, False), (3, 9, 1.0, 92,125, 2, 3, 1.06, True), ] # 缺实测的行用同原型插值填的(2,4)/(2,7)/(3,4)/(3,5) 按双单位/单体原型估。 def win(m): if m <= -5: return 0.35 if m <= -3: return 0.48 if m <= -1.5: return 0.60 if m <= 0: return 0.68 if m <= 2: return 0.80 if m <= 5: return 0.90 if m <= 9: return 0.95 return 0.97 def run_level(L, atk_up, hp_up, ac_up, ver, pool0, bonus, verbose=False): dps = DPS_DIG[L] + 2 + atk_up fac = 1.0 - 0.07 * ac_up pool = pool0 reach = 1.0 for (l, d, u, h1, h2, a1, a2, intake1, boss) in NODES: if l != L: continue hp = u * (h2 if ver == 2 else h1) atk = (a2 if ver == 2 else a1) intake = intake1 * (atk / a1) * fac if ver == 2: intake *= 1.0 # v2 承伤已按 atk 比例走上面一行 t_kill = hp / dps t_live = pool / intake m = t_live - t_kill p = win(m) if verbose: print(f" L{L} d{d}{' BOSS' if boss else '':>5} hp={hp:5.0f} dps={dps:4.1f} tkill={t_kill:4.1f} intake={intake:4.2f} tlive={t_live:4.1f} m={m:+5.1f} p={p:.2f}") yield_p = reach * p # boss 到达率在进入该点时即定格 if boss and verbose is not None: boss_reach = reach pool -= t_kill * intake * (0.5 + 0.5 * p) # 败北也吃部分伤(平均 ~50%*tkill 承伤) pool += HEAL_K * t_kill * p # 治疗只在胜局兑现大头 reach = yield_p return boss_reach, reach def stage_curve(atk_up, hp_up, ac_up, ver, bonus=10, tag=""): out = {} pool = 20 + hp_up for L in (1, 2, 3): poolL = pool + bonus * (L - 1) r, c = run_level(L, atk_up, hp_up, ac_up, ver, poolL, bonus) out[L] = (r, c, poolL) pool = pool + bonus if c > 0.001 else pool # 通关才拿关间奖励 print(f"{tag} atk+{atk_up} hp+{hp_up} ac+{ac_up}: " f"L1 达boss -/通关 {out[1][1]*100:4.1f}% | " f"L2 达boss {out[2][0]*100:4.1f}% 通关 {out[2][1]*100:4.1f}% | " f"L3 达boss {out[3][0]*100:4.1f}% 通关 {out[3][1]*100:4.1f}%") return out print("=== 校准组 v1(第6轮现役怪,模型 vs 实测)===") print("实测: L1通关 normal49.7/perfect85 | L2条件通过53/77.6 | L2 boss胜率65/97 | L3 boss胜率47/67 | 全通关 10/39.7") stage_curve(0, 0, 0, 1, tag="S0 fresh") print() print("=== 设计组 v2(阶段拔高提案)===") stage_curve(0, 0, 0, 2, tag="S0 fresh ") stage_curve(2, 6, 1, 2, tag="S1 ≈5次L1刷 ") stage_curve(4, 12, 2, 2, tag="S2 ≈再刷L2 ") stage_curve(6, 18, 3, 2, tag="S3 毕业 ")