j141 fix: the per-gun real-shot accounting was still array[17] after rack id 17 landed
REGRESSION: the live bot stopped firing entirely and moved degenerately whenever a rack admitted rack id 17 (the ADE+SBC BITBRAIN gun added ine9302bc). ROOT CAUSE: ModularBot.nim declared the per-gun accounting arrays (gunRealShots / gunRealHits / gunRealShotsByMode / gunRealHitsByMode / gunSelectionCount) as array[17, int] — the rack size BEFORE id 17 existed. The instant the selector picked gun 17, the accounting indexed one past the end: * debug build -> IndexDefect out of run(): the bot stops, 0 shots; * -d:release (shipped) -> silent out-of-bounds write onto the adjacent lastPowerLogKey: string header, so the bot kept moving but never fired and never reported a shot. Measured with the owner's exact out/.env, 1v1 SittingDuck:0dc5552(pre-rename): BitBrain(id16) selected 356+157 ticks, realShots 24+9, realHits 23+9, ModularBot wins 180/360 HEAD (e9302bc..) : selected 0, vShots 0, realShots 0, realHits 0 debug : IndexDefect on the first tick that selects id 17 -d:release : same 0/0/0, bot scores 22 and dies FIX: derive every gun-indexed width from the rack instead of a literal. gun_harness/selector exports NumRackGuns* = len(RackGunNames) (18); ModularBot uses it for the five accounting arrays, the per-round reset loops, the gun_stats.jsonl dump loop, the table and initTracker(). Shipped defaults unchanged: clean env is still the onlyPattern rack and movement is still strafe. GUARD: common_libs/tests/test_rack_stat_width.nim (24 checks) — rack table shape, a source scan proving no gun-indexed width/loop bound is narrower than NumRackGuns, an in-process accounting replay that would have overflowed array[17], and the legacy-namespace checks (id 16 via TR_RACK_BITBRAIN, id 17 never admitted while legacy). It reports 7 failures on the pre-fix ModularBot.nim and passes after. Optional --live section proves a rack admitting only the newest id fires and lands hits. Parity: test_env_report 25, test_rack_membership 49, test_lead_gain_ registration 13, test_lead_gain_legacy 24, test_bitbrain_net 44, test_gun_harness 39, test_tfil_commit_env 30, test_bitbrain 56, test_tm_pattern_registration 20 — all unchanged, 0 failures. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -286,18 +286,24 @@ type
|
||||
roundNumber: int
|
||||
realShotsFired: int
|
||||
realHits: int
|
||||
gunRealShots: array[17, int]
|
||||
gunRealHits: array[17, int]
|
||||
gunRealShots: array[NumRackGuns, int]
|
||||
gunRealHits: array[NumRackGuns, int]
|
||||
# Same real-shot accounting split by the rack in force at fire time, so a
|
||||
# later data-driven pass can rank guns per mode (1v1 vs melee).
|
||||
gunRealShotsByMode: array[vb.RackMode, array[17, int]]
|
||||
gunRealHitsByMode: array[vb.RackMode, array[17, int]]
|
||||
# These four arrays and `gunSelectionCount` are indexed by SELECTED GUN ID,
|
||||
# so their width is `NumRackGuns`, not a literal. A literal `array[17, int]`
|
||||
# survived the addition of rack id 17 (BITBRAIN) and indexed one past the end
|
||||
# on the first tick that gun was selected — an IndexDefect in a debug build
|
||||
# and silent corruption of the adjacent `lastPowerLogKey` string in the
|
||||
# shipped `-d:release` binary, i.e. a bot that aims, moves and never fires.
|
||||
gunRealShotsByMode: array[vb.RackMode, array[NumRackGuns, int]]
|
||||
gunRealHitsByMode: array[vb.RackMode, array[NumRackGuns, int]]
|
||||
pendingFires: seq[PendingShot] ## FIFO of fired shots awaiting onBulletFired bulletId stamp
|
||||
bulletGun: Table[int, int] ## bulletId -> gun id, filled on onBulletFired, drained on resolution
|
||||
bulletMode: Table[int, vb.RackMode] ## bulletId -> rack at fire time
|
||||
bulletShot: Table[int, PendingShot] ## bulletId -> shot metadata (Task A shot log)
|
||||
pendingHitBullets: HashSet[int] ## hit bulletIds seen before their onBulletFired stamp
|
||||
gunSelectionCount: array[17, int]
|
||||
gunSelectionCount: array[NumRackGuns, int]
|
||||
lastPowerLogKey: string ## change detector for the TR_POWER_LOG line
|
||||
lastKnownTargetId: int ## persists through death, used for round-end stats
|
||||
# Radar measurement instrumentation (only touched when RadarScanLog is set).
|
||||
@@ -790,7 +796,7 @@ method onRoundEnded*(bot: ModularBot, e: RoundEndedEventForBot) =
|
||||
let fit = bot.tracker.fitnessFor(targetId)
|
||||
|
||||
var gunsArr = newJArray()
|
||||
for gid in 0..<17:
|
||||
for gid in 0..<NumRackGuns:
|
||||
var totalShots = 0
|
||||
var totalHits = 0
|
||||
for binIdx in 0..<len(vb.PowerBins):
|
||||
@@ -911,12 +917,12 @@ method onRoundStarted*(bot: ModularBot, e: RoundStartedEvent) =
|
||||
bot.radarAcquireTicks = 0
|
||||
bot.radarTrackTicks = 0
|
||||
bot.radarMeleeActive = false
|
||||
for i in 0..<17:
|
||||
for i in 0..<NumRackGuns:
|
||||
bot.gunSelectionCount[i] = 0
|
||||
bot.gunRealShots[i] = 0
|
||||
bot.gunRealHits[i] = 0
|
||||
for m in vb.RackMode:
|
||||
for i in 0..<17:
|
||||
for i in 0..<NumRackGuns:
|
||||
bot.gunRealShotsByMode[m][i] = 0
|
||||
bot.gunRealHitsByMode[m][i] = 0
|
||||
# Reset per-round integrity counters so each /tmp/gun_stats.jsonl line reports
|
||||
@@ -1304,8 +1310,8 @@ method run*(bot: ModularBot) =
|
||||
# owning gun's onResult, so attribution survives a mid-round rack change.
|
||||
# TMPATTERN and TMHORIZON keep their own admission gate even when the knob
|
||||
# is 0, so TR_VBULLET_ADMIT_ONLY=0 reproduces the exact pre-change rack.
|
||||
var admit: array[18, bool]
|
||||
for gi in 0..<18:
|
||||
var admit: array[NumRackGuns, bool]
|
||||
for gi in 0..<NumRackGuns:
|
||||
admit[gi] = ModuleVBullets and
|
||||
vBulletAdmitted(gi, bot.rackMode, ActiveRackMembership,
|
||||
VBulletAdmitOnly or gi == TmPatternId or
|
||||
@@ -1534,7 +1540,7 @@ proc seedSelectorRng() =
|
||||
|
||||
when isMainModule:
|
||||
var bot = ModularBot(
|
||||
tracker: vb.initTracker(18), # 0: HeadOn, 1: Linear, 2: Tsetlin, 3: Circular, 4: GuessFactor, 5: Pattern, 6: WallBounce, 7: Accel, 8: StopShot, 9: Displace, 10: AvgLead, 11: DecayGF, 12: KNN, 13: TMSelect, 14: TMPattern, 15: TMHorizon, 16: LeadGain, 17: BitBrainNet
|
||||
tracker: vb.initTracker(NumRackGuns), # 0: HeadOn, 1: Linear, 2: Tsetlin, 3: Circular, 4: GuessFactor, 5: Pattern, 6: WallBounce, 7: Accel, 8: StopShot, 9: Displace, 10: AvgLead, 11: DecayGF, 12: KNN, 13: TMSelect, 14: TMPattern, 15: TMHorizon, 16: LeadGain, 17: BitBrainNet
|
||||
headOn: HeadOnGun(),
|
||||
linear: LinearGun(),
|
||||
circular: CircularGun(),
|
||||
|
||||
Reference in New Issue
Block a user