1+ import re
12from pathlib import Path
23
34from codeclash .agents .player import Player
45from codeclash .games .game import CodeGame , RoundStats
56from codeclash .utils .environment import copy_from_container
67
78HB_LOG_DIR = Path ("/testbed/engine/logs/" )
9+ HB_REGEX_SCORE = re .compile (r"Player\s(\d+)\sdelta\supdated\:[\d\s\-\+\=]+,\smoney\:\s\d+\s\-\>\s(\d+)" )
810
911
1012class HuskyBenchGame (CodeGame ):
1113 name : str = "HuskyBench"
1214
1315 def __init__ (self , config , * , tournament_id : str , local_output_dir : Path ):
1416 super ().__init__ (config , tournament_id = tournament_id , local_output_dir = local_output_dir )
17+ self .num_players : int = len (config ["players" ])
1518 self .run_cmd_round : str = (
16- f"python engine/main.py --port 8000 --sim --sim-rounds { self .game_config ['sims_per_round' ]} "
19+ f"python engine/main.py --port 8000 --players { self .num_players } "
20+ f"--sim --sim-rounds { self .game_config ['sims_per_round' ]} "
1721 )
1822 for arg , val in self .game_config .get ("args" , {}).items ():
1923 if isinstance (val , bool ):
@@ -32,17 +36,34 @@ def copy_logs_from_env(self, round_num):
3236 )
3337
3438 def get_stats (self , agents : list [Player ], round_num : int ) -> RoundStats :
35- return RoundStats (winner = "N/A" , scores = {})
39+ map_id_to_agent = {}
40+ for agent in agents :
41+ with open (self .log_round (round_num ) / f"logs/{ agent .name } .log" ) as f :
42+ for line in f :
43+ if line .startswith ("My id:" ):
44+ agent_id = line .strip ().split ()[- 1 ]
45+ map_id_to_agent [agent_id ] = agent .name
46+ self .logger .info ("Agent IDs: " + str (map_id_to_agent ))
47+
48+ with open (self .log_round (round_num ) / "logs/engine.log" ) as f :
49+ score_updates = [
50+ (match .group (1 ), int (match .group (2 ))) for l in f .readlines () if (match := HB_REGEX_SCORE .search (l ))
51+ ]
52+ map_id_to_score = {k : v for k , v in score_updates [- self .num_players :]}
53+ self .logger .info ("Final Scores: " + str (map_id_to_score ))
54+ agent_to_score = {map_id_to_agent [agent_id ]: score for agent_id , score in map_id_to_score .items ()}
55+ return RoundStats (winner = max (agent_to_score , key = agent_to_score .get ), scores = agent_to_score )
3656
3757 def execute_round (self , agents : list [Player ]):
3858 self .environment .execute (f"rm -rf { HB_LOG_DIR } ; mkdir -p { HB_LOG_DIR } " )
3959 try :
40- self .logger .debug ("Starting game servers" )
41- self .environment .execute (f"{ self .run_cmd_round } > { HB_LOG_DIR / 'engine.log' } &" )
60+ cmd = f"{ self .run_cmd_round } > { HB_LOG_DIR / 'engine.log' } &"
61+ self .logger .debug (f"Starting game engine with command: { cmd } " )
62+ self .environment .execute (cmd )
4263 for agent in agents :
43- self . environment . execute (
44- f"python client/main.py --port 8000 > { HB_LOG_DIR / f' { agent . name } .log' } &" , cwd = f"/ { agent . name } "
45- )
64+ cmd = f"python client/main.py --port 8000 > { HB_LOG_DIR / f' { agent . name } .log' } &"
65+ self . logger . debug ( f"Adding agent with command: { cmd } " )
66+ self . environment . execute ( cmd , cwd = f"/ { agent . name } " )
4667 finally :
4768 # Kill all python servers when done
4869 self .environment .execute ("pkill -f 'python client/main.py' || true" )
0 commit comments