68e0375be2
Replaces melee_scan in the rack. melee_scan spun the radar at the 45 deg/tick cap unconditionally, so a full 360 deg revolution took 8 ticks and every enemy was scanned roughly every 8 ticks. The new module starts with the same full spin, and once it is SURE it has covered every enemy it sweeps back and forth over only the minimal covering arc of all enemy bearings. MEASURED, real melees via the bridge, per-enemy onScannedBot counts: 3-bot melee (2 enemies): 29.6 -> 61.1 scans/100 melee-ticks (2.06x) 4-bot melee (3 enemies): 36.0 -> 75.7 scans/100 melee-ticks (2.10x) Covering-arc widths observed: mostly <90 deg in the 2-enemy case, up to 240 deg in the 3-enemy case, so the gain shrinks as the arc widens - and at the ExitTrackWidthDeg=300 fallback it degenerates to exactly the old full spin, so there is no loss when narrowing would not help. TRADEOFF, recorded rather than hidden: a wider arc legitimately takes longer to traverse, so the freshness window costs 5-7 points (fresh<=16: 93-95% vs 98-100%) and more at fresh<=8 (75-76% vs 97-100%). More scans per enemy, at slightly staler individual fixes. DESIGN: acquisition spins 360 until every live known enemy was seen within FreshnessTicks=16 (two revolutions of slack), no new id appeared, and the live count matches getEnemyCount(); that must hold FreshStreakTicks=3 consecutive ticks. Tracking then bang-bang sweeps the wraparound-aware covering arc (350+10 -> 20 through 0) widened by MarginDeg=20 each end, at up to 45 deg/tick. Fallbacks return to acquisition: any stale enemy, any new id, or an arc >= 300 deg. Enter 270 / Exit 300 gives 30 deg of hysteresis so it cannot flap. Adds EnemyInfo.lastSeenTick (additive) so coverage is judged on staleness, not mere knowledge - without it an enemy that slipped behind the sweep would keep contributing its own stale bearing, which is self-confirming. The offline range now round-trips that field from the fixture 'lst'. COMPANION FIX, and it matters: the radar-mode switch used the TRACKER's known enemy count, so in melee the bot saw one enemy before scanning the second, locked to 1v1, and the melee radar never ran at all. Now uses getEnemyCount() (server truth), so melee mode persists until one enemy is genuinely left. 41 new unit checks (wraparound arcs, straddle at 0/360, single/empty enemies, the 45 deg/tick cap, every phase transition and fallback). melee_scan is kept but marked DEPRECATED; nothing in the rack imports it. Non-regression: 33 gun-harness checks, vbullet metric, power selection, and 12/12 offline==online acceptance all pass.
24 lines
950 B
Nim
24 lines
950 B
Nim
## melee_scan.nim — DEPRECATED / reference only. Superseded by
|
|
## `adaptive_melee_radar.nim`, which sweeps only the arc containing the enemies.
|
|
## Nothing in the rack imports this module any more; it is kept because it is the
|
|
## exact baseline the adaptive radar is measured against (always 45 deg/tick).
|
|
##
|
|
## Continuously spinning radar for melee.
|
|
## Always returns max radar turn rate so all enemies get scanned periodically.
|
|
## No state needed; stateless spin guarantees coverage regardless of enemy count.
|
|
|
|
import ../radar_harness/radar_interface
|
|
|
|
export radar_interface
|
|
|
|
const MaxRadarTurnRate* = 45.0 ## deg/tick — Tank Royale hard limit
|
|
|
|
type MeleeScanModule* = object
|
|
debugGraphics*: bool
|
|
|
|
proc initMeleeScan*(): MeleeScanModule = MeleeScanModule(debugGraphics: false)
|
|
|
|
proc computeScan*(m: MeleeScanModule, state: WorldState): float =
|
|
## Always spin at max rate — guarantees full arena coverage every 8 ticks.
|
|
MaxRadarTurnRate
|