j136 add TR_MODULE_* on/off switches + single [modules] boot inventory
This commit is contained in:
@@ -7,6 +7,7 @@ import env_boot # MUST be first: applies the .env file before any other
|
|||||||
# module's top-level `let` reads the environment.
|
# module's top-level `let` reads the environment.
|
||||||
import std/[math, os, strformat, tables, sets, json, random, strutils]
|
import std/[math, os, strformat, tables, sets, json, random, strutils]
|
||||||
import robocode_tankroyale_botapi
|
import robocode_tankroyale_botapi
|
||||||
|
import module_switches
|
||||||
import radar_harness/radar_interface
|
import radar_harness/radar_interface
|
||||||
import radars/radar_lock_module
|
import radars/radar_lock_module
|
||||||
import radars/adaptive_melee_radar
|
import radars/adaptive_melee_radar
|
||||||
@@ -126,6 +127,10 @@ let VBulletAdmitOnly* =
|
|||||||
## tfil_ring — the new RANGE-WEIGHTED mover (movements/the_floor_is_lava_ring).
|
## tfil_ring — the new RANGE-WEIGHTED mover (movements/the_floor_is_lava_ring).
|
||||||
## UNPROVEN: it must never become the default silently.
|
## UNPROVEN: it must never become the default silently.
|
||||||
let MovementName* = getEnv("TR_MOVEMENT", "strafe").strip().toLowerAscii()
|
let MovementName* = getEnv("TR_MOVEMENT", "strafe").strip().toLowerAscii()
|
||||||
|
## The engine the tick ACTUALLY runs after the per-engine on/off switches
|
||||||
|
## (`TR_MODULE_MOVE_*`, default all on) are applied. With every switch unset this
|
||||||
|
## equals `MovementName`, so the dispatch below is byte-identical to before.
|
||||||
|
let EffectiveMovementName* = resolveMoveEngine(MovementName)
|
||||||
## TEMPORARY j134 diagnostic (TASK B): when `TR_FIRE_DIAG` is set, print the tick
|
## TEMPORARY j134 diagnostic (TASK B): when `TR_FIRE_DIAG` is set, print the tick
|
||||||
## of every enemy-hit / our-hit EVENT so it can be checked against the energy
|
## of every enemy-hit / our-hit EVENT so it can be checked against the energy
|
||||||
## reading tick logged by the mover. OFF by default; observability only.
|
## reading tick logged by the mover. OFF by default; observability only.
|
||||||
@@ -379,13 +384,13 @@ proc printConfig(bot: ModularBot, forceAll: bool = false) =
|
|||||||
let tc = if bot.currentTargetId != bot.prevTarget or forceAll: CLR_CHANGE else: ""
|
let tc = if bot.currentTargetId != bot.prevTarget or forceAll: CLR_CHANGE else: ""
|
||||||
let radarName = if bot.radarMode == 0: "radar_lock" else: "adaptive_melee"
|
let radarName = if bot.radarMode == 0: "radar_lock" else: "adaptive_melee"
|
||||||
let moveName =
|
let moveName =
|
||||||
if MovementName == "strafe":
|
if EffectiveMovementName == "strafe":
|
||||||
if bot.isRamming: "strafe(ram)" else: "strafe"
|
if bot.isRamming: "strafe(ram)" else: "strafe"
|
||||||
elif MovementName == "tfil_ring":
|
elif EffectiveMovementName == "tfil_ring":
|
||||||
if bot.isRamming: "tfil_ring(ram)" else: "tfil_ring"
|
if bot.isRamming: "tfil_ring(ram)" else: "tfil_ring"
|
||||||
elif MovementName == "surf":
|
elif EffectiveMovementName == "surf":
|
||||||
if bot.isRamming: "surf(ram)" else: "surf"
|
if bot.isRamming: "surf(ram)" else: "surf"
|
||||||
elif MovementName == "learned":
|
elif EffectiveMovementName == "learned":
|
||||||
if bot.isRamming: "learned(ram)" else: "learned"
|
if bot.isRamming: "learned(ram)" else: "learned"
|
||||||
elif bot.isRamming: "rammer"
|
elif bot.isRamming: "rammer"
|
||||||
else: "tfil"
|
else: "tfil"
|
||||||
@@ -1150,8 +1155,8 @@ method run*(bot: ModularBot) =
|
|||||||
let ramReason = ramTrigger(RamInputs(
|
let ramReason = ramTrigger(RamInputs(
|
||||||
dist: ramDist, selfEnergy: ws.selfEnergy,
|
dist: ramDist, selfEnergy: ws.selfEnergy,
|
||||||
enemyEnergy: ws.enemyEnergy, gunHitRate: gunHitRate))
|
enemyEnergy: ws.enemyEnergy, gunHitRate: gunHitRate))
|
||||||
let triggerRam = bot.currentTargetId >= 0 and bot.ramCooldownTicks == 0 and
|
let triggerRam = ModuleRam and bot.currentTargetId >= 0 and
|
||||||
ramReason != rrNone
|
bot.ramCooldownTicks == 0 and ramReason != rrNone
|
||||||
# Abort an IN-PROGRESS ram on sustained incoming fire. The trigger itself is
|
# Abort an IN-PROGRESS ram on sustained incoming fire. The trigger itself is
|
||||||
# unaffected, so a firefight before the approach never vetoes the start.
|
# unaffected, so a firefight before the approach never vetoes the start.
|
||||||
let abortRam = shouldAbortRam(bot.isRamming, ramDmgRate)
|
let abortRam = shouldAbortRam(bot.isRamming, ramDmgRate)
|
||||||
@@ -1195,13 +1200,13 @@ method run*(bot: ModularBot) =
|
|||||||
# through the single ring engine; the default `tfil` keeps the old
|
# through the single ring engine; the default `tfil` keeps the old
|
||||||
# two-engine behaviour (tfil when holding, rammer when ramming).
|
# two-engine behaviour (tfil when holding, rammer when ramming).
|
||||||
var spd, tr: float
|
var spd, tr: float
|
||||||
if MovementName == "strafe" and not shouldRam:
|
if EffectiveMovementName == "strafe" and not shouldRam:
|
||||||
(spd, tr) = bot.strafeMover.computeMove(ws)
|
(spd, tr) = bot.strafeMover.computeMove(ws)
|
||||||
elif MovementName == "surf" and not shouldRam:
|
elif EffectiveMovementName == "surf" and not shouldRam:
|
||||||
(spd, tr) = bot.surfMover.computeMove(ws)
|
(spd, tr) = bot.surfMover.computeMove(ws)
|
||||||
elif MovementName == "learned" and not shouldRam:
|
elif EffectiveMovementName == "learned" and not shouldRam:
|
||||||
(spd, tr) = bot.learnedMover.computeMove(ws)
|
(spd, tr) = bot.learnedMover.computeMove(ws)
|
||||||
elif MovementName == "tfil_ring":
|
elif EffectiveMovementName == "tfil_ring":
|
||||||
bot.ringMover.band =
|
bot.ringMover.band =
|
||||||
if shouldRam: (lo: 0.0, hi: 50.0)
|
if shouldRam: (lo: 0.0, hi: 50.0)
|
||||||
else: (lo: RangeLo, hi: RangeHi)
|
else: (lo: RangeLo, hi: RangeHi)
|
||||||
@@ -1282,7 +1287,8 @@ method run*(bot: ModularBot) =
|
|||||||
# is 0, so TR_VBULLET_ADMIT_ONLY=0 reproduces the exact pre-change rack.
|
# is 0, so TR_VBULLET_ADMIT_ONLY=0 reproduces the exact pre-change rack.
|
||||||
var admit: array[17, bool]
|
var admit: array[17, bool]
|
||||||
for gi in 0..<17:
|
for gi in 0..<17:
|
||||||
admit[gi] = vBulletAdmitted(gi, bot.rackMode, ActiveRackMembership,
|
admit[gi] = ModuleVBullets and
|
||||||
|
vBulletAdmitted(gi, bot.rackMode, ActiveRackMembership,
|
||||||
VBulletAdmitOnly or gi == TmPatternId or
|
VBulletAdmitOnly or gi == TmPatternId or
|
||||||
gi == TmHorizonId or gi == BitBrainId)
|
gi == TmHorizonId or gi == BitBrainId)
|
||||||
for i in 0..<len(PowerBins):
|
for i in 0..<len(PowerBins):
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import std/[os, strutils, algorithm, times, sets]
|
import std/[os, strutils, algorithm, times, sets]
|
||||||
import env_dotenv
|
import env_dotenv
|
||||||
|
import module_switches
|
||||||
import gun_harness/virtual_bullets
|
import gun_harness/virtual_bullets
|
||||||
import gun_harness/selector
|
import gun_harness/selector
|
||||||
import movements/ram_decision
|
import movements/ram_decision
|
||||||
@@ -194,12 +195,10 @@ proc printEffectiveValues(ctx: EnvReportContext) =
|
|||||||
# ── movement / process-level ModularBot knobs ─────────────────────────────
|
# ── movement / process-level ModularBot knobs ─────────────────────────────
|
||||||
# Only `tfil_ring` and `strafe` select a non-default engine; every other value
|
# Only `tfil_ring` and `strafe` select a non-default engine; every other value
|
||||||
# runs `tfil`, so report the RESOLVED engine rather than the raw string.
|
# runs `tfil`, so report the RESOLVED engine rather than the raw string.
|
||||||
let effectiveMovement =
|
# `resolveMoveEngine` applies the per-engine TR_MODULE_MOVE_* switches, so
|
||||||
if ctx.movementName == "tfil_ring": "tfil_ring"
|
# this line reports the engine the tick will actually run (identical to the
|
||||||
elif ctx.movementName == "strafe": "strafe"
|
# old name-mapping when every switch is unset).
|
||||||
elif ctx.movementName == "surf": "surf"
|
let effectiveMovement = resolveMoveEngine(ctx.movementName)
|
||||||
elif ctx.movementName == "learned": "learned"
|
|
||||||
else: "tfil"
|
|
||||||
emit("TR_MOVEMENT", effectiveMovement, sourceOf("TR_MOVEMENT"))
|
emit("TR_MOVEMENT", effectiveMovement, sourceOf("TR_MOVEMENT"))
|
||||||
emit("TR_MOVEMENT_LOG", onOff(MovementLog), sourceOfPresence("TR_MOVEMENT_LOG"))
|
emit("TR_MOVEMENT_LOG", onOff(MovementLog), sourceOfPresence("TR_MOVEMENT_LOG"))
|
||||||
emit("TR_VBULLET_ADMIT_ONLY", onOff(ctx.vBulletAdmitOnly),
|
emit("TR_VBULLET_ADMIT_ONLY", onOff(ctx.vBulletAdmitOnly),
|
||||||
@@ -422,6 +421,79 @@ proc printEffectiveValues(ctx: EnvReportContext) =
|
|||||||
emit(EnvReportEnableEnvVar, getEnv(EnvReportEnableEnvVar, "1"),
|
emit(EnvReportEnableEnvVar, getEnv(EnvReportEnableEnvVar, "1"),
|
||||||
sourceOf(EnvReportEnableEnvVar))
|
sourceOf(EnvReportEnableEnvVar))
|
||||||
|
|
||||||
|
# ── section C: the module on/off inventory ───────────────────────────────────
|
||||||
|
#
|
||||||
|
# One line per module, always the same shape:
|
||||||
|
# [modules] gun.pattern = ON (source: default)
|
||||||
|
# so `grep '^\[modules\]'` is the complete answer to "what is switched on right
|
||||||
|
# now". The always-on core is listed too, marked `source: always-on`, rather
|
||||||
|
# than silently omitted. Existing off switches (TR_RACK_<GUN>, TR_POWER_POLICY,
|
||||||
|
# TR_FIRE_FIX, TR_RADAR_FORCE_SPIN, TR_VBULLET_DEBUG, TR_GEO_DEBUG,
|
||||||
|
# TR_DEBUG_DRAW, TR_STRAFE_HEAT_GRID, TR_TFIL_HEAT_TIME) are surfaced under
|
||||||
|
# their ONE name — no duplicate knobs are invented.
|
||||||
|
|
||||||
|
proc emitModule(name: string, on: bool, source: string, note = "") =
|
||||||
|
var line = "[modules] " & name
|
||||||
|
while line.len < len("[modules] ") + 20: line.add ' '
|
||||||
|
line.add "= "
|
||||||
|
line.add(if on: "ON" else: "off")
|
||||||
|
line.add " (source: "
|
||||||
|
line.add source
|
||||||
|
if note.len > 0:
|
||||||
|
line.add "; "
|
||||||
|
line.add note
|
||||||
|
line.add ")"
|
||||||
|
echo line
|
||||||
|
|
||||||
|
proc printModules(ctx: EnvReportContext) =
|
||||||
|
echo "[modules] --- C. module on/off inventory (grep '^\\[modules\\]' for all) ---"
|
||||||
|
|
||||||
|
# Guns. Rack membership IS the on/off switch: `off` = disabled, any other
|
||||||
|
# mode = enabled in that rack.
|
||||||
|
for i in 0..<len(RackGunNames):
|
||||||
|
emitModule("gun." & RackGunNames[i].toLowerAscii(),
|
||||||
|
ActiveRackMembership[i] != rmOff,
|
||||||
|
sourceOf(RackEnvPrefix & RackGunNames[i]),
|
||||||
|
"rack: " & rackMembershipName(ActiveRackMembership[i]))
|
||||||
|
|
||||||
|
# Movement engines + the engine the tick actually runs.
|
||||||
|
for e in MoveEngines:
|
||||||
|
emitModule("move." & e.name, e.enabled, sourceOf(e.envVar))
|
||||||
|
echo "[modules] move.effective = ", resolveMoveEngine(ctx.movementName),
|
||||||
|
" (requested: TR_MOVEMENT=", ctx.movementName, ")"
|
||||||
|
|
||||||
|
# New TR_MODULE_* switches (j136).
|
||||||
|
emitModule("vbullets.tracker", ModuleVBullets, sourceOf(ModuleVBulletsEnvVar),
|
||||||
|
"off: no predict/spawn; selector falls back to its floor gun")
|
||||||
|
emitModule("ram.decider", ModuleRam, sourceOf(ModuleRamEnvVar),
|
||||||
|
"off: never ram; the movement engine alone drives")
|
||||||
|
|
||||||
|
# Existing off switches, surfaced as modules under their ONE existing name.
|
||||||
|
emitModule("radar.adaptive", not ctx.radarForceSpin,
|
||||||
|
sourceOfPresence("TR_RADAR_FORCE_SPIN"),
|
||||||
|
"off via TR_RADAR_FORCE_SPIN: full 360 spin")
|
||||||
|
emitModule("radar.lock", true, "always-on",
|
||||||
|
"1v1 radar; without it the bot cannot function")
|
||||||
|
emitModule("power.policy", PowerPolicyEnabled, sourceOf(PowerPolicyEnvVar),
|
||||||
|
"off via TR_POWER_POLICY: uncapped")
|
||||||
|
emitModule("fire.fix", TfilFireFix, sourceOf("TR_FIRE_FIX"),
|
||||||
|
"off: shipped prev-energy detector")
|
||||||
|
emitModule("dbg.debug_draw", ctx.debugDraw, sourceOfPresence(DebugDrawEnv),
|
||||||
|
"off: every mover debugGraphics=false")
|
||||||
|
emitModule("dbg.vbullet", ctx.vBulletDebug, sourceOfPresence(VBulletDebugEnv))
|
||||||
|
emitModule("dbg.geo", ctx.geoDebug, sourceOfPresence(GeoDebugEnv))
|
||||||
|
emitModule("dbg.heat_grid", StrafeHeatGrid, sourceOf("TR_STRAFE_HEAT_GRID"))
|
||||||
|
emitModule("dbg.heat_time", TfilHeatTime, sourceOf("TR_TFIL_HEAT_TIME"),
|
||||||
|
"off: flat (time-independent) bullet heat")
|
||||||
|
|
||||||
|
# Always-on core, listed so the inventory is complete.
|
||||||
|
emitModule("core.enemy_tracker", true, "always-on",
|
||||||
|
"without it the bot has no enemy positions")
|
||||||
|
emitModule("core.target_select", true, "always-on",
|
||||||
|
"picks which enemy to aim at")
|
||||||
|
emitModule("core.gun_selector", true, "always-on",
|
||||||
|
"ranks the rack; empty fitness floor = first admitted gun")
|
||||||
|
|
||||||
# ── build identity (which binary is the GUI actually running?) ───────────────
|
# ── build identity (which binary is the GUI actually running?) ───────────────
|
||||||
|
|
||||||
proc printBuildIdentity() =
|
proc printBuildIdentity() =
|
||||||
@@ -466,6 +538,10 @@ proc knownEnvNames*(): seq[string] =
|
|||||||
# exported constants — the single source of truth (do not re-spell these)
|
# exported constants — the single source of truth (do not re-spell these)
|
||||||
MetricEnvVar, SelectorModeEnvVar, TieBreakEnvVar,
|
MetricEnvVar, SelectorModeEnvVar, TieBreakEnvVar,
|
||||||
RackShareEnvVar,
|
RackShareEnvVar,
|
||||||
|
# module on/off switches (j136) — the new TR_MODULE_* prefix
|
||||||
|
ModuleVBulletsEnvVar, ModuleRamEnvVar,
|
||||||
|
ModuleMoveTfilEnvVar, ModuleMoveRingEnvVar, ModuleMoveStrafeEnvVar,
|
||||||
|
ModuleMoveSurfEnvVar, ModuleMoveLearnedEnvVar,
|
||||||
PowerPolicyEnvVar, PowerFarDistEnvVar, PowerFarCapEnvVar, PowerMidCapEnvVar,
|
PowerPolicyEnvVar, PowerFarDistEnvVar, PowerFarCapEnvVar, PowerMidCapEnvVar,
|
||||||
PowerRefEnvVar, PowerEnergyHiEnvVar, PowerEnergyLoEnvVar,
|
PowerRefEnvVar, PowerEnergyHiEnvVar, PowerEnergyLoEnvVar,
|
||||||
PowerEnergyMinEnvVar, PowerEnergyMaxEnvVar, PowerFinishKillEnvVar,
|
PowerEnergyMinEnvVar, PowerEnergyMaxEnvVar, PowerFinishKillEnvVar,
|
||||||
@@ -661,5 +737,6 @@ proc printEnvReport*(ctx: EnvReportContext) =
|
|||||||
printRawEnvironment()
|
printRawEnvironment()
|
||||||
printMistakeWarnings()
|
printMistakeWarnings()
|
||||||
printEffectiveValues(ctx)
|
printEffectiveValues(ctx)
|
||||||
|
printModules(ctx)
|
||||||
printBuildIdentity()
|
printBuildIdentity()
|
||||||
echo "[env] === END ENVIRONMENT ==="
|
echo "[env] === END ENVIRONMENT ==="
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
## Module on/off switches (job j136).
|
||||||
|
##
|
||||||
|
## The owner drives the bot from a `.env` file and wants to flip whole modules
|
||||||
|
## on and off to test combinations. Modules that ALREADY had an off switch keep
|
||||||
|
## it — no duplicate knobs are introduced here:
|
||||||
|
##
|
||||||
|
## adaptive melee radar -> TR_RADAR_FORCE_SPIN (on = force the old full spin)
|
||||||
|
## power policy -> TR_POWER_POLICY
|
||||||
|
## fire fix -> TR_FIRE_FIX
|
||||||
|
## time-indexed heat -> TR_TFIL_HEAT_TIME
|
||||||
|
## virtual-bullet overlay -> TR_VBULLET_DEBUG
|
||||||
|
## geometry overlay -> TR_GEO_DEBUG
|
||||||
|
## global debug draw -> TR_DEBUG_DRAW
|
||||||
|
## strafe heat grid -> TR_STRAFE_HEAT_GRID
|
||||||
|
## every gun -> TR_RACK_<GUN> (membership `off` = disabled)
|
||||||
|
##
|
||||||
|
## Everything NEW below uses one uniform, greppable prefix: `TR_MODULE_<NAME>`.
|
||||||
|
## Every switch defaults to ON, so an unset environment is byte-for-byte the
|
||||||
|
## shipped bot. "OFF" always means the simpler/older fallback, never a broken
|
||||||
|
## bot:
|
||||||
|
##
|
||||||
|
## TR_MODULE_VBULLETS=0 no gun predicts or spawns virtual bullets; the
|
||||||
|
## selector falls back to its floor gun.
|
||||||
|
## TR_MODULE_RAM=0 no ramming at all; the movement engine alone
|
||||||
|
## drives (the finisher/desperation/plan/opportunity
|
||||||
|
## triggers all stop firing).
|
||||||
|
## TR_MODULE_MOVE_<ENGINE>=0 that engine is no longer selectable. The
|
||||||
|
## EFFECTIVE engine falls back to the first enabled
|
||||||
|
## engine, with `tfil` (the long-shipped mover) as
|
||||||
|
## the designated fallback. There is no "no
|
||||||
|
## movement": if every engine is switched off the
|
||||||
|
## bot still runs `tfil`.
|
||||||
|
##
|
||||||
|
## Read once at module init, like every other knob, so one compiled binary can
|
||||||
|
## A/B every arm by environment alone.
|
||||||
|
|
||||||
|
import std/[os, strutils]
|
||||||
|
|
||||||
|
# ── the new switches ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
const
|
||||||
|
ModuleVBulletsEnvVar* = "TR_MODULE_VBULLETS"
|
||||||
|
ModuleRamEnvVar* = "TR_MODULE_RAM"
|
||||||
|
ModuleMoveTfilEnvVar* = "TR_MODULE_MOVE_TFIL"
|
||||||
|
ModuleMoveRingEnvVar* = "TR_MODULE_MOVE_TFIL_RING"
|
||||||
|
ModuleMoveStrafeEnvVar* = "TR_MODULE_MOVE_STRAFE"
|
||||||
|
ModuleMoveSurfEnvVar* = "TR_MODULE_MOVE_SURF"
|
||||||
|
ModuleMoveLearnedEnvVar* = "TR_MODULE_MOVE_LEARNED"
|
||||||
|
|
||||||
|
proc moduleFlagOn*(name: string, default = true): bool =
|
||||||
|
## Value-based, exactly like `TR_POWER_POLICY`: unset/empty -> `default`;
|
||||||
|
## explicit 0/false/no/off -> off; any other value -> on.
|
||||||
|
let v = getEnv(name, "").strip().toLowerAscii()
|
||||||
|
if v.len == 0: return default
|
||||||
|
v notin ["0", "false", "no", "off"]
|
||||||
|
|
||||||
|
let ModuleVBullets* = moduleFlagOn(ModuleVBulletsEnvVar)
|
||||||
|
## OFF: the virtual-bullet tracker stops. The selector's fitness stays empty
|
||||||
|
## and `chooseFromFit` takes its floor path (the first admitted gun), so the
|
||||||
|
## bot keeps aiming and firing — just without the fitness signal.
|
||||||
|
let ModuleRam* = moduleFlagOn(ModuleRamEnvVar)
|
||||||
|
## OFF: `triggerRam` is never true, so `isRamming` stays false and the
|
||||||
|
## movement engine drives every tick (the pre-rammer fallback).
|
||||||
|
|
||||||
|
type
|
||||||
|
MoveEngine* = object
|
||||||
|
name*: string ## the `TR_MOVEMENT` value
|
||||||
|
envVar*: string ## its `TR_MODULE_MOVE_*` switch
|
||||||
|
enabled*: bool
|
||||||
|
|
||||||
|
let MoveEngines*: array[5, MoveEngine] = [
|
||||||
|
MoveEngine(name: "tfil", envVar: ModuleMoveTfilEnvVar,
|
||||||
|
enabled: moduleFlagOn(ModuleMoveTfilEnvVar)),
|
||||||
|
MoveEngine(name: "tfil_ring", envVar: ModuleMoveRingEnvVar,
|
||||||
|
enabled: moduleFlagOn(ModuleMoveRingEnvVar)),
|
||||||
|
MoveEngine(name: "strafe", envVar: ModuleMoveStrafeEnvVar,
|
||||||
|
enabled: moduleFlagOn(ModuleMoveStrafeEnvVar)),
|
||||||
|
MoveEngine(name: "surf", envVar: ModuleMoveSurfEnvVar,
|
||||||
|
enabled: moduleFlagOn(ModuleMoveSurfEnvVar)),
|
||||||
|
MoveEngine(name: "learned", envVar: ModuleMoveLearnedEnvVar,
|
||||||
|
enabled: moduleFlagOn(ModuleMoveLearnedEnvVar)),
|
||||||
|
]
|
||||||
|
|
||||||
|
proc moveEngineEnvVar*(name: string): string =
|
||||||
|
## The switch name for `name`, or "" when it is not a known engine.
|
||||||
|
for e in MoveEngines:
|
||||||
|
if e.name == name: return e.envVar
|
||||||
|
""
|
||||||
|
|
||||||
|
proc moveEngineEnabled*(name: string): bool =
|
||||||
|
for e in MoveEngines:
|
||||||
|
if e.name == name: return e.enabled
|
||||||
|
false
|
||||||
|
|
||||||
|
proc resolveMoveEngine*(requested: string): string =
|
||||||
|
## The EFFECTIVE engine the live tick will run.
|
||||||
|
## * an unknown/empty `requested` means `tfil` (the shipped fallback);
|
||||||
|
## * the requested engine is used when its switch is on;
|
||||||
|
## * otherwise the first enabled engine in `MoveEngines` (tfil first);
|
||||||
|
## * if every engine is off, `tfil` is forced — there is no no-movement.
|
||||||
|
var req = requested.strip().toLowerAscii()
|
||||||
|
if moveEngineEnvVar(req).len == 0: req = "tfil"
|
||||||
|
if moveEngineEnabled(req): return req
|
||||||
|
for e in MoveEngines:
|
||||||
|
if e.enabled: return e.name
|
||||||
|
"tfil"
|
||||||
@@ -230,6 +230,55 @@ shooting *look* like missing).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Module on/off switches — the `[modules]` boot list
|
||||||
|
|
||||||
|
Every module appears once in the boot report, so one command shows the state of
|
||||||
|
them all right now:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
grep '^\[modules\]' /tmp/modularbot_stdout.log
|
||||||
|
```
|
||||||
|
|
||||||
|
The **new** switches all share the prefix `TR_MODULE_`. A module that already had
|
||||||
|
an off switch keeps its old name (no duplicate knobs). "OFF" always means the
|
||||||
|
simpler fallback, never a broken bot.
|
||||||
|
|
||||||
|
| switch | ON means | OFF falls back to |
|
||||||
|
|---|---|---|
|
||||||
|
| `TR_MODULE_VBULLETS` | guns predict and score virtual bullets so the selector can rank them (default) | no virtual bullets; the selector has no fitness and fires its floor gun (the first gun the rack admits) |
|
||||||
|
| `TR_MODULE_RAM` | the ram decider may start a ram: finisher, desperation and the optional triggers (default) | the bot never rams; the movement engine drives every tick |
|
||||||
|
| `TR_MODULE_MOVE_TFIL` | the `tfil` / lava-field engine may be selected (default) | it is skipped when picking the effective engine |
|
||||||
|
| `TR_MODULE_MOVE_TFIL_RING` | the range-weighted ring engine may be selected (default) | same — skipped in the fallback |
|
||||||
|
| `TR_MODULE_MOVE_STRAFE` | the perpendicular-strafe engine may be selected (default) | same — skipped in the fallback |
|
||||||
|
| `TR_MODULE_MOVE_SURF` | the wave-surfer engine may be selected (default) | same — skipped in the fallback |
|
||||||
|
| `TR_MODULE_MOVE_LEARNED` | the learned danger engine may be selected (default) | same — skipped in the fallback |
|
||||||
|
|
||||||
|
There is no "no movement". If the engine named by `TR_MOVEMENT` is switched off,
|
||||||
|
the effective engine is the first engine still on, in the order `tfil`,
|
||||||
|
`tfil_ring`, `strafe`, `surf`, `learned`. If all of them are off the bot still
|
||||||
|
runs `tfil`.
|
||||||
|
|
||||||
|
The modules that already had a switch — surfaced in `[modules]` under that one
|
||||||
|
name, with no new knob:
|
||||||
|
|
||||||
|
| switch | ON means | OFF falls back to |
|
||||||
|
|---|---|---|
|
||||||
|
| `TR_RACK_<GUN>` = `both`/`1v1`/`melee` | that gun may be selected | `TR_RACK_<GUN>=off`: the gun is removed from the rack |
|
||||||
|
| `TR_POWER_POLICY` | energy-aware power caps (default) | uncapped: the gun's own preferred power |
|
||||||
|
| `TR_FIRE_FIX` | the corrected enemy-fire detector (default) | the shipped `prev - energy` detector |
|
||||||
|
| `TR_RADAR_FORCE_SPIN` | force the old stateless full-spin melee radar (**off by default**) | the adaptive arc-narrowing radar (default) |
|
||||||
|
| `TR_TFIL_HEAT_TIME` | time-indexed bullet heat (**off by default**) | flat, time-independent heat (default) |
|
||||||
|
| `TR_VBULLET_DEBUG` | draw the virtual-bullet overlay (**off by default**) | nothing drawn |
|
||||||
|
| `TR_GEO_DEBUG` | draw the geometry overlay (**off by default**) | nothing drawn |
|
||||||
|
| `TR_DEBUG_DRAW` | per-mover debug graphics (default) | the movers draw nothing |
|
||||||
|
| `TR_STRAFE_HEAT_GRID` | draw the full heat grid in STRAFE (default) | the heat grid is hidden |
|
||||||
|
|
||||||
|
Always on, listed in `[modules]` but with no switch, because the bot cannot work
|
||||||
|
without them: the enemy tracker, target selection, the gun selector and the 1v1
|
||||||
|
radar lock.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 1. Gun rack — which gun(s) may be chosen
|
## 1. Gun rack — which gun(s) may be chosen
|
||||||
|
|
||||||
| variable | default | what it does |
|
| variable | default | what it does |
|
||||||
|
|||||||
Reference in New Issue
Block a user