1+ import random
12import re
23from pathlib import Path
34from typing import Any
45
5- from tqdm .auto import tqdm
6-
76from codeclash .constants import DIR_WORK , RESULT_TIE
87from codeclash .games .game import CodeGame , RoundStats
98from codeclash .utils .environment import copy_from_container
109
10+ BATTLECODE_LOG = "sim.log"
11+
1112
1213class BattleCodeGame (CodeGame ):
1314 name : str = "BattleCode"
@@ -27,27 +28,26 @@ def copy_logs_from_env(self, round_num):
2728 super ().copy_logs_from_env (round_num )
2829 copy_from_container (
2930 container = self .environment ,
30- src_path = "/testbed/logs " ,
31- dest_path = self .log_local / "rounds" / str ( round_num ) ,
31+ src_path = "/testbed/sim.log " ,
32+ dest_path = self .log_local / "rounds" / f"sim_ { round_num } .log" ,
3233 )
3334
3435 def get_stats (self , agents : list [Any ]) -> RoundStats :
3536 winners = []
36- for sim_file in [f"logs/sim_{ idx } .log" for idx in range (self .game_config ["sims_per_round" ])]:
37- ro = self .environment .execute (f"cat { sim_file } " )["output" ]
38- lines = ro .strip ().split ("\n " )
39- # Get the third-to-last line which contains the winner info
40- winner_line = lines [- 3 ] if len (lines ) >= 3 else ""
41- self .logger .debug (f"Winner line: { winner_line } " )
42- match = re .search (r"\s\((.*)\)\swins\s\(" , winner_line )
43- if match :
44- winner_key = match .group (1 )
45- self .logger .debug (f"Winner key from match: { winner_key } " )
46- # Map A/B to actual agent names (much closer to original code)
47- winner = {"A" : agents [0 ].name , "B" : agents [1 ].name }.get (winner_key , RESULT_TIE )
48- winners .append (winner )
49- else :
50- winners .append (RESULT_TIE )
37+ ro = self .environment .execute (f"cat { BATTLECODE_LOG } " )["output" ]
38+ lines = ro .strip ().split ("\n " )
39+ # Get the third-to-last line which contains the winner info
40+ winner_line = lines [- 3 ] if len (lines ) >= 3 else ""
41+ self .logger .debug (f"Winner line: { winner_line } " )
42+ match = re .search (r"\s\((.*)\)\swins\s\(" , winner_line )
43+ if match :
44+ winner_key = match .group (1 )
45+ self .logger .debug (f"Winner key from match: { winner_key } " )
46+ # Map A/B to actual agent names (much closer to original code)
47+ winner = {"A" : agents [0 ].name , "B" : agents [1 ].name }.get (winner_key , RESULT_TIE )
48+ winners .append (winner )
49+ else :
50+ winners .append (RESULT_TIE )
5151 return RoundStats (
5252 winner = max (set (winners ), key = winners .count ),
5353 scores = {agent .name : winners .count (agent .name ) for agent in agents },
@@ -57,11 +57,10 @@ def execute_round(self, agents: list[Any]):
5757 for agent in agents :
5858 src , dest = f"/{ agent .name } /src/mysubmission/" , str (DIR_WORK / "src" / agent .name )
5959 self .environment .execute (f"cp -r { src } { dest } " )
60+ random .shuffle (agents ) # Start position matters in BattleCode! Shuffle to be fair.
6061 args = [f"--p{ idx + 1 } -dir src --p{ idx + 1 } { agent .name } " for idx , agent in enumerate (agents )]
6162 cmd = f"{ self .run_cmd_round } { ' ' .join (args )} "
6263 self .logger .info (f"Running game: { cmd } " )
6364
64- self .environment .execute ("rm -rf logs; mkdir logs" )
65- for idx in tqdm (range (self .game_config ["sims_per_round" ])):
66- response = self .environment .execute (cmd + f" > logs/sim_{ idx } .log" )
67- assert response ["returncode" ] == 0 , response
65+ response = self .environment .execute (cmd + f" > { BATTLECODE_LOG } " )
66+ assert response ["returncode" ] == 0 , response
0 commit comments