BitBrain gun (id 16): Pattern-relative ADE+SBC aim corrector, default off

Wire the verified common_libs/bitbrain ADE+SBC library into ModularBot as a
fine-grained angular corrector on top of Pattern's prediction, the shape the
offline gate test measured (argmax readout over N correction classes).

- common_libs/guns/bitbrain_gun.nim: new gun. Input = the existing TMHorizon
  53 bits (tmhBaseBits + tmhLits); output = argmax class centre over
  +-TR_BITBRAIN_RANGE, applied by rotating the Pattern point around the shooter
  exactly as tmhApplyShift does. Label = the +h-tick fact from TmHorizonGun's
  own observation ring (never across a round). Prequential (defer + resolve).
  AD layer synthesised online for our binary inputs (center=0): heuristic
  cold-start thresholds + running-histogram ~1% percentile init + the library's
  adaptThresholds. Memory modes perRound (default, measured best) / retained /
  decay (periodic partial SBC wipe). Lazy network build + local RNG, so the
  default path builds nothing and consumes no global randomness.
- tm_horizon.nim: export tmhUpdateHistory and add tmhObservedAt (label seam).
- selector.nim: register BITBRAIN at rack id 16, default rmOff, in the SAME
  commit as the id and the wiring (the aed579b admission bug is not repeated).
- ModularBot.nim: id 16 wired through predict/spawn/onResult/resets/colors,
  arrays grown 16->17, spawn gated on rack admission, per-round/per-battle/
  target reset hooks.
- env_report.nim: report every TR_BITBRAIN_* knob + add names to the known set.
- tests: update the rack length literals; new test_bitbrain_registration
  (default-parity: off, lazy, global-RNG clean).

Guard counts unchanged: rack 48, tm_pattern_registration 20, vbullet_admit 12,
env_report 25, and the rest of the suite green.
This commit is contained in:
2026-09-24 22:25:04 +02:00
parent 1fec87537d
commit 795a0e59fe
8 changed files with 721 additions and 28 deletions
+6 -6
View File
@@ -158,14 +158,14 @@ proc testDefaultsOnlyPattern() =
DefaultRackMembership[12] == rmOff and DefaultRackMembership[13] == rmOff and
DefaultRackMembership[14] == rmOff
check "defaults: the default rack admits ONLY Pattern in 1v1",
admittedGuns(15, rm1v1, DefaultRackMembership) == @[PatternId]
admittedGuns(17, rm1v1, DefaultRackMembership) == @[PatternId]
check "defaults: the default rack admits ONLY Pattern in melee",
admittedGuns(15, rmMelee, DefaultRackMembership) == @[PatternId]
admittedGuns(17, rmMelee, DefaultRackMembership) == @[PatternId]
let loaded = loadRackMembership()
check "defaults: with a clean environment loadRackMembership() == shipped table",
loaded == DefaultRackMembership
check "defaults: RackGunNames covers the shipped 16-gun rack",
RackGunNames.len == 16 and DefaultRackMembership.len == 16
check "defaults: RackGunNames covers the shipped 17-gun rack",
RackGunNames.len == 17 and DefaultRackMembership.len == 17
proc testFloorRespectsAdmission() =
## The FLOOR path (`bestRate <= 0` or below the floor rate) historically fell
@@ -212,8 +212,8 @@ proc testRevertOverrideRestoresFullRack() =
let want = if i == 14: rmOff else: rmBoth
if m[i] != want: full = false
check "revert: the documented one-liner restores the all-`both` full rack", full
check "revert: 1v1 rack admits every gun again (all 14, TMPATTERN excluded)",
admittedGuns(15, rm1v1, m) == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
check "revert: 1v1 rack admits every gun again (TMPATTERN excluded)",
admittedGuns(17, rm1v1, m) == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16]
clearRackEnv()
proc testEnvOverrides() =