TM radial gun: registered (default OFF) + label-bias fix that removes the bias but
retracts its own earlier learning claim === TASK 1: REGISTERED AS GUN 14, DEFAULT `off` === The radial TM gun is now a first-class rack member (`TMPATTERN`, id 14), forceable alone with `TR_RACK_TMPATTERN=both` plus every other `TR_RACK_*=off`. DEFAULT IS `off`, and the justification matters: `both` would let it compete for selection AND (because the shared VirtualTracker ring is order-sensitive) shift every other gun's learning order, so it CANNOT leave the default path unchanged. With `off` its predict and spawnBullets are additionally GATED on rack admission (the only gun wired that way), so the shipped default never spawns it at all: zero cost, zero ring perturbation. Live proof: 1-round battle with only TMPATTERN racked -> `gun 14 (TMPattern): vShots=400 selected=104 other-gun selections=0`. Default-path-unchanged proof: parity checks that the 15-gun default bestGun/ selectGun equals the old 14-gun rack RNG-draw-for-RNG-draw, that gun 14 is never selected by default, and acceptance 12/12. Cost: 0.36 ms/tick (predict 0.30 + onResult 0.05) ~= 3% of the 13.16 ms budget. Tsetlin in the same harness is 1.62 ms/tick, so the new gun is ~4.5x cheaper. === TASK 2: THE LABEL-BIAS FIX - AND A RETRACTION === Root cause confirmed: under bmPoint a SHORT radial correction resolves the virtual bullet BEFORE the base arrival tick, so the label was dropped (labelMisses). Fix: defer the label in a pending queue and flush it once the arrival tick is recorded; labels still come from the BASE arrival tick. labelMisses 4,281,695 -> 0 training samples 1,071,824 -> 5,345,847 (x5) radial head acc 48.8% -> 57.0% (shuffled control 20.0%) bmPoint hit rate 9.4/5.8% -> 9.1/5.7% (unchanged, within noise) So the fix IMPROVES LEARNING but NOT the metric. **RETRACTION OF THE PREVIOUS JOB'S CLAIM.** It reported the radial head's 48.8% against a 36.7% majority baseline and concluded "conditional learning, not a constant bias". With the bias removed, the correctly-measured majority baseline is **58.2%** - so the head at 57.0% is AT/BELOW majority. The earlier apparent conditional learning was PARTLY AN ARTEFACT OF THE BIASED SAMPLE. The bmPoint metric win is real (TMRadial > Linear early 16/2 p=0.0013, overall 18/0 p<0.0001; > shuffled 18/0 p<0.0001) but it comes from a NET-POSITIVE AVERAGE RADIAL SHIFT, not from beating a majority classifier. Recorded plainly rather than left standing. Guards: test_tm_pattern_registration 20 (new), test_tm_pattern_rack_live 4 (new), test_gun_harness 39, test_vbullet_metric 11, test_power_selection 3 (the SIGSEGV is gone - the knn_gun rewrite is now committed), test_adaptive_radar 41, test_tfil_ring_weights 24, test_power_policy 26, test_ram_decision 28, test_rack_membership 38, test_selector_tiebreak 19, test_tm_pattern_learning 3, acceptance_offline_vs_online 12/12. ModularBot compiles (release). Note: `common_libs/tests/range_guns.nim` still builds 14 offline drivers (the offline sweep constructs TmPatternGun directly and acceptance only inspects ids 0..13), so nothing breaks - but a future job wanting it in the offline rack must add a 15th driver and mirror the live admission gating. gun_stats.jsonl now emits 15 rows; downstream tooling should ignore id 14.
This commit is contained in:
@@ -19,21 +19,30 @@ import virtual_bullets
|
||||
# TR_RACK_TSETLIN=1v1 -> 1v1 rack only
|
||||
# TR_RACK_DISPLACE=melee -> melee rack only
|
||||
# TR_RACK_KNN=off -> removed from both racks
|
||||
# TR_RACK_TMPATTERN=off (shipped default for the new TM pattern gun)
|
||||
#
|
||||
# The mode itself is derived from SERVER truth (`getEnemyCount()`), never from
|
||||
# the tracker's known-enemy count, by `rackMode` in virtual_bullets — the same
|
||||
# transition the radar uses. Defaults are all-`both`, so an unset environment
|
||||
# preserves the pre-change single-rack selection byte-for-byte.
|
||||
# transition the radar uses. Every gun except TMPATTERN defaults to `both`, so an
|
||||
# unset environment preserves the pre-change single-rack selection byte-for-byte;
|
||||
# TMPATTERN defaults to `off` so it cannot alter that selection.
|
||||
|
||||
const
|
||||
RackGunNames*: array[14, string] = [
|
||||
RackGunNames*: array[15, string] = [
|
||||
"HEADON", "LINEAR", "TSETLIN", "CIRCULAR", "GUESSFACTOR", "PATTERN",
|
||||
"WALLBOUNCE", "ACCEL", "STOPSHOT", "DISPLACE", "AVGLEAD", "DECAYGF",
|
||||
"KNN", "TMSELECT"]
|
||||
"KNN", "TMSELECT", "TMPATTERN"]
|
||||
RackEnvPrefix* = "TR_RACK_"
|
||||
DefaultRackMembership*: array[14, RackMembership] = [
|
||||
## Defaults are all-`both` EXCEPT the new TM pattern gun (id 14), which ships
|
||||
## `off`: it is registered and forceable (`TR_RACK_TMPATTERN=both|1v1|melee`)
|
||||
## but never spawns a virtual bullet unless explicitly enabled, so the shared
|
||||
## VirtualTracker ring head — and therefore every other gun's learning order
|
||||
## and the default selection sequence — is byte-for-byte unchanged. Defaulting
|
||||
## it to `both` would let it compete for selection and change the default rack.
|
||||
DefaultRackMembership*: array[15, RackMembership] = [
|
||||
rmBoth, rmBoth, rmBoth, rmBoth, rmBoth, rmBoth, rmBoth,
|
||||
rmBoth, rmBoth, rmBoth, rmBoth, rmBoth, rmBoth, rmBoth]
|
||||
rmBoth, rmBoth, rmBoth, rmBoth, rmBoth, rmBoth, rmBoth,
|
||||
rmOff]
|
||||
|
||||
proc parseRackMembership*(value: string): RackMembership =
|
||||
## Parse a `TR_RACK_<GUN>` value. Empty / unknown values fall back to the
|
||||
|
||||
Reference in New Issue
Block a user