From 3a22c334ac34e9452a4d91953539a9bdb8a7e422 Mon Sep 17 00:00:00 2001 From: Joe DiPrima Date: Sat, 1 Aug 2026 05:28:45 -0500 Subject: [PATCH] bench: two-node CROSS-POD damage verification for the #95 burst change Projectile damage now Dispatches directly at the victim instead of going through the shooter's SubsystemMessageManager, so cross-pod delivery had to be proven on real nodes rather than assumed. RESULT: cross-pod delivery intact, and the cluster count survives the wire. Node A fired 38 missile rounds with bursts {1:5,2:6,3:6,4:7,5:7,6:7}; node B received exactly the matching zone applications {2:12,3:18,4:28,5:35,6:42} -- i.e. rounds x burst, per burst band, exact. 135 of B's 142 explosive applications carried burst > 1 (the manager path used to drop it to 1). Energy stayed at burst 1 on both nodes; no crash on either. Co-Authored-By: Claude Opus 5 (1M context) --- scratchpad/night8/mp_burst.py | 41 +++++++++++++++++++++++++++++++ scratchpad/night8/mp_burst.sh | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 scratchpad/night8/mp_burst.py create mode 100644 scratchpad/night8/mp_burst.sh diff --git a/scratchpad/night8/mp_burst.py b/scratchpad/night8/mp_burst.py new file mode 100644 index 0000000..2adc51f --- /dev/null +++ b/scratchpad/night8/mp_burst.py @@ -0,0 +1,41 @@ +"""Cross-pod damage analysis for the #95 cluster-burst change. + +For each node: what it FIRED (shooter-side projectile impacts) versus what it +RECEIVED (zone applications), so a round fired on one node can be seen landing +on the other with its burst count intact. +""" +import re, sys, collections + +def load(path): + return open(path, encoding="latin-1", errors="replace").read() + +RX_HIT = re.compile(r"\[dmghit\] mech=(\S+) zone=(\d+) vital=(\d) type=(\d+) " + r"amt=([0-9.eE+-]+) burst=([0-9.]+) lvl ([0-9.eE+-]+)->([0-9.eE+-]+)") +RX_IMP = re.compile(r"\[projectile\] IMPACT damage=([0-9.]+) subsys=(\d+).*?burst=(\d+)") + +for name, path in [("NODE A (1501)", sys.argv[1]), ("NODE B (1601)", sys.argv[2])]: + d = load(path) + imps = RX_IMP.findall(d) + hits = RX_HIT.findall(d) + print("=" * 62) + print("%s %s" % (name, path)) + print(" FIRED : %d projectile impacts, bursts=%s" + % (len(imps), dict(sorted(collections.Counter(int(b) for _, _, b in imps).items())))) + byType = collections.defaultdict(list) + for mech, zone, vital, ty, amt, burst, a, b in hits: + byType[int(ty)].append((float(amt), int(float(burst)), float(b) - float(a))) + print(" TOOK : %d zone applications" % len(hits)) + for ty in sorted(byType): + v = byType[ty] + label = {2: "EXPLOSIVE(missile/AC)", 3: "ENERGY(beam)", 0: "COLLISION"}.get(ty, "type%d" % ty) + print(" %-22s %3d apps bursts=%-28s dlvl=%.4f" + % (label, len(v), + dict(sorted(collections.Counter(b for _, b, _ in v).items())), + sum(x[2] for x in v))) + mult = [b for _, b, _ in byType.get(2, []) if b > 1] + print(" >>> multi-burst EXPLOSIVE applications received: %d %s" + % (len(mult), "<-- cluster count SURVIVED the wire" if mult else "<-- NONE (burst lost!)")) + for tag in ("Unhandled", "assert", "ACCESS_VIOLATION"): + n = len(re.findall(tag, d, re.I)) + if n: + print(" !! %s x%d" % (tag, n)) diff --git a/scratchpad/night8/mp_burst.sh b/scratchpad/night8/mp_burst.sh new file mode 100644 index 0000000..4083400 --- /dev/null +++ b/scratchpad/night8/mp_burst.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# CROSS-POD damage verification for the #95 cluster-burst change. +# +# WHY: projectile damage no longer goes through the shooter's +# SubsystemMessageManager -- it now Dispatches DIRECTLY at the struck entity, as +# the binary's Missile does (FUN_004be078). Dispatch is documented to reroute +# cross-pod for a REPLICANT victim on its own, but the manager routing that used +# to carry it is gone, so this must be proven on two real nodes rather than +# assumed. +# +# Two pilots chase each other and fire in throttled bursts (unthrottled spam +# trips the FailureHeat all-weapons brick and combat dies). +# +# PASS, read on the VICTIM's log (the node that did NOT fire the round): +# * [dmghit] type=2 rows appear at all -> cross-pod damage arrives +# * those rows carry burst > 1 -> the cluster count SURVIVED +# the wire (this is the whole +# point: the manager used to +# drop it) +# * their damageLevel actually climbs -> armour is really applied +# Plus: no crash, and matchlog PROJ rows on the shooter pair with DMG on victim. +set -x +. /c/git/bt411/scratchpad/night6/bench_common.sh +cd /c/git/bt411/content || exit 1 +bt_assert_player_env +rm -f mpb_a.log mpb_b.log +bt_expert_egg MP.EGG MPB.EGG + +launch () { # $1=log $2=affinity $3=port + BT_MP_LOG=1 BT_DMG_LOG=1 BT_MATCHLOG=1 BT_PROJ_LOG=1 BT_DEATH_LOG=1 \ + BT_GOTO=enemy BT_GOTO_STOP=120 BT_AUTOFIRE=1 BT_AF_MISSILE=1 BT_AF_PERIOD=6 \ + bt_launch "$1" MPB.EGG "$2" -net "$3" + sleep 2 +} + +launch mpb_b.log 0x0C 1601 +launch mpb_a.log 0x03 1501 +sleep 5 +python ../tools/btconsole.py MPB.EGG 127.0.0.1:1501 127.0.0.1:1601 & +PC=$! + +sleep 240 +kill $PC 2>/dev/null +bt_kill_ours +rm -f MPB.EGG +echo "=== DONE -- analyse with mp_burst.py ==="