Files
SirRoboGarage/ModularBot_garage/.env.example
T
SirStone d2005abee9 j144 TFIL: arrival-based commitment + hysteresis + no mid-flight reversal
The owner's live-GUI report was correct on all four counts, and all four are
one bug: the commitment is cancelled by our own tile-boundary crossing
(96.1% of picks, 3793/3946, mean hold 5.06 ticks) while the bot is still
accelerating, and the picker is an unconstrained uniform draw over every
safe tile, so the new target can land in the mirror direction at |speed| < 4.

New knobs, all env-gated and default = today's behaviour (byte-for-byte
default parity guard re-run and green, 51 checks):
  TR_TFIL_COMMIT_ARRIVAL  hold the committed tile until we are ON it; the
                          tick knob becomes a MINIMUM dwell. 0 = shipped.
  TR_TFIL_COMMIT_MARGIN   leave only if the best alternative is at least
                          this much cooler on the same pathMaxHeat scale.
                          0 = shipped.
  TR_TFIL_NOREV_SPEED     while |speed| is below this, a mid-flight switch
                          may not take a tile >90 deg off the travel
                          direction. 0 = shipped. norevPool() never returns
                          an empty pool: with every candidate behind us it
                          takes the least-bad turn.

Offline gate (recorded DrussGT fixture, 20026 ticks): mean hold 4.1 -> 24.0
ticks, abandoned-before-arrival 92.8% -> 40.5%, committed tile actually
reached 3.3% -> 17.2%, opposite-direction slow mid-flight switches 394 -> 64
(-84%). 'TR_TFIL_TILE_REPLAN=off' alone - what cc11ede's arm B already tried -
only gets the hold to 13.6, which is why that A/B could not find this.

strafe is untouched: it imports only heatDecay/bulletMagScale/Pillar*, none
of which this touches. TR_MOVEMENT default stays strafe. Registered in
env_report.nim + knownEnvNames() + .env.example. Arms pre-registered in
docs/movement_campaign.md and tools/ab/arms_tfil_commit.txt.
2026-09-26 21:07:09 +02:00

264 lines
18 KiB
Bash

