Files
BT411/scratchpad/night14/scorepair.sh
T
Joe DiPrimaandClaude Opus 5 46ff8dd262 #150 double kill FIXED (two binary-cited gates) + #151 measured AUTHENTIC to the point
#150 -- one kill credited twice (Rajel on Oracle, Oracle on Conn Man).
CAUGHT: one death -> two type-2 arms 1ms apart (awards 501.96/505.88 -- the
tally GREW between them), victim inst=R.  Mechanism: this port deliberately
applies damage on replicants for local visual response; the report tail ran
there too, and a replicant's movement mode cannot flip to wreck until the
victim's death record round-trips -- so each round of a killing VOLLEY inside
that window re-posted the kill.  Why missiles, why intermittent.

The binary forbids the whole situation: its handler OPENS with the assertion
  if ((flags & 0xc) == 4) Fail("Replicant Mech recieving takedamage",
                               MECH.CPP, 0x3da)          [part_012.c:14613]
-- TakeDamage on a replicant was a BUG in 1995; the tail only ever ran on the
victim's master.  Fix: (1) gate the REPORT TAIL master-only (local damage
application stays); (2) adopt the binary's once-latch -- the 0->1 edge of
IsMechDestroyed() across the handler call (local_14), replacing the
deathBlastArmed form for the report gate.

VERIFIED (scratchpad/night14/scorepair.sh): 3 victim deaths, 5 shooter
respawns -> exactly one type-2 per credited kill, kills 0->1->2, zero doubles
(was: kills 0->2 on one death).

#151 -- panic eject "-499 instead of 0" is AUTHENTIC 1995 SCORING, decoded
from EjectPilot @0049f854: the punch-out dispatches a SELF TakeDamage of
  damageAmount = role->killBonus (+0x1c, 500 in dfltrole), type Explosive,
  senderMechID = SELF, player->suppressConsole = 1, graphicAlarm -> 10
which flows through the report tail as a SUICIDE kill: award = -CalcKillScore
(your own death), plus the type-1 death cost.  1000 - ~999 - 500 = -499:
the binary predicts Oracle's exact number.  Our port already used
role->killBonus for the blast (mech.cpp:652) -- faithful end to end; bench
shows each eject charged exactly once (-900/-1050 across three ejects).
Panic eject = scored as suicide.  Whether that is fun is a design question;
it is not a porting defect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SgmXGNMXavXiafKXf9MDC
2026-08-10 10:30:12 -05:00

31 lines
1.5 KiB
Bash

#!/usr/bin/env bash
# #150/#151: count type-2 arm executions per kill + measure the eject score arithmetic
. /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 sc_a.log sc_b.log sc_r.log
mkdir -p /c/git/bt411/scratchpad/night14/mlbak && mv matchlog_*.txt /c/git/bt411/scratchpad/night14/mlbak/ 2>/dev/null
bt_expert_egg MP.EGG SC.EGG
sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; s/^vehicle=.*/vehicle=madcat/" SC.EGG
# B: unarmed slow target, respawns on death
( export BT_GOTO=enemy BT_GOTO_STOP=80 BT_SCORE_LOG=1 BT_DEATH_LOG=1 BT_MATCHLOG=1 BT_MP_LOG=1
bt_launch sc_b.log SC.EGG 0x0C -net 1601 )
sleep 2
# A: kills B with autofire, then panic-ejects late
( export BT_GOTO=enemy BT_GOTO_STOP=100 BT_AUTOFIRE=1 BT_AF_MISSILE=1 BT_AF_PERIOD=4
export BT_EJECT_AT=9000
export BT_SCORE_LOG=1 BT_DEATH_LOG=1 BT_MATCHLOG=1 BT_MP_LOG=1
bt_launch sc_a.log SC.EGG 0x03 -net 1501 )
sleep 5
python ../tools/btconsole.py SC.EGG 127.0.0.1:1501 127.0.0.1:1601 > sc_r.log 2>&1 &
R=$!; sleep 300; kill $R 2>/dev/null; sleep 2
bt_kill_ours; sleep 2; taskkill //F //IM btl4.exe >/dev/null 2>&1
echo RESULT
echo "--- B deaths (kills A should have earned) ---"
grep -ac "Mech::Reset" sc_b.log
echo "--- A: kill-arm executions + score sequence (matchlog) ---"
grep -ah "SCORE\|KILL\|EJECT\|DEATH" matchlog_*.txt 2>/dev/null | head -25
echo "--- A: scorepost receipts (producer side) ---"
grep -a "scorepost" sc_a.log | head -10
grep -a "scorepost" sc_b.log | head -10