j127: forced-share allocator (TR_RACK_SHARE, default-off) + allocation batch pre-registration
This commit is contained in:
@@ -402,6 +402,11 @@ type
|
||||
# reads/writes these; `bestGun`/`chooseFromFit` stay memoryless.
|
||||
currentGun*: GunId
|
||||
currentSince*: int
|
||||
# Forced-share allocator state (`TR_RACK_SHARE`, see `selectSharedGun`).
|
||||
# `shareDeficit` accumulates one round of weights per allocation EPOCH; the
|
||||
# chosen gun has 1.0 subtracted, so the long-run allocation follows the
|
||||
# weights exactly. Empty/unused when the share is inactive.
|
||||
shareDeficit*: seq[float]
|
||||
|
||||
proc initTracker*(numGuns: int, metric = ActiveMetric): VirtualTracker =
|
||||
## `metric` defaults to the process-wide `GUN_VBULLET_METRIC` switch; pass it
|
||||
@@ -1175,10 +1180,52 @@ proc bestGun*(t: VirtualTracker, targetId: int = -1,
|
||||
referenceRate = t.peakRateRef,
|
||||
rackMode = rackMode, membership = membership)
|
||||
|
||||
proc selectSharedGun*(t: var VirtualTracker, share: openArray[float],
|
||||
tick: int, rackMode: RackMode,
|
||||
membership: openArray[RackMembership]): GunId =
|
||||
## Forced-share allocation (`TR_RACK_SHARE`). Deterministic deficit
|
||||
## round-robin over the named guns that the CURRENT rack admits; returns -1
|
||||
## when no named gun is admitted (caller falls back to the normal ranking).
|
||||
##
|
||||
## The schedule advances once per allocation EPOCH, not once per tick: the
|
||||
## incumbent is held for `ActiveDwellTicks`, so the turret converges on the
|
||||
## allocated gun before the next allocation — the same anti-chatter reason the
|
||||
## shipped hysteresis exists. Selected-tick counts therefore follow the weight
|
||||
## ratio, which is what `gun_stats.jsonl` reports as `selected`.
|
||||
var guns: seq[GunId]
|
||||
var total = 0.0
|
||||
for g in 0..<share.len:
|
||||
if share[g] > 0.0 and rackAdmitted(g, rackMode, membership):
|
||||
guns.add g
|
||||
total += share[g]
|
||||
if guns.len == 0 or total <= 0.0: return -1
|
||||
|
||||
# Hold the incumbent through its dwell window (it is already one of the
|
||||
# admitted share guns). This is what keeps aim convergence; the deficit below
|
||||
# is NOT advanced on a held tick.
|
||||
if t.currentGun in guns and (tick - t.currentSince) < ActiveDwellTicks:
|
||||
return t.currentGun
|
||||
|
||||
if t.shareDeficit.len != share.len:
|
||||
t.shareDeficit.setLen(share.len)
|
||||
for g in guns:
|
||||
t.shareDeficit[g] += share[g] / total
|
||||
var pick = guns[0]
|
||||
var best = t.shareDeficit[pick]
|
||||
for g in guns:
|
||||
if t.shareDeficit[g] > best:
|
||||
best = t.shareDeficit[g]
|
||||
pick = g
|
||||
t.shareDeficit[pick] -= 1.0
|
||||
t.currentGun = pick
|
||||
t.currentSince = tick
|
||||
result = pick
|
||||
|
||||
proc selectGun*(t: var VirtualTracker, targetId: int = -1, tick = 0,
|
||||
diag: ptr SelectorDiag = nil,
|
||||
rackMode: RackMode = rm1v1,
|
||||
membership: openArray[RackMembership] = []): GunId =
|
||||
membership: openArray[RackMembership] = [],
|
||||
share: seq[float] = @[]): GunId =
|
||||
## Stateful, sticky gun selection — the LIVE path (`selector.selectShot` calls
|
||||
## this). Wraps the pure `chooseFromFit` ranking with two commitments:
|
||||
##
|
||||
@@ -1198,6 +1245,13 @@ proc selectGun*(t: var VirtualTracker, targetId: int = -1, tick = 0,
|
||||
## `peakRateRef` history) and is threaded through the whole live loop; the bot
|
||||
## does not need to know about it. `bestGun`/`chooseFromFit` stay pure for the
|
||||
## offline tools.
|
||||
##
|
||||
## `share` (non-empty) is the `TR_RACK_SHARE` forced allocation: it bypasses
|
||||
## `chooseFromFit` entirely (see `selectSharedGun`). Empty is the shipped
|
||||
## ranking path, byte-for-byte.
|
||||
if share.len > 0:
|
||||
let shared = t.selectSharedGun(share, tick, rackMode, membership)
|
||||
if shared >= 0: return shared
|
||||
let fit = t.fitnessFor(targetId)
|
||||
var local: SelectorDiag
|
||||
let d = if diag != nil: diag else: addr local
|
||||
|
||||
Reference in New Issue
Block a user