j142 retire the ADE+SBC gun (rack id 17): the owner watched it, it does not learn, throw it away

Remove guns/bitbrain_net.nim (+README), test_bitbrain_net.nim,
measure_bitbrain_scaling.nim, rack id 17 and all of its plumbing in
selector.nim / ModularBot.nim / env_report.nim, the TR_BITBRAIN_NET switch
and the NEW-NETWORK TR_BITBRAIN_* knobs, and the BitBrainNet arm of
run_prediction_quality.nim.

With id 17 gone there is nothing to disambiguate, so the legacy namespace
becomes the ONLY one: TR_RACK_BITBRAIN always selects id 16 LEADGAIN and
every TR_BITBRAIN_<X> in the frozen 14-suffix alias set always means
TR_LEADGAIN_<X>. The alias layer and its [depr] line stay.

KEPT: the common_libs/bitbrain/ SBC library (learned_surfer imports
bitbrain/sbc), lead_gain at id 16 with env TR_LEADGAIN_* and log tag [lg],
and the c9b6753 crash fix (NumRackGuns widths + test_rack_stat_width).

Tombstone: docs/bitbrain_campaign.md ## RETIRED and one cross-reference line
in docs/gun_campaign.md. Shipped defaults unchanged: clean env -> rack
active 1v1 = PATTERN, movement default strafe.
This commit is contained in:
2026-09-26 19:20:23 +02:00
parent c9b67530db
commit 5e32ec16df
18 changed files with 279 additions and 1732 deletions
+5 -41
View File
@@ -31,7 +31,6 @@ import guns/tm_selector
import guns/tm_pattern
import guns/tm_horizon
import guns/lead_gain
import guns/bitbrain_net
import movements/phantom_meteor
import movements/rammer
import movements/ram_decision
@@ -151,7 +150,7 @@ let ResultLog* =
block:
let v = getEnv("TR_RESULT_LOG", "1").strip().toLowerAscii()
not (v == "0" or v == "false" or v == "no" or v == "off")
const GunNames = ["HeadOn", "Linear", "Tsetlin", "Circular", "GuessFactor", "Pattern", "WallBounce", "Accel", "StopShot", "Displace", "AvgLead", "DecayGF", "KNN", "TMSelect", "TMPattern", "TMHorizon", "LeadGain", "BitBrainNet"]
const GunNames = ["HeadOn", "Linear", "Tsetlin", "Circular", "GuessFactor", "Pattern", "WallBounce", "Accel", "StopShot", "Displace", "AvgLead", "DecayGF", "KNN", "TMSelect", "TMPattern", "TMHorizon", "LeadGain"]
## Rack id of the new TM pattern gun. It defaults to `TR_RACK_TMPATTERN=off`;
## unlike the other guns, its virtual-bullet spawn is gated on rack admission
@@ -171,20 +170,10 @@ const TmHorizonId = 15
## is unchanged). It defaults to `TR_RACK_LEADGAIN=off` and its virtual-bullet
## spawn is gated on rack admission, so the shipped default never spawns it and
## the shared tracker ring head — hence every other gun's learning order — is
## byte-for-byte unchanged. `TR_RACK_BITBRAIN` still selects it while
## `TR_BITBRAIN_NET` is off (backward compatibility; see `gun_harness/selector`).
## byte-for-byte unchanged. `TR_RACK_BITBRAIN` still selects it unconditionally
## (backward compatibility; see `gun_harness/selector`).
const LeadGainId = 16
## Rack id of the ADE+SBC gun — the gun that actually runs the algorithm
## (`guns/bitbrain_net.nim`). It takes the `BITBRAIN` name and the
## `TR_BITBRAIN_*` knob prefix that the renamed corrector gave up. TWO switches
## admit it, and both default off: `TR_RACK_BITBRAIN=both` in the rack table and
## `TR_BITBRAIN_NET=1` in the gun itself (the switch that also disowns the
## legacy `TR_BITBRAIN_*` aliases — see `gun_harness/selector`). Its
## virtual-bullet spawn is gated on rack admission, so the shipped default never
## spawns it and the shared tracker ring head is byte-for-byte unchanged.
const BitbrainNetId = 17
## ── virtual-bullet debug overlay (TR_VBULLET_DEBUG*) ───────────────────────
## OFF by default: the shipped bot draws nothing. When on, the tracker's
## virtual bullets are overlaid so the training signal the selector learns
@@ -257,7 +246,6 @@ type
tmPattern: TmPatternGun
tmHorizon: TmHorizonGun
leadGain: LeadGainGun
bbn: BitbrainNetGun
mover: TFILModule
ringMover: TFILRingModule
strafeMover: StrafeModule
@@ -961,7 +949,6 @@ method onRoundStarted*(bot: ModularBot, e: RoundStartedEvent) =
# LEADGAIN: per-round wipe always clears observations/labels; `perRound` mode
# also wipes its SBCs (the gate test's winning regime).
bot.leadGain.resetRoundState()
bot.bbn.resetRoundState()
if e.roundNumber <= 1:
bot.leadGain.resetLearning("round1")
bot.isRamming = false
@@ -1044,7 +1031,6 @@ method onGameStarted*(bot: ModularBot, e: GameStartedEventForBot) =
# boundary. The round-1 fallback in `onRoundStarted` covers a missed callback.
bot.tmHorizon.resetLearning("game_start")
bot.leadGain.resetLearning("game_start")
bot.bbn.resetLearning("game_start")
# minNumberOfParticipants == maxNumberOfParticipants for fixed battles; self is -1
bot.initialEnemyCount = e.gameSetup.minNumberOfParticipants - 1
# New battle: reset the cumulative outcome counters and remember how many
@@ -1153,7 +1139,6 @@ method run*(bot: ModularBot) =
# TR_TMHORIZON_RESET_ON_TARGET, default on; no-op in 1v1).
discard bot.tmHorizon.targetChanged(candidateId)
discard bot.leadGain.targetChanged(candidateId)
discard bot.bbn.targetChanged(candidateId)
if bot.currentTargetId >= 0:
bot.lastKnownTargetId = bot.currentTargetId
@@ -1298,7 +1283,6 @@ method run*(bot: ModularBot) =
var tmpPreds: array[len(PowerBins), GunPrediction]
var tmhPreds: array[len(PowerBins), GunPrediction]
var lgPreds: array[len(PowerBins), GunPrediction]
var bbnPreds: array[len(PowerBins), GunPrediction]
# ── TR_VBULLET_ADMIT_ONLY gate ──────────────────────────────────────
# Rack membership used to filter only SELECTION, so every unselected gun
# still ran predict()+spawnBullets() each tick to feed a fitness table the
@@ -1315,18 +1299,7 @@ method run*(bot: ModularBot) =
admit[gi] = ModuleVBullets and
vBulletAdmitted(gi, bot.rackMode, ActiveRackMembership,
VBulletAdmitOnly or gi == TmPatternId or
gi == TmHorizonId or gi == LeadGainId or
gi == BitbrainNetId) and
# BITBRAIN (id 17) needs BOTH switches. The rack table alone
# is not enough: a pre-rename `.env` still carries
# `TR_RACK_BITBRAIN=both` (it used to select LEADGAIN), and
# admitting a DISABLED gun would let its placeholder
# predictions into the shared VirtualTracker ring and shift
# every other gun's learning order. With this gate an
# incomplete configuration is exactly as inert as an unset
# one.
(gi != BitbrainNetId or
bot.bbn.gunAdmitted(true))
gi == TmHorizonId or gi == LeadGainId)
for i in 0..<len(PowerBins):
if admit[0]: headsUp[i] = bot.headOn.predict(bot.lastState, bulletSpeed(PowerBins[i]))
if admit[1]: linPreds[i] = bot.linear.predict(bot.lastState, bulletSpeed(PowerBins[i]))
@@ -1352,9 +1325,6 @@ method run*(bot: ModularBot) =
# LEADGAIN: Pattern base, lead scaled by a per-band learned gain.
if admit[LeadGainId]:
lgPreds[i] = bot.leadGain.predict(bot.lastState, bulletSpeed(PowerBins[i]))
# BITBRAIN: Pattern base + a fine-grained ADE/SBC angular correction.
if admit[BitbrainNetId]:
bbnPreds[i] = bot.bbn.predict(bot.lastState, bulletSpeed(PowerBins[i]))
if admit[0]: bot.tracker.spawnBullets(0, headsUp, bot.lastState, tid)
if admit[1] and not gunDisabled(1): bot.tracker.spawnBullets(1, linPreds, bot.lastState, tid)
@@ -1378,8 +1348,6 @@ method run*(bot: ModularBot) =
bot.tracker.spawnBullets(TmHorizonId, tmhPreds, bot.lastState, tid)
if admit[LeadGainId] and not gunDisabled(LeadGainId):
bot.tracker.spawnBullets(LeadGainId, lgPreds, bot.lastState, tid)
if admit[BitbrainNetId] and not gunDisabled(BitbrainNetId):
bot.tracker.spawnBullets(BitbrainNetId, bbnPreds, bot.lastState, tid)
# Build slim enemy table for tickBullets
var enemyPositions: Table[int, tuple[x, y: float, lastSeenTick: int, alive: bool]]
@@ -1416,7 +1384,6 @@ method run*(bot: ModularBot) =
of TmPatternId: bot.tmPattern.onResult(fe)
of TmHorizonId: bot.tmHorizon.onResult(fe)
of LeadGainId: bot.leadGain.onResult(fe)
of BitbrainNetId: bot.bbn.onResult(fe)
else: discard
if fe.hit: inc bot.virtualHits else: inc bot.virtualMiss
if DebugDrawOn and VBulletDebugOn:
@@ -1472,7 +1439,6 @@ method run*(bot: ModularBot) =
of TmPatternId: bot.tmPattern.predict(bot.lastState, bulletSpeed(power))
of TmHorizonId: bot.tmHorizon.predict(bot.lastState, bulletSpeed(power))
of LeadGainId: bot.leadGain.predict(bot.lastState, bulletSpeed(power))
of BitbrainNetId: bot.bbn.predict(bot.lastState, bulletSpeed(power))
else: bot.headOn.predict(bot.lastState, bulletSpeed(power))
let aimTarget = aimAngle(getX(), getY(), pred.x, pred.y)
@@ -1540,7 +1506,7 @@ proc seedSelectorRng() =
when isMainModule:
var bot = ModularBot(
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
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
headOn: HeadOnGun(),
linear: LinearGun(),
circular: CircularGun(),
@@ -1558,7 +1524,6 @@ when isMainModule:
tmPattern: initTmRadialGun(),
tmHorizon: initTmHorizonGun(),
leadGain: initLeadGainGun(),
bbn: initBitbrainNetGun(),
radar: RadarLockModule(),
meleeRadar: initAdaptiveMeleeRadar(),
mover: TFILModule(debugGraphics: DebugDrawOn),
@@ -1598,6 +1563,5 @@ when isMainModule:
tmHorizon: bot.tmHorizon,
patternMatcher: bot.patternMatcher,
leadGain: bot.leadGain,
bitbrainNet: bot.bbn,
))
start(bot, botJsonPath)