MCPcopy Create free account
hub / github.com/CodeClash-ai/CodeClash / BattleCode25Arena

Class BattleCode25Arena

codeclash/arenas/battlecode25/battlecode25.py:17–100  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

15
16
17class BattleCode25Arena(CodeArena):
18 name: str = "BattleCode25"
19 description: str = """BattleCode 2025 throws you into a real-time strategy showdown where your Python bot pilots a team of specialized robots—Soldiers, Moppers, Splashers—alongside towers that spawn units or generate resources.
20Your mission: paint over 70% of the map (or eliminate the enemy) by coordinating cleanups, area cover, and tower-building through tight bytecode budgets and clever unit synergy."""
21 default_args: dict = {
22 "maps": "quack",
23 }
24 submission: str = "src/mysubmission"
25
26 def __init__(self, config, **kwargs):
27 super().__init__(config, **kwargs)
28 assert len(config["players"]) == 2, "BattleCode25 is a two-player game"
29 self.run_cmd_round: str = "python run.py run"
30 for arg, val in self.game_config.get("args", self.default_args).items():
31 if isinstance(val, bool):
32 if val:
33 self.run_cmd_round += f" --{arg}"
34 else:
35 self.run_cmd_round += f" --{arg} {val}"
36
37 def _run_single_simulation(self, agents: list[Player], idx: int, cmd: str) -> str:
38 try:
39 response = self.environment.execute(cmd + f" > {self.log_env / BC_LOG.format(idx=idx)}")
40 except subprocess.TimeoutExpired:
41 self.logger.warning(f"BattleCode simulation {idx} timed out: {cmd}")
42 return ""
43 if response["returncode"] != 0:
44 self.logger.warning(
45 f"BattleCode simulation {idx} failed with exit code {response['returncode']}:\n{response['output']}"
46 )
47 return response["output"]
48
49 def execute_round(self, agents: list[Player]):
50 for agent in agents:
51 src, dest = f"/{agent.name}/src/{BC_FOLDER}/", str(DIR_WORK / "src" / agent.name)
52 self.environment.execute(f"rm -rf {dest}; cp -r {src} {dest}")
53 args = [f"--p{idx + 1}-dir src --p{idx + 1} {agent.name}" for idx, agent in enumerate(agents)]
54 cmd = f"{self.run_cmd_round} {' '.join(args)}"
55 self.logger.info(f"Running game: {cmd}")
56
57 with ThreadPoolExecutor(self.game_config.get("sim_concurrency", 5)) as executor:
58 # Submit all simulations to the thread pool
59 futures = [
60 executor.submit(self._run_single_simulation, agents, idx, cmd)
61 for idx in range(self.game_config["sims_per_round"])
62 ]
63 # Collect results as they complete
64 for future in tqdm(as_completed(futures), total=len(futures), desc="Simulations"):
65 future.result()
66
67 def get_results(self, agents: list[Player], round_num: int, stats: RoundStats):
68 scores = defaultdict(int)
69 for idx in range(self.game_config["sims_per_round"]):
70 with open(self.log_round(round_num) / BC_LOG.format(idx=idx)) as f:
71 lines = f.read().strip().split("\n")
72 if len(lines) < 3:
73 # Game likely crashed, skip this simulation
74 continue

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected