- Deleted constants.nim, event_queue.nim, graphics.nim, json_parse.nim, schemas.nim, utils.nim, and ws_client.nim files.
- This cleanup removes unused code and simplifies the codebase, focusing on essential functionalities.
- Removed non-existent exported/ directory from layout docs
- Replaced hardcoded bot binary entries with *_garage/out/ pattern for build directories
- Added all known bot binaries (GotoTest, OscillatorBot, PPO_Bot, QBot, SAC_LSTM_Bot)
to .gitignore with clarifying comment about Nim's compilation target structure
Nim places compiled binaries at bot root (no extension) and in out/ subdirs.
The out/ pattern catches all build outputs; specific bot binaries listed for
root-level executables since gitignore lacks a reliable "no-extension files" glob.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extracted concrete numbers from 13 papers in docs/papers/neuroevolution/.
Key findings: use CMA-ES or mutation-only truncation GA, mutate ALL weights
(not 5%), sigma=0.005-0.01, pop=64-200, no crossover, single elite.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
$(cat f) inside a command redirected to f saw the already-truncated file,
so every eval cycle wiped ma_history_*.txt back to one leading-space value
and degraded the composite best-gate to last-cycle mean. Read is hoisted
into its own statement; unquoted expansion + tail -n keeps exactly the last
MA_WINDOW values. Verified: fresh/5+/6+ cycle edges reproduce sliding window.
SACLSTM_EVAL_MODE=1 in SacTwin.sh suppresses all sendTrainingMsg traffic
(lever-4 gate), so the twin never trains — not even in-RAM within a battle.
Required now that the main bot's SACLSTM_SAVE_INTERVAL drops to 1 (v2 relaunch
after checkpoint-cadence diagnosis): without the gate the twin would persist
per-battle drift and stop being the frozen reproducible opponent #54 specifies.
Lever 2 (#59): x1.25 aggression mult on damage dealt, flat +0.5 hit bonus,
-3.0 per bot-bot collision (server deals RAM_DAMAGE=0.6 to both parties but
only notifies the hitter), escalating proximity deterrent below 12% arena
diagonal suppressed while dealing damage. Win/loss terminals unchanged and
dominant. All weights TUNABLE consts marked ponytail. SACLSTM_REWARD_DEBUG=1
env-gated reward_debug.log for calibration greps.
Lever 5 (#59): no code needed — SACLSTM_LR_ACTOR/LR_CRITIC/LR_ALPHA (3e-4)
and SACLSTM_TARGET_ENTROPY (-4.0) were already env-overridable in training.nim.
Smoke vs RamFire+Crazy (hidden=32, random init, isolated weights): 75 ram
penalties, 381 charge events, hit bonuses firing, 0 crashes, metrics JSONL
flowing. Tests: 8/8 suites green incl. new assert-level term math.
Levers 3, 4, 1 of the #57 sign-off (execution order 3->4->1), tracked in #59.
- Lever 3 (#59): one JSONL line per trainPass in training_metrics.jsonl with
exactly the scalars sacUpdate already exposes (SACMetrics: critic/actor/alpha
losses + alpha, averaged per pass) plus epoch, buffer size (replay_buffer.len),
cumulative steps and drained count. No trainer change needed.
- Lever 4 (#59): sendTrainingMsg drops all training input while SACLSTM_EVAL_MODE=1
(existing #49 harness mechanism) — eval battles can neither pollute the replay
buffer nor trigger gradient updates; one-time stderr notice at bot init.
- Lever 1 (#59): sac_train.sh evaluates every SAC_EVAL_OPPONENTS entry per cycle
(results carry opponent name in eval_log.jsonl); best-gating now uses a
composite = mean over opponents of the last-5-evals moving average per
opponent. best_score.txt format change: float composite replaces the
single-opponent integer win rate semantics (retired).
- Tests: metricsLine JSONL scalars + eval-mode suppression asserts.
Refs: #59, #57