# ModularBot environment — EVERY knob the bot reads, already set to its default.
#
# cp .env.example .env
#
# The bot reads `.env` from its own folder automatically when you start it from
# there. To use a different file: ./out/ModularBot --env-file /path/to/my.env
# The FILE WINS over variables you exported in the shell: if a shell value
# differs, the bot prints one override line at boot so you know it happened.
#
# Every value below IS the built-in default, so running the bot with this file
# is identical to a clean run with no file at all. Delete a line (or comment it
# out with #) and that knob falls back to the built-in default. An inline
# `# comment` after a value is fine — the loader strips it.
#
# A few switches are PRESENCE-only (`existsEnv`): for those, OFF means the line
# is absent, so they are shown commented out. Writing `=0` would still turn them
# ON.
#
# SNAPSHOT of the code at commit 5e32ec1. Regenerate this file whenever a default
# changes, or it will start lying.
# ── movement ─────────────────────────────────────────────────────────────────
# Which dodging engine runs: tfil, tfil_ring, strafe, surf or learned.
TR_MOVEMENT=strafe
# Whole-engine on/off switches. 0 removes an engine from the TR_MOVEMENT choices.
TR_MODULE_MOVE_TFIL=on # the long-shipped "floor is lava" engine
TR_MODULE_MOVE_TFIL_RING=on # the same, re-weighted toward a target range
TR_MODULE_MOVE_STRAFE=on # perpendicular strafe with sign-flip reversals
TR_MODULE_MOVE_SURF=on # wave surfing, steered by the GuessFactor
TR_MODULE_MOVE_LEARNED=on # learned per-state danger field
# ── gun rack: which guns the bot may choose (off | 1v1 | melee | both) ───────
# The shipped rack is Pattern only. Turn a gun on with `both`.
TR_RACK_PATTERN=both # the only admitted gun; both = usable in 1v1 and melee
TR_RACK_HEADON=off # aim straight at the target, no lead
TR_RACK_LINEAR=off # constant-angle linear aim
TR_RACK_TSETLIN=off # Tsetlin automaton gun
TR_RACK_CIRCULAR=off # assumes the enemy circles
TR_RACK_GUESSFACTOR=off # learns the wave-surfing GF of the enemy
TR_RACK_WALLBOUNCE=off # predicts a rebound off the arena wall
TR_RACK_ACCEL=off # leads a bullet that is still accelerating
TR_RACK_STOPSHOT=off # fires only when it expects a full stop
TR_RACK_DISPLACE=off # leads a displaced enemy
TR_RACK_AVGLEAD=off # averaged lead over recent shots
TR_RACK_DECAYGF=off # GuessFactor with a forgetting decay
TR_RACK_KNN=off # nearest-neighbour over past gun states
TR_RACK_TMSELECT=off # Tsetlin machine used as the shot selector
TR_RACK_TMPATTERN=off # Tsetlin machine used as a pattern matcher
TR_RACK_TMHORIZON=off # horizon Tsetlin automata gun
TR_RACK_LEADGAIN=off # per-range-band learned lead-gain corrector
# Give every admitted gun a fixed share of the turns instead of ranking them,
# e.g. TR_RACK_SHARE=PATTERN:60%,HEADON:40%. Empty = the ranking selector.
TR_RACK_SHARE=
# Drop whole guns by rack id (comma separated, e.g. 16). Empty = keep them all.
GUN_RACK_DISABLE=
# ── gun selector (which admitted gun fires this tick) ───────────────────────
GUN_VBULLET_METRIC=path # fitness measure: path (time-to-collision) or point
GUN_SELECTOR_MODE=relative # rank guns against the incumbent (absolute = vs a fixed bar)
GUN_SELECTOR_WINDOW=100 # ticks of virtual-bullet history behind the fitness
GUN_SELECTOR_MINOBS=50 # observations a gun needs before it may compete
GUN_SELECTOR_TIE=0.2 # relative margin two guns must differ by to count as separated
GUN_SELECTOR_FLOOR=0.25 # fitness fraction of the peak below which a band is unsafe
GUN_SELECTOR_POOL=on # pool the per-tick samples over the window instead of replacing
GUN_SELECTOR_RANK=mean # how to rank guns: mean, wilson, ucb, thompson or shrunk
GUN_SELECTOR_SHRINK=20.0 # pseudo-count the shrunk rank adds per prior observation
GUN_SELECTOR_DWELL=10 # ticks a gun must lead before it can be switched away from
GUN_SELECTOR_MARGIN=0.05 # fraction the challenger must beat the incumbent by
GUN_SELECTOR_TIEBREAK=off # off, point or pointCommit: break ties on arrival accuracy
GUN_SELECTOR_POINT_TIE=0.5 # relative width of the point band used by the tie-break
# Seed for the selector's tie-breaks. Empty = seed from the clock + pid.
GUN_SELECTOR_SEED=
# ── power / energy policy ────────────────────────────────────────────────────
# Every rule below only ever CAPS power; the gun's own preference is the ceiling.
TR_POWER_POLICY=on # 0 = no cap at all (the control arm)
TR_POWER_FAR_DIST=200.0 # px; past this the enemy is in the bad-chances zone
TR_POWER_FAR_CAP=1.0 # cap applied past TR_POWER_FAR_DIST
TR_POWER_MID_CAP=2.0 # cap when close and healthy but not above its average
TR_POWER_REF=0.0 # 0 = the gun's own mean; >0 = that fixed reference power
TR_POWER_ENERGY_HI=80.0 # our energy at/above which the energy slope stops capping
TR_POWER_ENERGY_LO=20.0 # our energy at/below which the cap is TR_POWER_ENERGY_MIN
TR_POWER_ENERGY_MIN=0.5 # NOTE: this is a CEILING, not a floor — low energy, low power
TR_POWER_ENERGY_MAX=3.0 # the cap at/above ENERGY_HI; 3.0 means effectively uncapped
TR_POWER_FINISH_KILL=on # cap to the smallest bullet that still kills a low-energy enemy
# ── radar ────────────────────────────────────────────────────────────────────
#TR_RADAR_FORCE_SPIN=1 # presence-only: force the old full 360 spin instead of 1v1 lock
TR_RADAR_SCAN_LOG_PATH=/tmp/radar_scan_log.jsonl # where the per-tick scan log is written
# ── ram ──────────────────────────────────────────────────────────────────────
TR_MODULE_RAM=on # 0 = never ram; the movement engine alone drives
TR_RAM_OPPORTUNITY=off # the proactive "close the distance" gate (measured not to convert)
TR_RAM_OPP_DIST=200.0 # px; max range at which that gate may fire
TR_RAM_OPP_MARGIN=15.0 # energy advantage the gate needs before it starts
TR_RAM_ABORT_DMG=2.0 # incoming damage per turn that aborts a ram in progress
TR_RAM_PLAN=off # the change-of-plan trigger (enemy outguns us while we ram)
TR_RAM_PLAN_DIST=250.0 # px; max range at which the plan trigger may fire
TR_RAM_PLAN_MARGIN=20.0 # energy advantage the plan trigger needs
TR_RAM_PLAN_HITRATE=0.05 # pooled virtual hit rate below which the gun duel counts as failing
# ── movement internals: tfil (the floor-is-lava field) ──────────────────────
TR_TFIL_RANGE_LO=100.0 # px; lower edge of the range band the ring mover prefers
TR_TFIL_RANGE_HI=200.0 # px; upper edge of that band
TR_TFIL_RANGE_TEMP=0.4 # sharpness of the ring mover's weighted random draw
TR_TFIL_RANGE_K=60.0 # px; how fast the weight falls off outside the band
TR_TFIL_CORRIDOR_HEAT=10.0 # lava painted per corridor-overlapping tile
TR_TFIL_WALL_HOTNESS=15.0 # peak heat painted on tiles next to a wall
TR_TFIL_WALL_RADIANCE=10.0 # how fast wall heat falls off with distance
TR_TFIL_TILE_REPLAN=self # self | enemy | off: when a dodge commitment is cancelled
TR_TFIL_COMMIT_TICKS=15 # ticks to commit to a dodge point before replanning
TR_TFIL_NO_REV=off # on = never reverse direction inside a corridor
TR_TFIL_COMMIT_LOG= # path for the per-commit log; empty = no log
TR_TFIL_COMMIT_ARRIVAL=off # on = hold the dodge tile until we are ON it (not a fixed dwell)
TR_TFIL_COMMIT_MARGIN=0.0 # lava an alternative tile must be cooler by before it wins the tile
TR_TFIL_NOREV_SPEED=0.0 # px/tick; below this, a mid-flight switch may not turn the bot around
TR_TFIL_HEAT_TIME=off # on = index bullet heat by time (flat field when off)
TR_TFIL_HEAT_TAU=9.0 # ticks a tracked bullet's heat lives for
TR_TFIL_HEAT_POWER_GAIN=1.0 # scale of the heat a bullet paints, per firepower
TR_TFIL_PILLAR_ON=off # on = paint heat on the arena centre, which has no pillar
# ── movement internals: strafe ───────────────────────────────────────────────
TR_STRAFE_BAND=20.0 # degrees the heading may sit off the perpendicular
TR_STRAFE_SPREAD=1 # tiles of sideways jitter added to each candidate
TR_STRAFE_REACH=144.0 # px the candidate line reaches in each direction
TR_STRAFE_DWELL_MIN=6 # min ticks on a target tile before it may be re-picked
TR_STRAFE_DWELL_MAX=20 # max ticks on a target tile before it is re-picked anyway
TR_STRAFE_RANGE=325.0 # px; the enemy distance the line is tilted toward
TR_STRAFE_RANGE_TOL=25.0 # px dead band around it, where the tilt is exactly 0
TR_STRAFE_TILT_MAX=15.0 # degrees; the hard cap on that tilt
TR_STRAFE_TILT_GAIN=0.1 # degrees of tilt per px of range error beyond the band
TR_STRAFE_KAPPA=0.0025 # 1/px; how hard the candidate wing bends near a wall
TR_STRAFE_WALL_MARGIN=108.0 # px range over which the wing starts to bend
TR_STRAFE_WING_MAX=30.0 # degrees; cap on the wing's own tilt toward the interior
TR_STRAFE_WALL_BIAS=0.35 # how strongly a tile farther from the wall is preferred
TR_STRAFE_WALL_SAFE=24.0 # px; a wing point never lands nearer than this to a wall
TR_STRAFE_ESCAPE=on # the guaranteed wall escape when every candidate is hot
TR_STRAFE_FIRE_FIX=on # strafe's share of the shared TR_FIRE_FIX switch
TR_FIRE_FIX=on # 0 = the shipped previous-energy bullet detector
#TR_FIRE_DIAG=1 # presence-only: per-reading tick/raw/correction trace
TR_STRAFE_HEAT_GRID=on # draw the whole heat grid; 0 leaves only the chosen tile
TR_STRAFE_BULLET_CORE=20.0 # strafe's own retune: lava per bullet-overlapping tile
TR_STRAFE_BULLET_AURA=10.0 # strafe's own retune: lava for the bullet aura ring
TR_STRAFE_CORRIDOR_HEAT=10.0 # strafe's own retune: lava per corridor tile
TR_STRAFE_WALL_HOTNESS=15.0 # strafe's own retune: peak wall heat
TR_STRAFE_WALL_RADIANCE=5.0 # strafe's own retune: wall heat falloff
# ── movement internals: surf (wave surfing) ─────────────────────────────────
TR_SURF_PREF_DIST=400.0 # px; the wave distance the mover tries to sit at
TR_SURF_DIST_BAND=50.0 # px dead band around it
TR_SURF_WALL_MARGIN=48.0 # px kept from the wall when picking a wave point
TR_SURF_RADIAL_FRAC=0.35 # how much of the remaining weight goes to the radial blend
#TR_SURF_LOG=1 # presence-only: one line per wave-surfing decision
# ── movement internals: learned (per-state learned danger) ──────────────────
TR_LEARNED_DECAY_EVERY=128 # learns between forgetting passes; 0 never forgets
TR_LEARNED_DECAY_SHIFT=1 # forgetting is c -= c shr shift; 0 disables it
TR_LEARNED_ALPHA=5.0 # weight of the uniform prior against the learned counts
TR_LEARNED_TRAVEL=0.01 # danger cost of crossing a wave
TR_LEARNED_REVERSAL=0.02 # danger cost of flipping the strafe side
TR_LEARNED_PREF_DIST=400.0 # px; the enemy distance this mover prefers
TR_LEARNED_DIST_BAND=50.0 # px dead band around it
TR_LEARNED_RADIAL_FRAC=0.35 # radial blend used outside the band
TR_LEARNED_WALL_MARGIN=48.0 # px kept from the wall
TR_LEARNED_GLOBAL=off # on = ignore the learned state (ablation arm)
TR_LEARNED_LABEL=histogram # histogram (default) or outcome: what a wave is labelled with
TR_LEARNED_REAL_EVENTS=off # on = resolve a wave on the real bullet event, not on energy
#TR_LEARNED_LOG=1 # presence-only: one line per learned decision
# ── guns ─────────────────────────────────────────────────────────────────────
# Virtual bullets: the prediction the whole gun selector is built on.
TR_MODULE_VBULLETS=on # 0 = no gun predicts or spawns; the selector falls back to its floor gun
# TMH — the horizon Tsetlin automata gun.
TR_TMHORIZON_SHIFT=2.0 # degrees added to the aim; 0 disables the correction arm
TR_TMHORIZON_BIG_MULT=1.5 # extra scale applied when the error magnitude is big
TR_TMHORIZON_RESET_ON_TARGET=on # wipe the automata when the target changes
TR_TMHORIZON_NSTATES=64 # automata state count (the inertia it can hold)
TR_TMHORIZON_WINDOW=0 # samples kept in the sliding window; 0 keeps everything
TR_TMHORIZON_RESET_DROP=0.0 # rolling accuracy drop, in points, that forces a retrain
TR_TMHORIZON_ACCURVE=off # log the accuracy curve even without the thinking log
TR_TMHORIZON_RETRAIN_EVERY=50 # samples between full retrains in sliding mode
TR_TMHORIZON_EPOCHS=1 # epochs each full retrain runs
# LEADGAIN (rack id 16) — the per-range-band learned lead-gain corrector.
TR_LEADGAIN_MEM=perRound # perRound | retained | decay: how corrections are kept
TR_LEADGAIN_GAINS=0.0,0.25,0.5,0.75,1.0 # the candidate lead gains it picks among
TR_LEADGAIN_MIN_OBS=8 # samples a band needs before its gain is trusted
TR_LEADGAIN_DECAY=250 # samples between count-decay passes
TR_LEADGAIN_DECAY_FRAC=0.02 # fraction each decay pass takes off every count
TR_LEADGAIN_RESET_ON_TARGET=on # wipe the learned gains when the target changes
TR_LEADGAIN_LOG=off # on = one line per gain change
# Kept only so a pre-rename .env does not warn. The gun does not read them.
TR_LEADGAIN_N=32 # NO-OP: the old SBC geometry, no longer used
TR_LEADGAIN_NADE=256 # NO-OP: the old ADE count, no longer used
TR_LEADGAIN_RANGE=40.0 # NO-OP: the old class half-range, no longer used
TR_LEADGAIN_WARMUP=400 # NO-OP: the old warm-up count, no longer used
TR_LEADGAIN_ADAPT=32 # NO-OP: the old adapt interval, no longer used
TR_LEADGAIN_CALIB=512 # NO-OP: the old calibration interval, no longer used
TR_LEADGAIN_SEED=20240921 # NO-OP: the old seed, no longer used
# PATTERN — the shipped gun, the only one the rack admits.
TR_PATTERN_LEN=10 # ticks of movement history used as the search key
TR_PATTERN_DEPTH=500 # how far back the history scan may reach
TR_PATTERN_RAD_OFFSET=0.0 # px added to the aim distance; negative aims short
TR_PATTERN_RAD_SCALE=1.0 # multiplier on the whole aim distance
# The SBC library (common_libs/bitbrain), not a gun knob. Registered so a config
# that sets them is not reported as a typo; the shipped bot path never reads them.
TR_BITBRAIN_MODE=bitset # bitset (default) or counted: the memory's storage
TR_BITBRAIN_DECAY_EVERY=1024 # learns between forgetting passes, counted mode only
TR_BITBRAIN_DECAY_SHIFT=1 # forgetting strength, counted mode only; 0 disables it
# Legacy names. `TR_BITBRAIN_<X>` is the old namespace of TR_LEADGAIN_<X> and
# `TR_RACK_BITBRAIN` the old name of TR_RACK_LEADGAIN; they are still honoured,
# but the new name always wins and setting an old one prints a [depr] line, so
# they stay commented out here.
#TR_RACK_BITBRAIN=off # LEGACY: old name of TR_RACK_LEADGAIN
#TR_BITBRAIN_MEM=perRound # LEGACY: old name of TR_LEADGAIN_MEM
#TR_BITBRAIN_GAINS=0.0,0.25,0.5,0.75,1.0 # LEGACY: old name of TR_LEADGAIN_GAINS
#TR_BITBRAIN_N=32 # LEGACY: old name of TR_LEADGAIN_N
#TR_BITBRAIN_NADE=256 # LEGACY: old name of TR_LEADGAIN_NADE
#TR_BITBRAIN_RANGE=40.0 # LEGACY: old name of TR_LEADGAIN_RANGE
#TR_BITBRAIN_LOG=off # LEGACY: old name of TR_LEADGAIN_LOG
#TR_BITBRAIN_MIN_OBS=8 # LEGACY: old name of TR_LEADGAIN_MIN_OBS
#TR_BITBRAIN_WARMUP=400 # LEGACY: old name of TR_LEADGAIN_WARMUP
#TR_BITBRAIN_ADAPT=32 # LEGACY: old name of TR_LEADGAIN_ADAPT
#TR_BITBRAIN_CALIB=512 # LEGACY: old name of TR_LEADGAIN_CALIB
#TR_BITBRAIN_DECAY=250 # LEGACY: old name of TR_LEADGAIN_DECAY
#TR_BITBRAIN_DECAY_FRAC=0.02 # LEGACY: old name of TR_LEADGAIN_DECAY_FRAC
#TR_BITBRAIN_SEED=20240921 # LEGACY: old name of TR_LEADGAIN_SEED
#TR_BITBRAIN_RESET_ON_TARGET=on # LEGACY: old name of TR_LEADGAIN_RESET_ON_TARGET
# ── debug overlays (all on top of the gun; they never change a decision) ─────
TR_DEBUG_DRAW=on # master switch for every mover's debugGraphics
TR_GEO_DEBUG=off # draw the shared candidate-tile geometry overlay
TR_VBULLET_DEBUG=off # draw each admitted gun's virtual-bullet paths
TR_VBULLET_DEBUG_GUN= # which gun the overlay draws: empty = the selected one
TR_VBULLET_DEBUG_MAX=32 # max virtual bullets drawn per gun
TR_VBULLET_ADMIT_ONLY=on # on = a gun the rack does not admit is not even predicted
# ── logs (set the value to 1; presence alone turns some of them on) ──────────
TR_RESULT_LOG=on # one line per round result
#TR_POWER_LOG=1 # presence-only: one line per power decision
#TR_RAM_LOG=1 # presence-only: one line per ram start/stop and why
#TR_MOVEMENT_LOG=1 # presence-only: movement band/class changes
#TR_STRAFE_LOG=1 # presence-only: one line per strafe tile pick
#TR_TMHORIZON_LOG=1 # presence-only: the per-shot thinking of the TM horizon gun
GUN_STATS_PATH=/tmp/gun_stats.jsonl # where the per-round gun stats are written
GUN_SHOTLOG_PATH=/tmp/shot_log.jsonl # where the per-shot log is written
# ── measurement helpers (leave off unless you are measuring) ─────────────────
#TR_RECORD_WORLDSTATE=1 # presence-only: dump every observed world state
#TR_RADAR_SCANLOG=1 # presence-only: log every radar scan tick
#TR_TRACKER_PROBE=1 # presence-only: dump the enemy-tracker's internal state
TR_TRACKER_PROBE_PATH=/tmp/tracker_probe.jsonl # where that dump is written
# ── dotenv / boot report ─────────────────────────────────────────────────────
# Name of the env file to load. Must be set in the REAL environment, not in the
# file it points at. Empty = use ./.env, else .env next to the binary.
TR_ENV_FILE=
# 1 = print the [env] report on startup (default). 0 = do not print it.
TR_ENV_REPORT=1