Feat/competition tooling - #138
Open
mrinmoy2developer wants to merge 5 commits into
Open
Conversation
The GUI hardcoded a 50px cell, so a 22x22 competition board wanted 1436x1101 and simply did not fit a 1440x932 screen. Cell size is now a property of the GUI: with no explicit size it is derived from the desktop dimensions and never scales above the old default, so small boards look exactly as before. Cell contents follow — icons are smoothscaled and army counts get a proportional font. The right panel keeps its fixed sizing so the scoreboard stays readable at any zoom. ReplayGUI/GUI take cell_size=None and expose the value actually used. protocol.encode_observation: build each row with row.tolist() + map(str) instead of indexing numpy scalars one at a time. Byte-identical output, 0.125ms -> 0.071ms per call, and it runs 3xH times per turn per agent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
matchup2 is matchup with the ruleset gaps closed. matchup drives game.step
directly, which skips the build-castles and deathtouch modifiers that live
in GeneralsEnv.step — so under --mode competition a `2 r c 0 0` build was
not merely ignored, it fell through to _execute_move and silently marched
the army upward. It also always generated a max_grid_size square instead of
drawing each side per seed. Both fixed here, plus:
--log PATH transcript of the engine<->agent conversation, with
per-decision timing, flushed so a hang leaves a usable tail
--show-grids full observation grids in the log (~2MB/match, opt-in)
--save PATH compact recording
--cell-size GUI zoom
replay.py stores seed + action stream only and re-simulates on playback:
2.0KB versus 51KB for a compressed state dump, verified bit-exact across
every frame and field against a live re-run.
arena.py plays every seed in both seat orders and reports a score with a
95% interval. Fusing the per-turn modifier dispatches under one jit and
batching the action transfer took a 200-match run from 76s to ~55s with
identical results.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nine generations, each its own directory so every earlier bot stays
runnable and every claim in my_bot.md stays reproducible. my_bot9 goes
12-0-0 against expander_python and 81W-27L-12D over 120 matches against a
frozen my_bot5.
What drove it:
* A castle is worth ~25 land. global_update grants +1/cell every 50 ticks
but +1/structure every 2, and competition maps spawn with no neutral
castles — building is the only economy there is (my_bot..my_bot3).
* Economy alone wins nothing: my_bot3 reached 10,607 army against 943 and
still went 0-1-11, every game a truncation draw. BFS pathfinding plus
deathtouch awareness converted that into wins (my_bot4).
* Attacking the nearest enemy cell nibbles the shared border and never
reveals anything; aiming at the fog behind enemy territory found the
general (my_bot6, 4W-0L-8D -> 11W-0L-1D).
* my_bot9: the starter's _is_passable treats type 5 (structure under fog)
as impassable, but 5 is a mountain OR a castle. Bots ring their own
general with castles, so both sides were unreachable by construction —
"general known for 500 turns, no path exists". Two-tier routing with
learned walls halved the draws.
my_bot.md records two negative results as well (my_bot7's gather and
my_bot8's rush both measured flat) and the harness discipline that exposed
them: fixed opponent, 120 matches minimum, replicate on a disjoint seed
range before believing anything.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
matchup3 serves a generals.io-style client and drives the bot over the ordinary stdio protocol, so competition agents run unmodified. It uses the same engine path as matchup2, and the player only ever receives get_observation(state, seat) — the same fog the bot gets. relay.py runs on a public box and holds no engine at all: the laptop dials out to it, so bots can run behind NAT while the site stays reachable. When no worker has checked in the site reports "no bots live" and Start is disabled. Liveness counts an in-flight long-poll as connected and derives its timeout from LONG_POLL, because a shorter window declared a healthy worker dead between polls. Client: click selects, double-click arms a half-army move, right-click builds. The move queue lives server-side like generals.io, so a closed tab just drains it. Replays are archived (--replays N) and can be watched from either seat or with no fog — fog is a 3x3 dilation of owned cells, reproduced in the browser and cross-checked against the engine's own get_visibility. The true board is released only after a match ends. Autopilot hands the player's seat to a bot and back mid-game. Export produces a real .rpl that competition/replay.py can open. Stdlib only on both sides, so the public box needs no pip install. deploy/ has a systemd unit and a Caddyfile for automatic HTTPS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
One page per tool — matchup/matchup2/matchup3, relay, arena, replay — with a template command, a flag table and the operational details that actually cost time: --seed defaults to 0 so runs repeat the same map, --mode overrides the manual ruleset flags, --relay wants the base URL, -u matters because block-buffered logs look like a dead process, arena results under ~120 matches are noise, and Oracle Cloud needs both a VCN ingress rule and the instance firewall opened. Every command in it was executed; all flags checked against argparse. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.