Skip to content

Commit 5a4f7ae

Browse files
committed
Add multithreading to battlesnake execution
1 parent c4cd3c3 commit 5a4f7ae

2 files changed

Lines changed: 38 additions & 22 deletions

File tree

codeclash/games/battlesnake/battlesnake.py

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import json
22
import time
3+
import uuid
4+
from concurrent.futures import ThreadPoolExecutor, as_completed
35
from pathlib import Path
46

57
from tqdm.auto import tqdm
@@ -69,29 +71,43 @@ def execute_round(self, agents: list[Player]) -> RoundData:
6971
log_outputs, result_outputs = [], []
7072
cmd = self.run_cmd_round + " " + " ".join(cmd)
7173
self.logger.info(f"Running game: {cmd}")
72-
for idx in tqdm(range(self.game_config["sims_per_round"])):
73-
# Create temporary output file for results
74-
output_file = f"battlesnake_output_{idx}_{int(time.time())}.json"
75-
76-
# Run game
77-
response = assert_zero_exit_code(
78-
self.environment.execute(
79-
cmd + f" -o {output_file}",
80-
cwd=f"{self.environment.config.cwd}/game",
81-
)
82-
)
83-
84-
# Read the output file for result information
85-
result_response = self.environment.execute(f"cat game/{output_file}")
86-
result_output = result_response["output"]
87-
log_outputs.append(response["output"])
88-
result_outputs.append(result_output)
89-
90-
# Clean up the output file
91-
self.environment.execute(f"rm -f game/{output_file}")
92-
time.sleep(0.05)
74+
75+
# Use ThreadPoolExecutor for parallel execution
76+
with ThreadPoolExecutor(20) as executor:
77+
# Submit all simulations to the thread pool
78+
futures = [
79+
executor.submit(self._run_single_simulation, cmd) for _ in range(self.game_config["sims_per_round"])
80+
]
81+
82+
# Collect results as they complete
83+
for future in tqdm(as_completed(futures), total=len(futures)):
84+
log_output, result_output = future.result()
85+
log_outputs.append(log_output)
86+
result_outputs.append(result_output)
9387

9488
return RoundData(logs=log_outputs, results=result_outputs)
9589
finally:
9690
# Kill all python servers when done
9791
self.environment.execute("pkill -f 'python main.py' || true")
92+
93+
def _run_single_simulation(self, cmd: str) -> tuple[str, str]:
94+
"""Run a single battlesnake simulation and return log and result outputs."""
95+
# Create temporary output file for results
96+
output_file = f"battlesnake_output_{uuid.uuid4().hex}.json"
97+
98+
# Run game
99+
response = assert_zero_exit_code(
100+
self.environment.execute(
101+
cmd + f" -o {output_file}",
102+
cwd=f"{self.environment.config.cwd}/game",
103+
)
104+
)
105+
106+
# Read the output file for result information
107+
result_response = self.environment.execute(f"cat game/{output_file}")
108+
result_output = result_response["output"]
109+
110+
# Clean up the output file
111+
self.environment.execute(f"rm -f game/{output_file}")
112+
113+
return response["output"], result_output

configs/pvp/battlesnake.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ tournament:
22
rounds: 25
33
game:
44
name: BattleSnake
5-
sims_per_round: 30
5+
sims_per_round: 100
66
args:
77
width: 11
88
height: 11

0 commit comments

Comments
 (0)