Files
SirRoboGarage/ModularBot_garage
SirStone 994f88d7a7 ramming: make the decision PROACTIVE, with a bullet-rain abort
The user watched 1v1 and melee runs and saw ram opportunities arise that the bot
declined: "there were moments where the bot could jump over the enemy and shred
it but shot it down instead."

DIAGNOSIS - a chicken-and-egg loop. `ramOpportunity` required dist < 50px, but
an offline measurement over 15 rounds vs DrussGT found the closest approach was
118.7px and the <50px trigger had NEVER fired: the mover has no reason to close,
so the trigger waited for a proximity nothing created. The MECHANISM to close
already existed (the ring mover expresses a ram as band=(0,50)); what was
missing was a decision that fires at a range the bot can actually close from.

Changes:
- opportunity gate relaxed: dist 50 -> TR_RAM_OPP_DIST (200), energy margin
  +30 -> TR_RAM_OPP_MARGIN (15). Both env-tunable, no rebuild needed.
- New pure module `common_libs/movements/ram_decision.nim` holding the trigger
  and abort logic (no battle/API deps), so it is unit-testable.
- BULLET-RAIN ABORT (the user asked for this earlier): `onHitByBullet` now
  accumulates `e.bullet.power` into a 15-turn ring; damageRatePerTurn = sum/15;
  an in-progress ram aborts when rate > TR_RAM_ABORT_DMG (0.5/turn). On abort:
  isRamming=false, cooldown 30, TARGET KEPT, and the mover returns to the normal
  range band. It never stops the bot.
- Opt-in, DEFAULT-OFF `plan` trigger for "change of plan when the gun duel is
  failing" (dist<250, margin+20, selected gun's pooled virtual rate < 0.05).
  Left off because a cold gun reads 0.0 and would qualify - speculative.
- `TR_RAM_LOG=1` change-gated line: `[ram] ON reason=opportunity dist=143
  selfE=78 enemyE=41 cap=3.0 band=[0,50]` / `[ram] OFF reason=bulletRain`.
- Existing cooldown/duration/stuck machinery untouched (stuck>10 or duration>60
  -> abort + cooldown 30). A refactor bug that briefly DROPPED the
  `ramCooldownTicks == 0` gate was caught and fixed.

Trigger set (first match wins): finisher (dist<300, enemy<20, we are healthier);
opportunity (dist<200, we lead by 15+); desperation (both <5, dist<150); plan
(off). All require enemy>0, a valid target, and no cooldown.

Proof the intent now fires at a closable distance (28/28 unit checks):
  PASS: opportunity fires at dist 143 with a 37-energy lead   <- the exact case
  PASS: old gate (dist<50, margin+30) does NOT fire at 143    <- the old bug
  PASS: fires at 199px / does NOT fire at 201px
  + margin, finisher priority, desperation, plan on/off, window mean, abort
    threshold checks.

HONEST FRAMING: ram damage is 0.6 per CONTACT EVENT, one-shot (collision
resolution rewinds positions so contacts do not stream) - small next to a p=3.0
bullet hit (16). The payoff is that point-blank forces hit probability toward 1,
so heavy bullets stop missing and E[dE]=p(3P-1) turns positive above P=1/3; ram
damage also scores 2.0/point (highest in the game) and a ram kill carries a 0.30
bonus vs 0.20. So this is "force the fight to point-blank", not "the ram shreds
them". Base rate is rare (2 collisions in the whole fixture corpus).

Guards: test_ram_decision 28 (new), test_power_policy 26, test_gun_harness 39,
test_vbullet_metric 11, test_power_selection 3, test_adaptive_radar 41,
test_tfil_ring_weights 24. Compiles (release).
UNVERIFIED: the live effect. No A/B has run, and whether the mover actually
reaches contact is unproven.
2026-09-22 00:24:45 +02:00
..