diff --git a/ModularBot_garage/.env.example b/ModularBot_garage/.env.example index 4d554f9..c6187cb 100644 --- a/ModularBot_garage/.env.example +++ b/ModularBot_garage/.env.example @@ -1,53 +1,260 @@ -# Copy this file to `.env` (same folder as the bot) and edit what you need. -# The bot reads `.env` automatically when you start it from its folder. -# To use a different file: ./out/ModularBot --env-file /path/to/my.env +# ModularBot environment — EVERY knob the bot reads, already set to its default. # -# The file WINS over variables you exported in the shell. If a shell value -# differs, the bot prints a warning line so you know it was overridden. +# cp .env.example .env # -# Everything is optional. Leave a line out (or commented, with #) to keep the -# built-in default. Values shown are the defaults. +# 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 to run: strafe (default), tfil, tfil_ring, surf. +# 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 default is Pattern only. Turn a gun on with `both`. -TR_RACK_PATTERN=both -#TR_RACK_TMHORIZON=both -#TR_RACK_HEADON=both - -# Drop whole guns by number (comma separated ids; empty = keep all). +# 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 ──────────────────────────────────────────────────── -# 1 = use the energy-aware power cap (default). 0 = no cap (for experiments). -TR_POWER_POLICY=1 -# Lowest cap when our own energy is low. NOTE: this is a CEILING, not a floor. -TR_POWER_ENERGY_MIN=0.5 +# 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_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_` is the old namespace of TR_LEADGAIN_ 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) ────────── -# Print one line per power decision. -#TR_POWER_LOG=1 -# Print one line per ram start/stop and why. -#TR_RAM_LOG=1 -# Print movement band/class changes. -#TR_MOVEMENT_LOG=1 -# Print the per-shot thinking of the TM horizon gun. -#TR_TMHORIZON_LOG=1 -# Print one line per round result. -TR_RESULT_LOG=1 - -# Where the per-round gun stats and the per-shot log are written. -GUN_STATS_PATH=/tmp/gun_stats.jsonl -GUN_SHOTLOG_PATH=/tmp/shot_log.jsonl +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 -#TR_RADAR_SCANLOG=1 -#TR_TRACKER_PROBE=1 +#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 -# ── boot report ────────────────────────────────────────────────────────────── +# ── 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 diff --git a/ModularBot_garage/src/vbullet_draw.nim b/ModularBot_garage/src/vbullet_draw.nim index 551473d..32ccc6e 100644 --- a/ModularBot_garage/src/vbullet_draw.nim +++ b/ModularBot_garage/src/vbullet_draw.nim @@ -99,7 +99,7 @@ proc gunColors*(gunId: int): tuple[turret, bullet: string] = of 13: ("#00FFCC", "#66FFDD") # TMSelect — cyan of 14: ("#AAFF00", "#CCFF66") # TMPattern — lime of 15: ("#00AAFF", "#66CCFF") # TMHorizon — sky - of 16: ("#FF1493", "#FF69B4") # BitBrain — deep pink + of 16: ("#FF1493", "#FF69B4") # LEADGAIN — deep pink else: ("#FFFFFF", "#FFFFFF") proc gunTurretColor*(gunId: int): string = gunColors(gunId).turret