tracker: corpses do not exist - revert the fix and retire the workaround
The belief "BotDeathEvent never reaches ModularBot, so enemyTracker keeps dead
enemies alive forever" was written into a code comment and then believed twice.
It is FALSE. Measured in a 7-bot melee with a per-tick probe comparing
enemyTracker's alive count against the server's getEnemyCount():
metric 1.3.1 (20 rd) 0.35.5 (15 rd)
observed enemy deaths 83 68
...non-round-ending 83 (100%) 66 (97%)
ekBotDeath events DROPPED 0 0
max dispatch lag (turns behind) 1 1
phantom ticks 1 / 16,820 1 / 12,596
MAX CORPSE LIFETIME 0 ticks 0 ticks
victims still alive at round end 0 0
onBotDeath fires for every death, including non-round-ending ones. The
API-level event-drop mechanism IS real (test_event_drop_mechanism.nim proves
it: ekBotDeath is not in isCritical and MAX_EVENTS_AGE=2) - the bot simply
never falls far enough behind for it to trigger (max lag 1 turn).
Removed:
- reconcileWithServer + ReconcilePersistTicks/mismatchTicks/sawServerAlive
(uncommitted, and ON BY DEFAULT despite the premise being false). Its own
comment admitted a shorter window once KILLED A LIVE ENEMY ("it fired three
more times after the tracker marked it dead") - a latent mis-prune path
defending against a bug that does not exist.
- The radar's CorpseTicks=40 filter and the same-class age>60 filter in
recordRadarStats, both carrying the false comment. Removal changes no real
behaviour: buildState feeds the radar enemyTracker.allAlive(), so a dead
enemy never reaches computeScan.
Kept:
- The TR_TRACKER_PROBE instrument (default OFF), which produced the table above.
- test_event_drop_mechanism.nim - the drop mechanism is a genuine library
behaviour worth guarding.
- isAlive/aliveCount on the tracker.
Added: docs/tracker_death_events.md (the durable negative, so this is not
re-invented a third time) and test_enemy_tracker_death.nim (13 checks) in place
of the test for the deleted feature.
Guards: test_gun_harness 39/39, test_vbullet_metric 11, test_power_selection 3,
test_adaptive_radar 41/41, test_event_drop_mechanism 6, test_enemy_tracker_death
13, acceptance 12/12, ModularBot compiles.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
## Corpse measurement: run a real melee where bots kill each other and log
|
||||
## ModularBot's tracker-vs-server disagreement per tick.
|
||||
##
|
||||
## The tracker probe (ModularBot TR_TRACKER_PROBE=1) records, each tick:
|
||||
## tracker_alive (bot.enemyTracker.allAlive().len), server_ec (getEnemyCount()),
|
||||
## each tracked enemy's lastSeenTick, the dead map and any reconcile prunes.
|
||||
## The queue probe records the event queue BEFORE removeOldEvents deletes events.
|
||||
##
|
||||
## TR_TRACKER_RECONCILE defaults to 0 here so the RAW corpse behaviour is
|
||||
## measured (a corpse can only be removed by a BotDeathEvent fast-path).
|
||||
##
|
||||
## MELEE_ROUNDS=20 TR_SERVER_JAR=<jar> \
|
||||
## nim c -r --path:common_libs common_libs/tests/measure_corpse_melee.nim
|
||||
|
||||
import std/[os, strformat, strutils]
|
||||
import test_framework/server_manager
|
||||
import test_framework/bot_compiler
|
||||
import test_framework/runner_process
|
||||
import test_framework/battle_result
|
||||
|
||||
const
|
||||
repoRoot = currentSourcePath().parentDir.parentDir.parentDir
|
||||
modularBotDir = repoRoot / "ModularBot_garage"
|
||||
samplesDir = "/home/davide/Downloads/robocode-tankroyale/sample-bots-nim-linux-1.0.7"
|
||||
|
||||
let drussDir = getEnv("DRUSSGT_BOTDIR", "/tmp/tr_bots/DrussGT")
|
||||
let rounds = parseInt(getEnv("MELEE_ROUNDS", "20"))
|
||||
let probePath = getEnv("TR_TRACKER_PROBE_PATH", "/tmp/tracker_probe_melee.jsonl")
|
||||
|
||||
# RAW behaviour: no reconciliation, so any corpse persists until a BotDeathEvent.
|
||||
putEnv("TR_TRACKER_RECONCILE", getEnv("TR_TRACKER_RECONCILE", "0"))
|
||||
putEnv("TR_TRACKER_PROBE", "1")
|
||||
putEnv("TR_TRACKER_PROBE_PATH", probePath)
|
||||
if fileExists(probePath): removeFile(probePath)
|
||||
|
||||
var bots = @[modularBotDir]
|
||||
for name in ["Fire", "Corners", "Crazy", "RamFire", "SpinBot"]:
|
||||
let d = samplesDir / name
|
||||
if dirExists(d): bots.add d
|
||||
if fileExists(drussDir / "DrussGT.sh"): bots.add drussDir
|
||||
|
||||
echo "server jar : ", getEnv("TR_SERVER_JAR", DefaultServerJar)
|
||||
echo "probe path : ", probePath
|
||||
echo "reconcile : ", getEnv("TR_TRACKER_RECONCILE")
|
||||
echo "bots : ", bots
|
||||
echo "rounds : ", rounds
|
||||
|
||||
ensureServer()
|
||||
discard compileBots(@[modularBotDir])
|
||||
let raw = runBattleRunner(getServerUrl(), bots, rounds, 1_800_000, true)
|
||||
let r = parseServerOutput(raw)
|
||||
for b in r.results:
|
||||
echo fmt" {b.name:<12} totalScore={b.totalScore} rank={b.rank} survival={b.survivalCount}"
|
||||
echo "rounds played: ", r.rounds.len
|
||||
Reference in New Issue
Block a user