Skip to content

Commit 8a015c0

Browse files
committed
Add RoboCode CC:Ladder (80 imported classic-Robocode bots + build tooling)
- 80 open-source classic Robocode bots imported to CodeClash-ai/RoboCode human/robocode/* branches (source of truth, not committed here): shipped sample bots + mgalushka Super* variants; the full RoboWiki/PEZ collection (micro/mini/nano/femto + Marshmallow, GF1, Swiffer, ...); flat multi-file bots (Mb2, BerendBotje, MaximBot, TheCarver, BobTheBuilder, StarterBot); single-file DrussGT/HawkOnFire (strong top rungs); and bots from ~10 other GitHub repos (reimu, cham, pikachu, it-economics x8, ...). All copy-in (0 reimplementations) — verbatim, only repackaged to + main class renamed to MyTank (helpers flattened). - Each of the 80 verified to COMPILE and play a real battle in the arena image (stage 2, 80/80). - Provenance: every port file carries a source-URL/author/license header; scripts/ladder/SOURCES.md is the committed manifest (slug -> GitHub URL). See stamp_sources.py. - Fix arena description: it mislabeled itself 'Tank Royale' but the engine is classic Robocode. - make_robocode.yaml: round-robin (100 rounds, ~1h local at -w6) for Elo; README note. - scripts/ladder/: build tooling (copy-in porting guide, structural validator, compile+battle smoke, push script, provenance stamper, reference bot); ports/ regenerated, not committed.
1 parent 09823d2 commit 8a015c0

13 files changed

Lines changed: 844 additions & 2 deletions

File tree

codeclash/arenas/robocode/robocode.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818

1919
class RoboCodeArena(CodeArena):
2020
name: str = "RoboCode"
21-
description: str = f"""Robocode (Tank Royale) is a programming game where your code is the tank: each turn your bot sends intents—speed plus body/gun/radar turn rates and firepower—based on the game state it perceives via radar.
22-
Your program decides how to move, aim, and fire in a deterministic, turn-based arena to outlast other bots.
21+
description: str = f"""Robocode is a programming game where your code IS the tank. This is classic
22+
Robocode (the `robocode.*` API compiled against robocode.jar) — NOT Robocode Tank Royale.
23+
Your bot is a Java class that `extends robocode.Robot` (or `robocode.AdvancedRobot` for non-blocking
24+
control): its `run()` method drives the tank in a loop (e.g. `ahead(100)`, `turnGunRight(90)`,
25+
`fire(3)`), and it reacts to events like `onScannedRobot(ScannedRobotEvent)`, `onHitByBullet(...)`,
26+
and `onHitWall(...)`. Move, aim the gun, sweep the radar, and fire to outlast other bots.
2327
Your bot logic must be written in Java and located in the `robots/custom/` directory.
2428
Keep the main bot class named `{str(RC_FILE)}`, but you can include additional Java files if you'd like."""
2529
default_args: dict = {

configs/ablations/ladder/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@ You can follow these steps to create your own "CC:<arena>" ladder.
1212
The tricky part is typically finding a large collection of human solutions for a particular arena.
1313
We've typically found that googling for online leaderboards or awesome-<arena> repositories (e.g. [BattleSnake](https://github.com/BattlesnakeOfficial/awesome-battlesnake)) is a good strategy.
1414

15+
### RoboCode (newly added)
16+
17+
The [CC:RoboCode](https://github.com/CodeClash-ai/RoboCode) repo hosts 80 human bots on `human/robocode/*`
18+
branches (bot code lives only on the branches, not in this repo). This arena is **classic Robocode**
19+
(`robocode.*` API compiled against `robocode.jar`), so importing open-source bots is mostly a
20+
mechanical copy-in + rename rather than a strategy rewrite: each bot's Java class(es) are placed in
21+
`robots/custom/`, the main class renamed to `MyTank`, `package custom;`. The set spans the shipped
22+
sample bots (SittingDuck/Walls/Corners/…) through famous RoboWiki/PEZ micro-mini bots (Aristocles,
23+
Pugilist, HawkOnFire) up to a single-file **DrussGT** (a world-class bot) as the top rung; a few use
24+
Robocode's sanctioned `getDataFile` persistence (degrades gracefully without cross-battle saves).
25+
Diamond/BeepBoop remain as future top rungs (nested-package multi-file → need flattening). Each import
26+
was verified to **compile and play a real battle**. Build tooling + per-bot source provenance (`SOURCES.md`) live in `scripts/ladder/`.
27+
1528
## Config layout
1629

1730
Each arena has a few kinds of config in this folder:
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
# Round-robin over the human classic-Robocode bots (imported from open-source repos; see
2+
# scripts/ladder/SOURCES.md for each bot's origin URL/author/license), used to RANK them via
3+
# Elo/Bradley-Terry -> see robocode.yaml. rounds:0 = dummy players play baseline battles (no code
4+
# edits). N bots -> N*(N-1)/2 pairs; each pair plays sims_per_round rounds (batched 10 at a time,
5+
# sim_concurrency parallel). Bots live on CodeClash-ai/RoboCode human/* branches; Docker required.
6+
# COST (measured ~3.4s for a 50-round pair headless): at sims_per_round=100, 80 bots -> 3160 pairs
7+
# ~= 6 core-hours -> ~1 h on a laptop (--workers 6), ~12 min on a 32-core box (-w 30). Runs locally.
8+
# Run: uv run codeclash ladder make configs/ablations/ladder/make_robocode.yaml --workers 6
9+
tournament:
10+
rounds: 0
11+
game:
12+
name: RoboCode
13+
sims_per_round: 100
14+
sim_concurrency: 5
15+
args:
16+
nodisplay: true
17+
nosound: true
18+
players:
19+
- agent: dummy
20+
branch_init: human/robocode/aristocles
21+
- agent: dummy
22+
branch_init: human/robocode/berendbotje
23+
- agent: dummy
24+
branch_init: human/robocode/blackwidow
25+
- agent: dummy
26+
branch_init: human/robocode/blackwidow_mini
27+
- agent: dummy
28+
branch_init: human/robocode/bobthebuilder
29+
- agent: dummy
30+
branch_init: human/robocode/cham
31+
- agent: dummy
32+
branch_init: human/robocode/chironex_micro
33+
- agent: dummy
34+
branch_init: human/robocode/chironex_mini
35+
- agent: dummy
36+
branch_init: human/robocode/corners
37+
- agent: dummy
38+
branch_init: human/robocode/crawler
39+
- agent: dummy
40+
branch_init: human/robocode/crazy
41+
- agent: dummy
42+
branch_init: human/robocode/dacruzer
43+
- agent: dummy
44+
branch_init: human/robocode/droidpoet
45+
- agent: dummy
46+
branch_init: human/robocode/drussgt
47+
- agent: dummy
48+
branch_init: human/robocode/fire
49+
- agent: dummy
50+
branch_init: human/robocode/frankie
51+
- agent: dummy
52+
branch_init: human/robocode/genetic
53+
- agent: dummy
54+
branch_init: human/robocode/gf1
55+
- agent: dummy
56+
branch_init: human/robocode/gntest
57+
- agent: dummy
58+
branch_init: human/robocode/gouldingi
59+
- agent: dummy
60+
branch_init: human/robocode/gruffalo
61+
- agent: dummy
62+
branch_init: human/robocode/haikupoet
63+
- agent: dummy
64+
branch_init: human/robocode/haikuwalls
65+
- agent: dummy
66+
branch_init: human/robocode/hawkonfire
67+
- agent: dummy
68+
branch_init: human/robocode/hugbot
69+
- agent: dummy
70+
branch_init: human/robocode/hypoleach
71+
- agent: dummy
72+
branch_init: human/robocode/ianstank
73+
- agent: dummy
74+
branch_init: human/robocode/icarus
75+
- agent: dummy
76+
branch_init: human/robocode/ite_bomax
77+
- agent: dummy
78+
branch_init: human/robocode/ite_claptrap
79+
- agent: dummy
80+
branch_init: human/robocode/ite_cliffbot2
81+
- agent: dummy
82+
branch_init: human/robocode/ite_ctbot
83+
- agent: dummy
84+
branch_init: human/robocode/ite_florian2
85+
- agent: dummy
86+
branch_init: human/robocode/ite_m9
87+
- agent: dummy
88+
branch_init: human/robocode/ite_simple
89+
- agent: dummy
90+
branch_init: human/robocode/ite_terminator
91+
- agent: dummy
92+
branch_init: human/robocode/leach
93+
- agent: dummy
94+
branch_init: human/robocode/leachpmc
95+
- agent: dummy
96+
branch_init: human/robocode/littlebrother
97+
- agent: dummy
98+
branch_init: human/robocode/littleevilbrother
99+
- agent: dummy
100+
branch_init: human/robocode/mako
101+
- agent: dummy
102+
branch_init: human/robocode/markiv
103+
- agent: dummy
104+
branch_init: human/robocode/markrobo
105+
- agent: dummy
106+
branch_init: human/robocode/marshmallow
107+
- agent: dummy
108+
branch_init: human/robocode/maximbot
109+
- agent: dummy
110+
branch_init: human/robocode/mb2
111+
- agent: dummy
112+
branch_init: human/robocode/myfirstrobot
113+
- agent: dummy
114+
branch_init: human/robocode/paolo
115+
- agent: dummy
116+
branch_init: human/robocode/pikachu
117+
- agent: dummy
118+
branch_init: human/robocode/poet
119+
- agent: dummy
120+
branch_init: human/robocode/pugilist
121+
- agent: dummy
122+
branch_init: human/robocode/ramfire
123+
- agent: dummy
124+
branch_init: human/robocode/regullarmonk
125+
- agent: dummy
126+
branch_init: human/robocode/reimu
127+
- agent: dummy
128+
branch_init: human/robocode/sittingduck
129+
- agent: dummy
130+
branch_init: human/robocode/smallpoet
131+
- agent: dummy
132+
branch_init: human/robocode/spinbot
133+
- agent: dummy
134+
branch_init: human/robocode/starterbot
135+
- agent: dummy
136+
branch_init: human/robocode/supercorners
137+
- agent: dummy
138+
branch_init: human/robocode/supercrazy
139+
- agent: dummy
140+
branch_init: human/robocode/supermercutio
141+
- agent: dummy
142+
branch_init: human/robocode/superramfire
143+
- agent: dummy
144+
branch_init: human/robocode/superspinbot
145+
- agent: dummy
146+
branch_init: human/robocode/supertracker
147+
- agent: dummy
148+
branch_init: human/robocode/superwalls
149+
- agent: dummy
150+
branch_init: human/robocode/swiffer
151+
- agent: dummy
152+
branch_init: human/robocode/tannerbot1
153+
- agent: dummy
154+
branch_init: human/robocode/tarektank
155+
- agent: dummy
156+
branch_init: human/robocode/thecarver
157+
- agent: dummy
158+
branch_init: human/robocode/tityus
159+
- agent: dummy
160+
branch_init: human/robocode/tracker
161+
- agent: dummy
162+
branch_init: human/robocode/trackfire
163+
- agent: dummy
164+
branch_init: human/robocode/velocirobot
165+
- agent: dummy
166+
branch_init: human/robocode/vertileach
167+
- agent: dummy
168+
branch_init: human/robocode/vertimicro
169+
- agent: dummy
170+
branch_init: human/robocode/walls
171+
- agent: dummy
172+
branch_init: human/robocode/wallspoet
173+
- agent: dummy
174+
branch_init: human/robocode/wallspoetas
175+
- agent: dummy
176+
branch_init: human/robocode/wallspoethaiku
177+
- agent: dummy
178+
branch_init: human/robocode/wavesurfing
179+
prompts:
180+
game_description: RoboCode ladder

scripts/ladder/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Regenerated build artifacts — bot ports live on the CodeClash-ai/<arena> branches
2+
# (source of truth), not in this repo. Populate ports/ locally when (re)building a ladder.
3+
ports/
4+
out/

scripts/ladder/PORTING_GUIDE.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Importing a classic Robocode bot into the CodeClash arena
2+
3+
This arena is **classic Robocode** (Java, `robocode.jar`), NOT Tank Royale. Importing an
4+
open-source classic bot is mostly a mechanical **copy-in + rename**, not a strategy rewrite.
5+
6+
## The submission contract
7+
The submission is a directory `robots/custom/` containing Java source. The arena harness then:
8+
1. copies `robots/custom/*` into `robots/<player>/`,
9+
2. runs `sed 's/custom/<player>/g'` over every `.java` (this renames the `package custom`
10+
`package <player>` so bots are namespaced),
11+
3. compiles `javac -cp "libs/robocode.jar" robots/<player>/*.java`**flat glob, one directory**,
12+
4. runs battles selecting `<player>.MyTank*`.
13+
14+
`validate_code` requires `robots/custom/MyTank.java` to exist, compile, and produce `MyTank.class`.
15+
16+
## Hard rules for a port (`ports/<slug>/`)
17+
Produce a directory `scripts/ladder/ports/<slug>/` containing:
18+
- **`MyTank.java`** — the bot's main class, **renamed to `public class MyTank`** (rename the source's
19+
main class everywhere: declaration, constructors, and any self-references). It must
20+
`extends robocode.Robot` (or `AdvancedRobot` / `TeamRobot` / `RateControlRobot` / `JuniorRobot`).
21+
- **`package custom;`** as the package line in `MyTank.java` and in *every* helper file. Replace any
22+
original `package a.b.c;`.
23+
- **Helper classes** (if the bot is multi-file) as additional flat `.java` files in the same dir,
24+
also `package custom;`. **No nested subdirectories** — the compile is a flat `*.java` glob, so a
25+
bot that uses nested packages (e.g. `voidious/gun/…`) must be flattened or it won't compile.
26+
Inner classes inside one file are fine (preferred).
27+
- **The literal substring `custom` must NOT appear anywhere except the `package custom;` lines.**
28+
The harness's `sed s/custom/<player>/g` is a blind global replace, so any identifier, comment, or
29+
string containing "custom" would be corrupted. Rename such tokens.
30+
31+
## What's allowed / what breaks
32+
- Only the classic `robocode.*` API. No Tank Royale (`dev.robocode.tankroyale.*`).
33+
- Robocode runs under a security manager: **raw `java.io`, threads, reflection, and network are
34+
blocked.** Persistent gun/enemy stats via the sanctioned `getDataFile()` +
35+
`RobocodeFileOutputStream` are allowed but **may not persist** across our battles — such a bot
36+
still compiles and plays, it just degrades to no saved data (fine; note it). If the source uses
37+
raw `java.io`/threads/reflection, it will fail — flag and skip, or strip that path if it's optional.
38+
- Keep behavior faithful: do not "improve" the bot; only rename/repackage/flatten.
39+
40+
## Deliverable + report
41+
Write the port dir `scripts/ladder/ports/<slug>/` (at minimum `MyTank.java`). It must be valid Java
42+
that would compile against `robocode.jar`. In your report note per bot: source repo/author, base
43+
class, #files, and any caveat (data-file use, "custom"-token rename you had to do, multi-file, or
44+
anything you had to strip). A reference `MyTank.java` lives at
45+
`scripts/ladder/examples/robots/custom/MyTank.java`.

scripts/ladder/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Ladder build tooling (RoboCode)
2+
3+
Operational one-off scripts for constructing a CC:Ladder for **classic Robocode**. Unlike the
4+
SCML/Gomoku ladders (which re-express bots into a function contract), Robocode importing is mostly
5+
a mechanical **copy-in + rename**: classic bots are Java classes that drop into `robots/custom/`.
6+
7+
This is scaffolding, not product code — nothing under `codeclash/` imports it. The durable outputs
8+
are the `human/*` branches on `CodeClash-ai/RoboCode` (the bots) and the
9+
`configs/ablations/ladder/*.yaml` configs. Ports are **not** committed here (see `.gitignore`).
10+
11+
## Files
12+
- `PORTING_GUIDE.md` — the classic-Robocode submission contract + copy-in/rename rules (main class
13+
`MyTank`, `package custom;`, flat files, no stray "custom" token). Hand to an import agent with
14+
`examples/robots/custom/MyTank.java` as the reference.
15+
- `examples/robots/custom/MyTank.java` — reference bot (AdvancedRobot) + porting example.
16+
- `validate_ports.py` — stage 1 (structural, local): each `ports/<slug>/` has `MyTank.java` with
17+
`class MyTank extends <RobocodeBase>`, `package custom;`, flat, no sed-hazard token. Writes `_stage1.json`.
18+
- `run_smoke_all.sh`**stage 2 (the real gate):** in the arena Docker image, compile each port
19+
(`javac -cp libs/robocode.jar`) and run a real 3-round battle vs `sample.Walls`; confirm it
20+
compiles AND plays. Writes `_stage2.json` + per-bot compile/battle logs in `out/`.
21+
- `push_branches.sh` — push each stage-2-healthy `ports/<slug>/` to `CodeClash-ai/RoboCode` as
22+
`human/robocode/<slug>` with the files under `robots/custom/`.
23+
- `RUN.md` — round-robin (`ladder make`) + Elo ranking instructions.
24+
25+
## Typical flow
26+
1. Populate `ports/<slug>/MyTank.java` (fan out import agents with `PORTING_GUIDE.md`).
27+
2. `python3 scripts/ladder/validate_ports.py` → stage 1 (structural)
28+
3. `bash scripts/ladder/run_smoke_all.sh` → stage 2 (compile + battle each; needs Docker)
29+
4. `bash scripts/ladder/push_branches.sh` → push healthy ports to branches
30+
5. Rank + assemble configs — see `RUN.md`.
31+
32+
Note: `ports/` and `out/` are gitignored and shared on disk across branches — clean stale files
33+
(`rm -rf scripts/ladder/ports/* scripts/ladder/out`) when switching between arena ladder branches.

scripts/ladder/RUN.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Running the RoboCode round-robin (Elo ranking)
2+
3+
Rank the human bots in `configs/ablations/ladder/make_robocode.yaml` via all-pairs battles, then fit
4+
Elo. Each pair plays `sims_per_round` battle-rounds (the arena batches them `SIMS_PER_RUN=10` at a
5+
time, `sim_concurrency` in parallel). Battles are headless Java; cost is moderate — measure one pair
6+
first (below) to size the full run. Bots live on `CodeClash-ai/RoboCode` `human/*` branches;
7+
`branch_init` fetches them at runtime, so you only need this repo branch + Docker + a GitHub token.
8+
9+
## Prerequisites
10+
- Docker running, git, `uv`, and a token for `CodeClash-ai/RoboCode` (public → `gh auth token`).
11+
12+
## Step 0 — pre-build the arena image once (avoids a build stampede under -w N)
13+
```bash
14+
docker build -t codeclash/robocode -f codeclash/arenas/robocode/RoboCode.Dockerfile .
15+
```
16+
17+
## Step 1 — round-robin
18+
`N` bots → `N*(N-1)/2` pairs. Keep `--workers ≈ cores-2`. Resumable (skips logged pairs).
19+
```bash
20+
GITHUB_TOKEN=$(gh auth token) \
21+
uv run codeclash ladder make configs/ablations/ladder/make_robocode.yaml --workers 6
22+
```
23+
Tip: time one pair first to size the run — e.g. run a 2-player `codeclash run` config and note the
24+
wall time, then multiply by pair count / workers.
25+
26+
## Step 2 — rank
27+
```bash
28+
python -m codeclash.analysis.metrics.elo -d logs/ladder/RoboCode --output-dir assets/robocode_elo
29+
```
30+
Prints the Bradley-Terry/Elo ordering and writes `assets/robocode_elo/elo_results.log`.
31+
32+
## Step 3 — assemble the ladder configs (once you have the ranking)
33+
1. `configs/ablations/ladder/rungs/robocode.yaml` — ranked opponents, weakest first, strongest last.
34+
2. `configs/ablations/ladder/robocode.yaml` — climber `player` + `ladder: !include ablations/ladder/rungs/robocode.yaml`
35+
+ a `ladder_rules` block (model on `battlesnake.yaml`).
36+
3. Optional `robocode__<model>.yaml` per-model variants.

0 commit comments

Comments
 (0)