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:
@@ -49,14 +49,6 @@ const
|
||||
FreshStreakTicks* = 3 ## consecutive fresh ticks required to enter
|
||||
## tracking (hysteresis against a single lucky
|
||||
## fresh tick).
|
||||
CorpseTicks* = 40 ## ticks; an enemy unseen for longer is treated as
|
||||
## dead and dropped from the arc/coverage. The
|
||||
## staleness fallback re-acquires a LIVE enemy
|
||||
## within FreshnessTicks + one full spin, so a
|
||||
## live enemy is never unseen this long. Needed
|
||||
## because BotDeathEvent does not reach this bot
|
||||
## in the current API, so the tracker keeps dead
|
||||
## enemies 'alive' forever.
|
||||
MarginDeg* = 20.0 ## deg added to EACH end of the covering arc. An
|
||||
## enemy at 8 px/tick and 300 px changes bearing
|
||||
## by at most ~1.5 deg/tick; over a half-sweep
|
||||
@@ -199,9 +191,12 @@ proc computeScan*(m: var AdaptiveMeleeRadarModule, state: WorldState): float =
|
||||
if e.id notin m.knownIds:
|
||||
m.knownIds.incl e.id
|
||||
newId = true
|
||||
# No corpse filter: `state.enemies` is built from `EnemyTracker.allAlive()`
|
||||
# and `onBotDeath` reliably marks deaths (measured 0 corpse ticks; see
|
||||
# docs/tracker_death_events.md). A long-unseen entry is therefore a stale
|
||||
# LIVE enemy, and the freshness fallback below must re-acquire it rather
|
||||
# than the radar silently dropping it from the arc.
|
||||
let age = state.tick - e.lastSeenTick
|
||||
if age > CorpseTicks:
|
||||
continue # dead-but-unmarked corpse: ignore it entirely
|
||||
bearings.add normalizeDeg(
|
||||
arctan2(e.y - state.selfY, e.x - state.selfX).radToDeg)
|
||||
if age > FreshnessTicks:
|
||||
|
||||
Reference in New Issue
Block a user