fix(battle): 地图伤害账殿后批(案C 2026-10-06 用户裁——「主角先手攻击一次」歧义质询触发)——①结算顺序定死=①授予段兑非伤害账(资源/增益/治疗/行动点/GP/警觉,伤害形态单据暂存不兑)→③战斗段「主角先基础攻击→敌人按生成序逐个还手→地图伤害账殿后」→④衰减→⑤判定;②切片=battle_orchestrator 暂存闸 _defer_board_damage/_deferred_board+_submit 案C分流(sync同闸——清图批一致延后)+_outcome_of(暂存单按「将兑付」回报——完美第二份依据开单时点事实)+授予段四处直提改走闸+战斗段末补提交块(主角死于怪物→暂存单整体不兑逐单留「未生效(主角已倒下)」行 forfeit=hero_down);③文档=战斗结算 v0.26(五段表①③行/授予段节/兑付形态表/结账时机双模式/战斗段节/P0闭环/三分量遗留顺手清+三处普通分量改基础分量)+敌人系统(P0第4步战斗段限定+地图账+死亡来源改述)+地图战斗资源(流程图/负向恒即时节/五步清单)+01-核心循环(「怪物的先手」用词相撞改警觉)+README案C批节+registry两处案C注记+编排器头部注释;④测试=行相位分类器换代(damage恒战斗段/reward_ineffective按forfeit分流)+先手断言收紧(存在或授予段终局→必存在)+新增案C段内序断言(地图账不得先于先手或插入敌方还手中间)——冒烟783/0三闸过+run_all 17套全绿+probe_gate --click全绿+gdd_lint与基线一致;⑤旧行为MC锚全数作废(授予段伤害致死短路先手语义消失),重锚归数值批

This commit is contained in:
DKChan committed 2026-10-06 09:14:59 +08:00
1 parent da157e3f65
commit 58dfb56272
8 files changed
+111 -47

No files matched your search

+32 -6
View File
@@ -1665,9 +1665,9 @@ func _smoke_full_battle(L: int, D: int, label: String) -> void:
if not (row.has(atk_t) and row.has("roll") and row.has("ac") and row.has("tier")):
hero_breakdown_ok = false
check(has_verdict, "%s 步骤流含判定行" % label)
# 伤害道具批(2026-09-18):单弱敌遭遇可被挖掘期兑付(穿刺弹/魔法矢/爆裂粉尘)在授予段单独击杀——
# 敌全灭后战斗段整段跳过、零先手行为合法结局;先手规则本身由强敌场景(L1/L2 深节点)继续守护。
check(hero_attacks >= 1 or run1.terminated, "%s 主角先手攻击行存在或授予段终局(2026-09-11 拍板① + 伤害道具批)×%d" % [label, hero_attacks])
# 案C(2026-10-06 用户裁):授予段不再产出伤害——进入战斗段时主角恒存活且场上有敌,
# 先手必兑;旧「挖掘期兑付可在授予段单独击杀、零先手合法」结局随地图账迁战斗段末整体消失。
check(hero_attacks >= 1, "%s 主角先手攻击行必存在(2026-09-11 拍板① + 案C 地图账殿后)×%d" % [label, hero_attacks])
check(hero_breakdown_ok, "%s 主角攻击行携带类型键与掷点读数(单分量——充能退役批)" % label)
@@ -2784,6 +2784,32 @@ func _smoke_settlement_segments() -> void:
if decays != 1 or verdicts != 1:
decay_verdict_ok = false # 衰减/判定每结算恰一次
check(order_ok, "每轮行相位单调(授予→增益/减益→战斗→衰减→判定)")
# 案C 段内序(2026-10-06 用户裁):段内伤害序 = 主角先手 →〔连珠矢随先手段〕→ 敌方逐个 → 地图账殿后。
# 地图账 = 全部棋盘来源伤害行 + 主角倒下不兑留痕行;违序(先于先手或插进敌方还手中间)即失败。
var mapdmg_ok := true
for ri_key in by_round.keys():
var rows_r: Array = by_round[ri_key]
var first_hero := -1
var last_enemy := -1
for i in rows_r.size():
var rw: Dictionary = rows_r[i]
if String(rw.get("type", "")) != "damage":
continue
if String(rw.get("source_class", "")) == "hero_attack" and first_hero < 0:
first_hero = i
elif String(rw.get("source_class", "")) == "enemy_action":
last_enemy = i
for i in rows_r.size():
var rw: Dictionary = rows_r[i]
var sc := String(rw.get("source_class", ""))
var is_board_acct: bool = (String(rw.get("type", "")) == "damage" \
and not ["hero_attack", "enemy_action", "feat_chain_arrows"].has(sc)) \
or String(rw.get("forfeit", "")) == "hero_down"
if not is_board_acct:
continue
if (first_hero >= 0 and i < first_hero) or (last_enemy >= 0 and i < last_enemy):
mapdmg_ok = false
check(mapdmg_ok, "案C 段内序:地图伤害账殿后(主角先手→敌方逐个→地图账;连珠矢随先手段)")
check(decay_verdict_ok, "衰减/判定段每结算恰一段(先兑付后衰减——含末轮)")
@@ -2797,9 +2823,9 @@ func _row_phase(row: Dictionary, ri: int) -> int:
"cast":
return 2
"damage":
if String(row.get("source_class", "")) in ["hero_attack", "enemy_action"]:
return 2
return 0 # 授予段 flat 兑付(爆裂/直伤)
return 2 # 案C(2026-10-06 用户裁):全部伤害兑付=战斗段(主角先手/敌方还手/地图账殿后统一结账)
"reward_ineffective":
return 2 if String(row.get("forfeit", "")) == "hero_down" else 0 # 战斗段末地图账不兑留痕 vs 授予段未生效
match String(row.get("source_class", "")):
"safe_cell", "mine_hit", "flag_hit", "flag_miss", "clear_reward":
if int(row.get("round_index", ri)) < ri: