bench parity: local nodes now launch exactly like a player's shortcut
Local benches had drifted from the shipped launchers and every divergence
cost a debugging session:
* no BT_START_INSIDE -> benches opened in the EXTERNAL CHASE camera while
every player starts in the COCKPIT. The first first-person look at a
bench window was misread as a broken HUD.
* novice bench eggs -> every SHIPPED egg is expert; novice gates off the
entire heat model, crits and jams, so bench combat was not field combat.
(Verified: the aligned node now boots experience=3 simLive=1
heatModelOn=1, where it used to boot 0/0/0.)
* 1-LP affinity pins -> starved the gauge executive and produced a false
"the comms panel never counts deaths" reading. Two LPs per node keeps
the documented single-box jitter fix without the starvation.
scratchpad/night6/bench_common.sh now owns the contract (bt_player_env,
bt_launch, bt_expert_egg, bt_novice_egg) copied verbatim from play_solo.bat,
with bt_assert_player_env warning if the shipped bat ever drifts. All three
4-node benches source it. The limp bench keeps a novice egg -- expert crits
the aimed leg and the mech turns-but-never-moves -- and now says so loudly.
Also: BT_SHOT_EVERY=<n> headless backbuffer capture (btl4vid.cpp), the tool
this was diagnosed with. It must sit above the warp phase-0 early-out since
that fn is the per-frame alpha-pass hook. OS screen-capture is off-limits:
a foreground-lock failure photographed the user's browser instead of the game.
KB: build-and-run.md gains the bench-parity rule + the capture diag;
cockpit-view.md gains the measured aspect/FOV finding (the surround's 2.05:1
view collapses vertical FOV to 31.5 deg vs the pod's 46.8, so fixed canopy
geometry covers 68.6% of the lower half -- NOT a regression: the shipped 643
binary reports identical geometry).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
82f1ea1183
commit
4e89baeff3
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
# ===========================================================================
|
||||
# BENCH COMMON -- launch a local test node EXACTLY as a field player's
|
||||
# shortcut does, so what we see locally is what they see.
|
||||
#
|
||||
# WHY THIS FILE EXISTS (2026-07-30): local benches had drifted from the
|
||||
# shipped launchers, and every divergence cost a debugging session:
|
||||
# * no BT_START_INSIDE -> benches opened in the EXTERNAL CHASE camera while
|
||||
# every player starts in the COCKPIT. Hours were
|
||||
# spent on a "broken HUD" that was simply the first
|
||||
# first-person look at a view the benches never showed.
|
||||
# * novice bench eggs -> every SHIPPED egg is `expert`; novice silences the
|
||||
# whole heat model, crits and jams, so bench combat
|
||||
# was not the combat players get.
|
||||
# * 1-logical-processor affinity pins -> starved the gauge executive and
|
||||
# produced a false "the comms panel never counts"
|
||||
# reading. Two LPs per node keeps MP jitter pinned
|
||||
# (the documented single-box fix) without starving.
|
||||
#
|
||||
# THE PLAYER ENV IS THE CONTRACT. It is copied verbatim from the shipped
|
||||
# play_solo.bat / join.bat (dist zip). bt_assert_player_env compares this
|
||||
# list against a shipped .bat when one is available, so drift is caught.
|
||||
# ===========================================================================
|
||||
|
||||
BT_ROOT=/c/git/bt411
|
||||
BT_EXE=$BT_ROOT/build/Release/btl4.exe
|
||||
|
||||
# --- the exact env every shipped launcher sets -----------------------------
|
||||
bt_player_env () {
|
||||
export BT_PLATFORM=glass # unified build, desktop cockpit layer
|
||||
export BT_START_INSIDE=1 # COCKPIT eyepoint -- what a player sees
|
||||
export BT_DEV_GAUGES=1 # MFD/gauge surfaces + cockpit surround
|
||||
}
|
||||
|
||||
# --- warn if the shipped launcher has gained/lost a setting ----------------
|
||||
bt_assert_player_env () {
|
||||
local bat="$BT_ROOT/dist/BT411_4.11.643/play_solo.bat"
|
||||
[ -f "$bat" ] || return 0
|
||||
for v in BT_PLATFORM BT_START_INSIDE BT_DEV_GAUGES; do
|
||||
grep -qi "set $v=" "$bat" || echo "[bench] WARNING: shipped bat no longer sets $v"
|
||||
done
|
||||
}
|
||||
|
||||
# --- launch one node -------------------------------------------------------
|
||||
# bt_launch <logfile> <egg> <affinity> [extra args...] (env: extra BT_* vars)
|
||||
# Two logical processors per node: disjoint core sets keep single-box packet
|
||||
# delivery even (peer-shakiness fix) without starving the gauge executive.
|
||||
bt_launch () {
|
||||
local log="$1" egg="$2" aff="$3"; shift 3
|
||||
( bt_player_env
|
||||
export BT_LOG="$log" BT_AFFINITY="$aff"
|
||||
"$BT_EXE" -egg "$egg" "$@" & )
|
||||
}
|
||||
|
||||
# --- an EXPERT copy of an egg (what players actually fly) ------------------
|
||||
# Shipped eggs are all experience=expert. Bench eggs must match unless the
|
||||
# harness itself needs otherwise (see bt_novice_egg).
|
||||
bt_expert_egg () { # bt_expert_egg <src.egg> <dst.egg>
|
||||
sed 's/^experience=.*/experience=expert/' "$1" > "$2"
|
||||
}
|
||||
|
||||
# --- a NOVICE copy, for the harnesses that genuinely require it ------------
|
||||
# ONLY the aimed-leg gimp bench: on expert the self-damage bursts roll CRITS on
|
||||
# the aimed leg, and one myomers crit leaves the mech turning-but-not-moving --
|
||||
# which destroys the limp demo. Novice gates crits; the leg gimp still fires.
|
||||
# Any bench using this is NOT showing player-authentic damage behaviour.
|
||||
bt_novice_egg () { # bt_novice_egg <src.egg> <dst.egg>
|
||||
sed 's/^experience=.*/experience=novice/' "$1" > "$2"
|
||||
echo "[bench] NOTE: novice egg $2 -- crits/heat/jams are GATED OFF (harness requirement)"
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# #81/#45 FOUR-NODE CROSS-FIRE: real weapon kills, real attribution.
|
||||
#
|
||||
# No self-damage anywhere. All four pilots chase the nearest live peer
|
||||
# (BT_GOTO=enemy), hold at 150m, and fire in bursts (BT_AF_PERIOD throttles
|
||||
# BOTH the gun and missile groups -- unthrottled spam trips the documented
|
||||
# FailureHeat all-weapons brick and combat dies). Every death is a weapon
|
||||
# kill by another pilot, resolved cross-machine through the authentic path.
|
||||
#
|
||||
# Launched through bench_common.sh: every window is configured EXACTLY like a
|
||||
# player's shortcut (cockpit view, glass cockpit, MFDs) on an EXPERT egg, so
|
||||
# heat/crits/jams behave as they do in the field.
|
||||
#
|
||||
# PASS = matchlog KILL rows with killer != victim, panels mirror (SBMIRROR +
|
||||
# panel DRAW), every death START -> RESET, 0 SWALLOWED / 0 MISMATCH /
|
||||
# 0 DISCARDED / 0 GHOST / 0 crash.
|
||||
set -x
|
||||
. /c/git/bt411/scratchpad/night6/bench_common.sh
|
||||
cd /c/git/bt411/content || exit 1
|
||||
bt_assert_player_env
|
||||
rm -f mp4c_a.log mp4c_b.log mp4c_c.log mp4c_d.log
|
||||
A=/c/git/bt411/scratchpad/night6/runs/$(date +%H%M%S); mkdir -p "$A"; mv matchlog_*.txt "$A"/ 2>/dev/null
|
||||
|
||||
bt_expert_egg MP4.EGG MP4X.EGG
|
||||
PD=/c/git/bt411/scratchpad/night6/procdump.exe
|
||||
|
||||
launch () { # $1=log $2=affinity $3=port
|
||||
BT_MP_LOG=1 BT_SCORE_LOG=1 BT_DEATH_LOG=1 BT_MATCHLOG=1 BT_TLOC_LOG=1 \
|
||||
BT_GOTO=enemy BT_GOTO_STOP=150 BT_AUTOFIRE=1 BT_AF_MISSILE=1 BT_AF_PERIOD=7 \
|
||||
bt_launch "$1" MP4X.EGG "$2" -net "$3"
|
||||
sleep 2
|
||||
# crash net: full dump on any unhandled exception (a node died silently once)
|
||||
if [ -x "$PD" ]; then
|
||||
for pid in $(tasklist //FI "IMAGENAME eq btl4.exe" //NH 2>/dev/null | awk '{print $2}'); do
|
||||
[ -f "/c/git/bt411/scratchpad/night6/pd_$pid.txt" ] && continue
|
||||
"$PD" -accepteula -e -ma "$pid" \
|
||||
"/c/git/bt411/scratchpad/night6/crash_$pid.dmp" \
|
||||
> "/c/git/bt411/scratchpad/night6/pd_$pid.txt" 2>&1 &
|
||||
done
|
||||
fi
|
||||
}
|
||||
rm -f /c/git/bt411/scratchpad/night6/pd_*.txt /c/git/bt411/scratchpad/night6/crash_*.dmp
|
||||
launch mp4c_d.log 0xC0 1801
|
||||
launch mp4c_c.log 0x30 1701
|
||||
launch mp4c_b.log 0x0C 1601
|
||||
launch mp4c_a.log 0x03 1501
|
||||
sleep 5
|
||||
python ../tools/btconsole.py MP4X.EGG 127.0.0.1:1501 127.0.0.1:1601 \
|
||||
127.0.0.1:1701 127.0.0.1:1801 &
|
||||
PC=$!
|
||||
|
||||
sleep 480
|
||||
kill $PC 2>/dev/null
|
||||
taskkill //F //IM btl4.exe 2>/dev/null
|
||||
rm -f MP4X.EGG
|
||||
echo "=== DONE ==="
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# #82 FOUR-NODE LIMP VERIFICATION: do peers see a gimped mech step-drag, or skate?
|
||||
#
|
||||
# Node A gimps a LEG ~2s after it is alive (BT_SELF_DAMAGE_ZONE=leg resolves the
|
||||
# zone symbolically -- numeric ids are per-mech-type) and circles slowly in its
|
||||
# own spawn area from the first second. B/C/D are PLAIN observers: no
|
||||
# automation, full keyboard control, parked at spawn. Drive one over and look.
|
||||
#
|
||||
# Launched through bench_common.sh, so every window is configured EXACTLY like
|
||||
# a player's shortcut -- COCKPIT view, glass cockpit, MFDs.
|
||||
#
|
||||
# ⚠ THE ONE DELIBERATE DIVERGENCE: this bench flies a NOVICE egg. On expert the
|
||||
# self-damage bursts roll CRITS on the aimed leg and one myomers crit leaves the
|
||||
# mech turning-but-not-moving, which destroys the limp. Crits/heat/jams are
|
||||
# therefore OFF here -- do not read damage behaviour off this bench.
|
||||
#
|
||||
# USER CHECK: the limping mech must STEP-DRAG, never glide/skate.
|
||||
# LOG CHECK: [animind] inst=1 entering gait states 22-27 on the observers.
|
||||
set -x
|
||||
. /c/git/bt411/scratchpad/night6/bench_common.sh
|
||||
cd /c/git/bt411/content || exit 1
|
||||
bt_assert_player_env
|
||||
rm -f mp4l_a.log mp4l_b.log mp4l_c.log mp4l_d.log
|
||||
A=/c/git/bt411/scratchpad/night6/runs/$(date +%H%M%S); mkdir -p "$A"; mv matchlog_*.txt "$A"/ 2>/dev/null
|
||||
|
||||
bt_novice_egg MP4L.EGG MP4LN.EGG
|
||||
|
||||
observer () { # $1=log $2=affinity $3=port
|
||||
BT_MP_LOG=1 BT_SYNC_LOG=1 BT_REPL_LOG=1 BT_MATCHLOG=1 BT_AUDIO_SPATIAL=1 \
|
||||
bt_launch "$1" MP4LN.EGG "$2" -net "$3"
|
||||
}
|
||||
observer mp4l_d.log 0xC0 1801
|
||||
sleep 1
|
||||
observer mp4l_c.log 0x30 1701
|
||||
sleep 1
|
||||
observer mp4l_b.log 0x0C 1601
|
||||
sleep 1
|
||||
# the LIMPER: symbolic leg zone, 2 ticks of 60 -> gimp (no kill) ~2s after
|
||||
# alive; slow tight circle from t0 so it never leaves its spawn area.
|
||||
BT_MP_LOG=1 BT_DMG_LOG=1 BT_MATCHLOG=1 BT_AUDIO_SPATIAL=1 \
|
||||
BT_SELF_DAMAGE=60 BT_SELF_DAMAGE_ZONE=leg BT_SELF_DAMAGE_TICKS=2 BT_SELF_DAMAGE_DELAY=2 \
|
||||
BT_AUTODRIVE=0.4 BT_FORCE_TURN=0.45 \
|
||||
bt_launch mp4l_a.log MP4LN.EGG 0x03 -net 1501
|
||||
sleep 5
|
||||
python ../tools/btconsole.py MP4LN.EGG 127.0.0.1:1501 127.0.0.1:1601 \
|
||||
127.0.0.1:1701 127.0.0.1:1801 &
|
||||
PC=$!
|
||||
|
||||
sleep 420
|
||||
kill $PC 2>/dev/null
|
||||
taskkill //F //IM btl4.exe 2>/dev/null
|
||||
rm -f MP4LN.EGG
|
||||
echo "=== DONE ==="
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# #81/#45 FOUR-NODE RESPAWN + SCOREBOARD BENCH.
|
||||
#
|
||||
# Four networked instances, ALL dying repeatedly on staggered timers so death
|
||||
# cycles overlap (the field condition: several respawn handshakes in flight at
|
||||
# once, each answered by an arbitrary peer's DropZone).
|
||||
#
|
||||
# Launched through bench_common.sh, so every window is configured EXACTLY like
|
||||
# a player's play_solo/join shortcut (cockpit view, glass cockpit, MFDs) and
|
||||
# flies an EXPERT egg like every shipped one. What you see here is what the
|
||||
# field sees.
|
||||
#
|
||||
# PASS = every death cycle pairs START -> RESET on its own node
|
||||
# 0 SWALLOWED / 0 MISMATCH / 0 DISCARDED / 0 GHOST / 0 crash
|
||||
# and each node's PLAYER_DEAD tally increments 1 per death.
|
||||
# WATCH = the comms panel KILLS/DEATHS columns, and the blue respawn vortex.
|
||||
set -x
|
||||
. /c/git/bt411/scratchpad/night6/bench_common.sh
|
||||
cd /c/git/bt411/content || exit 1
|
||||
bt_assert_player_env
|
||||
rm -f mp4p_a.log mp4p_b.log mp4p_c.log mp4p_d.log
|
||||
A=/c/git/bt411/scratchpad/night6/runs/$(date +%H%M%S); mkdir -p "$A"; mv matchlog_*.txt "$A"/ 2>/dev/null
|
||||
|
||||
bt_expert_egg MP4.EGG MP4X.EGG
|
||||
|
||||
# staggered first deaths so the cycles interleave instead of lining up
|
||||
launch () { # $1=log $2=affinity $3=port $4=delay
|
||||
BT_MP_LOG=1 BT_SCORE_LOG=1 BT_DEATH_LOG=1 BT_MATCHLOG=1 BT_PERF=1 \
|
||||
BT_SELF_DAMAGE=60 BT_SELF_DAMAGE_DELAY=$4 BT_SELF_DAMAGE_REPEAT=1 \
|
||||
bt_launch "$1" MP4X.EGG "$2" -net "$3"
|
||||
}
|
||||
launch mp4p_d.log 0xC0 1801 34
|
||||
sleep 1
|
||||
launch mp4p_c.log 0x30 1701 41
|
||||
sleep 1
|
||||
launch mp4p_b.log 0x0C 1601 48
|
||||
sleep 1
|
||||
launch mp4p_a.log 0x03 1501 55
|
||||
sleep 5
|
||||
python ../tools/btconsole.py MP4X.EGG 127.0.0.1:1501 127.0.0.1:1601 \
|
||||
127.0.0.1:1701 127.0.0.1:1801 &
|
||||
PC=$!
|
||||
|
||||
sleep 150
|
||||
kill $PC 2>/dev/null
|
||||
taskkill //F //IM btl4.exe 2>/dev/null
|
||||
rm -f MP4X.EGG
|
||||
echo "=== DONE ==="
|
||||
@@ -14,11 +14,11 @@ sed 's/^experience=expert/experience=novice/' MP.EGG > MPG.EGG
|
||||
|
||||
# B first (listener), then A -- same order as the working mp_skate.sh
|
||||
BT_LOG=mp_b.log BT_AFFINITY=0x2 BT_MP_LOG=1 BT_SCORE_LOG=1 BT_DEATH_LOG=1 \
|
||||
BT_SELF_DAMAGE=60 BT_SELF_DAMAGE_DELAY=40 BT_SELF_DAMAGE_REPEAT=1 \
|
||||
BT_TLOC_LOG=1 BT_SELF_DAMAGE=60 BT_SELF_DAMAGE_DELAY=40 BT_SELF_DAMAGE_REPEAT=1 \
|
||||
../build/Release/btl4.exe -egg MPG.EGG -net 1601 &
|
||||
sleep 2
|
||||
BT_LOG=mp_a.log BT_AFFINITY=0x1 BT_MP_LOG=1 BT_SCORE_LOG=1 BT_DEATH_LOG=1 \
|
||||
BT_SELF_DAMAGE=60 BT_SELF_DAMAGE_DELAY=55 BT_SELF_DAMAGE_REPEAT=1 \
|
||||
BT_TLOC_LOG=1 BT_SELF_DAMAGE=60 BT_SELF_DAMAGE_DELAY=55 BT_SELF_DAMAGE_REPEAT=1 \
|
||||
../build/Release/btl4.exe -egg MPG.EGG -net 1501 &
|
||||
sleep 4
|
||||
python ../tools/btconsole.py MPG.EGG 127.0.0.1:1501 127.0.0.1:1601 &
|
||||
|
||||
Reference in New Issue
Block a user