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:
@@ -546,6 +546,19 @@ proc ringValidCount*(g: TmHorizonGun): int =
|
||||
for i in 0..<TMH_POS_RING:
|
||||
if g.ringValid[i]: inc result
|
||||
|
||||
proc tmhObservedAt*(g: TmHorizonGun, tick: int, selfX, selfY: float
|
||||
): tuple[ok: bool, bearing, dist: float, lastSeenTick: int] =
|
||||
## Exported seam for the BitBrain corrector: the enemy's OBSERVED bearing and
|
||||
## distance (relative to `(selfX, selfY)`) at `tick`, if the observation ring
|
||||
## holds that exact tick. `lastSeenTick` lets the caller apply the same
|
||||
## staleness rule TMHorizon uses before trusting the label. `ok = false` when
|
||||
## the tick is missing (e.g. across a round boundary or before warm-up).
|
||||
let r = g.ringAt(tick)
|
||||
if not r.ok:
|
||||
return (false, 0.0, 0.0, 0)
|
||||
(true, arctan2(r.t.ey - selfY, r.t.ex - selfX),
|
||||
hypot(r.t.ex - selfX, r.t.ey - selfY), r.t.lastSeenTick)
|
||||
|
||||
proc ringHas*(g: TmHorizonGun, tick: int): bool =
|
||||
## Observability / test seam: is there a valid observation exactly at `tick`?
|
||||
## Used to prove a round boundary drops the old positions (so a label can never
|
||||
@@ -598,7 +611,7 @@ proc bulletFeatures(g: var TmHorizonGun, state: WorldState): tuple[tta: int, lat
|
||||
result.lat = b.ux * vy - b.uy * vx
|
||||
g.bulletCount = w
|
||||
|
||||
proc tmhUpdateHistory(g: var TmHorizonGun, state: WorldState) =
|
||||
proc tmhUpdateHistory*(g: var TmHorizonGun, state: WorldState) =
|
||||
## Once per tick: write the observation ring, advance the reversal counter and
|
||||
## the self-energy-drop bullet proxy.
|
||||
let slot = ((state.tick mod TMH_POS_RING) + TMH_POS_RING) mod TMH_POS_RING
|
||||
|
||||
Reference in New Issue
Block a user