Agent for Kaggle's Maze Crawler simulation competition. Two factories race northward through a scrolling maze. The game ends when the scroll boundary reaches your factory. Metric: ELO ladder rating (higher is better, starts ~600 and calibrates over hours of episodes).
The key insight: this is a survival race, not a combat game. Enemies are visible only ~3% of turns through fog-of-war; the real opponent is the scroll boundary itself.
| Version | Ladder Score | Note |
|---|---|---|
| π v18 (peak stable) | 1046.6 (#70) | Pure BFS sprinter, no extras |
| π v21 (current) | ~1017β1057 | Mine economy + ceiling buffer |
| v15 | 932.4 | First jump-BFS (ported from public LB1223 notebook) |
| v10 | 513.8 | Survival-first heuristic (first real improvement over v9) |
| v9 | 492.1 | Original baseline |
Status: ladder fluctuates Β±50 points per session. Best observed: 1057.5, rank #53/459 (top 12%). All versions above v15 use the same jump-BFS core; improvements are marginal tuning.
The winning approach is pure north-sprinting via jump-preferred BFS, ported and tuned from the public notebook "Top 2 Maze Crawler β Jump-Preferred BFS (LB 1223)" by Nicolas Bridelance.
Factory spawns 1 scout β scout runs BFS toward (factory_row + target_ahead)
JUMP when cooldown == 0 AND jump clears >1 row
WALK otherwise on shortest path
Factory itself flees north: JUMP_NORTH on emergency (gap β€ 2), step otherwise
Critical engine detail most agents miss: cooldowns tick BEFORE action processing, so
a robot with observed cd == 1 can act this turn. Planning only at cd == 0 wastes every
other move window. This alone accounts for a large chunk of the jump-BFS advantage over naive agents.
Agents v10βv14 were tuned via local self-play (one frozen opponent). Every iteration that looked like +10% local winrate turned out to be noise (Β±8% at 30β50 seeds). The real ladder settled all of them within Β±50 ELO of each other.
Lesson: mirror self-play saturates at 50% Β± noise. Only the calibrated ladder matters. This is especially painful because ladder calibration takes hours of episodes.
Reading the public LB1223 notebook revealed the cooldown bug and the jump-BFS structure. v15 jumped from ~500 to 932 ELO overnight β a bigger gain than the entire v9βv14 iteration.
This is the Mahog principle applied to simulation: reading the top public code first beats weeks of local tuning.
Every "improvement" after v15 (mine economy, scouts, ceiling buffer, worker logic) either held at ~1000 or degraded. v18 β a clean, minimal sprinter β held at 1046.6. v19 added a miner pipeline and collapsed to 659 ELO. Classic complexity trap.
The agent that wins is the simplest one that correctly implements the core mechanic.
| Version | Ladder Score | Change |
|---|---|---|
| v9 | 492 | original heuristic (over-builds, bankrupt deaths) |
| v10 | 514 | survival-first, energy solvency, scout1 build order |
| v11 | 471 | BFS escape + factory feeding β regressed |
| v12 | 606 | tuned margins |
| v13 | 737 | tuned scoring weights |
| v15 | 932 | jump-BFS from public LB1223 β step change |
| v16 | 864 | over-tuned, regressed |
| v18 | 1047 | pure sprinter, minimal β BEST STABLE |
| v19 | 659 | miner pipeline β catastrophic regression |
| v20 | 980 | scouts + ceiling buffer |
| v21 | ~1020 | mine economy + ceiling buffer (current) |
agents/
baseline_v9.py β¦ baseline_v22.py agent version history
cand_v23*.py experimental candidates
ext_jumpbfs_lb1223.py reference: public LB1223 notebook port
starter_baseline.py Kaggle starter kit (preserved)
scripts/
arena.py local self-play tournament harness
tournament.py multi-agent round-robin
analyze_ladder.py parse ladder JSON β ELO trends
breakdown.py per-version death cause analysis
survival.py factory survival rate by version
compare_death.py death cause diff between two agents
maze_submit/
build_submission.py packages main.py for Kaggle kernel submit
main.py current submission (single self-contained file)
tests/
test_agent_smoke.py smoke test: synthetic obs + env episode
SOLUTION.md full architecture and iteration notes
python3.12 -m venv .venv-sim
source .venv-sim/bin/activate
pip install kaggle-environments
# Run smoke tests
python -m unittest discover tests
# Self-play tournament (30 seeds, v21 vs v18)
python scripts/arena.py --agent agents/baseline_v21.py \
--opponent agents/baseline_v18.py \
--seeds 30Note: local winrate is a noisy proxy for ladder performance. Use it only to catch regressions (crashes, obvious death spikes). The real signal is the Kaggle ladder after ~1h of episodes.