Files
BT411/scratchpad/night16/weaponx_bench.sh
T

78 lines
4.2 KiB
Bash

#!/usr/bin/env bash
# #165 THE REAL PATH (night-16 root cause): crit-lottery kills went through
# MechWeapon::TakeDamage, which dropped the statusAlarm=1 destroyed write --
# X'd weapons kept firing. The old xfire bench used BT_KILL_SUBSYS (writes
# both cells directly) so it validated the gate, not the writers.
#
# Phase 1 (field path): BT_CRIT_SUBSYS=ERSLaser_1 kills via Damage ->
# ApplyDamageAndMeasure -> virtual TakeDamage. PASS: [crit] DESTROYED
# receipt fires, X ([techstat] condition 0) fires, ZERO named FIRED after
# the [crit] line, REFUSED lines present, survivor keeps firing.
# Phase 2 (freeze regression): BT_CRIT_SUBSYS=ERSLaser_1=0.5 partial-crits the
# weapon. PASS: it KEEPS firing after (the old port tail parked partially
# critted weapons at weaponAlarm=1 -- a state with no FSM case: the silent
# freeze, berserker's 20x STUCK-ON and #164's upstream writer).
set -x
. /c/git/bt411/scratchpad/night6/bench_common.sh
cd /c/git/bt411/content || exit 1
taskkill //F //IM btl4.exe >/dev/null 2>&1; sleep 3
rm -f wx1.log wx2.log
bt_expert_egg MP.EGG WX.EGG
sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; s/^vehicle=.*/vehicle=vulture/" WX.EGG
# ---- Phase 1: crit-path kill ----
( export BT_AUTOFIRE=1 BT_FIRE_AT_ICON=1 BT_CRIT_SUBSYS=ERSLaser_1
export BT_DMG_LOG=1 BT_FIRE_LOG=1 BT_LAMP_LOG=1
bt_launch wx1.log WX.EGG 0x03 -egg WX.EGG )
sleep 120
bt_kill_ours; sleep 2; taskkill //F //IM btl4.exe >/dev/null 2>&1; sleep 3
# ---- Phase 2: partial crit (freeze regression) ----
( export BT_AUTOFIRE=1 BT_FIRE_AT_ICON=1 BT_CRIT_SUBSYS=ERSLaser_1=0.5
export BT_DMG_LOG=1 BT_FIRE_LOG=1 BT_LAMP_LOG=1
bt_launch wx2.log WX.EGG 0x03 -egg WX.EGG )
sleep 100
bt_kill_ours; sleep 2; taskkill //F //IM btl4.exe >/dev/null 2>&1
python - <<'PY'
import io
def lines_of(p): return io.open(p, encoding="latin-1", errors="replace").read().splitlines()
print("=== #165 WEAPON-X BENCH (crit path) ===")
ok = True
# Phase 1
L = lines_of("wx1.log")
crit = next((i for i,l in enumerate(L) if "[crit] 'ERSLaser_1' DESTROYED" in l), None)
x = next((i for i,l in enumerate(L) if "ERSLaser_1 condition 0 SET" in l), None)
pre_f = sum(1 for l in L[:crit] if crit and "FIRED 'ERSLaser_1'" in l) if crit else 0
post_f = sum(1 for l in L[crit:] if "FIRED 'ERSLaser_1'" in l) if crit is not None else -1
post_r = sum(1 for l in L[crit:] if "'ERSLaser_1' fire REFUSED" in l) if crit is not None else -1
surv = sum(1 for l in L[crit:] if "FIRED 'ERMLaser_1'" in l) if crit is not None else -1
print(f"P1 [crit] DESTROYED line: {crit}")
print(f"P1 [techstat] X line: {x}")
print(f"P1 ERSLaser_1 FIRED pre={pre_f} post={post_f} REFUSED post={post_r} survivor FIRED post={surv}")
if crit is None: ok=False; print("FAIL: crit-path destruction never landed")
if x is None: ok=False; print("FAIL: no MFD X (techstat condition 0)")
if pre_f < 1: ok=False; print("FAIL: weapon never fired pre-kill (rig broken)")
if post_f != 0: ok=False; print(f"FAIL: {post_f} FIRED after crit destruction -- #165 ALIVE")
if post_r < 1: ok=False; print("FAIL: no REFUSED receipts post-kill")
if surv < 1: ok=False; print("FAIL: survivor stopped firing (over-kill)")
# Phase 2
L2 = lines_of("wx2.log")
mark = next((i for i,l in enumerate(L2) if "[critsub] 'ERSLaser_1'" in l and "zone=0.4" in l or "[critsub] 'ERSLaser_1'" in l and "zone=0.5" in l), None)
if mark is None:
mark = next((i for i,l in enumerate(L2) if "[critsub] 'ERSLaser_1'" in l), None)
p2_after = sum(1 for l in L2[mark:] if "FIRED 'ERSLaser_1'" in l) if mark is not None else -1
p2_crit = any("[crit] 'ERSLaser_1' DESTROYED" in l for l in L2)
p2_x = any("ERSLaser_1 condition 0 SET" in l for l in L2)
print(f"P2 partial marker line: {mark} FIRED after partial={p2_after} destroyed={p2_crit} X={p2_x}")
if mark is None: ok=False; print("FAIL: partial crit never applied")
if p2_after < 1: ok=False; print("FAIL: FROZEN after partial crit (the old tail bug)")
if p2_crit: ok=False; print("FAIL: partial mode destroyed the weapon")
if p2_x: ok=False; print("FAIL: X shown for a merely-damaged weapon")
print("RESULT:", "PASS" if ok else "FAIL")
PY