Skip to content

Commit 2ea90af

Browse files
committed
Enh(battlesnake): Randomize player order for every game
1 parent 254439a commit 2ea90af

1 file changed

Lines changed: 18 additions & 7 deletions

File tree

codeclash/games/battlesnake/battlesnake.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
import random
23
import time
34
from concurrent.futures import ThreadPoolExecutor, as_completed
45
from pathlib import Path
@@ -46,10 +47,20 @@ def _wait_for_ports(self, requested_ports: list[int], timeout: float = 3.0) -> l
4647

4748
return list(available_ports)
4849

49-
def _run_single_simulation(self, cmd: str, idx: int) -> str:
50+
def _run_single_simulation(self, player2port: dict[str, int], idx: int) -> str:
5051
"""Run a single battlesnake simulation and return log and result outputs."""
52+
# Build command with player URLs in randomized order
53+
players = list(player2port.items())
54+
random.shuffle(players)
55+
56+
cmd_args = []
57+
for player_name, port in players:
58+
cmd_args.append(f"--url http://0.0.0.0:{port} -n {player_name}")
59+
60+
cmd = self.run_cmd_round + " " + " ".join(cmd_args) + f" -o {self.log_env / f'sim_{idx}.jsonl'}"
61+
5162
output = self.environment.execute(
52-
cmd + f" -o {self.log_env / f'sim_{idx}.jsonl'}",
63+
cmd,
5364
cwd=f"{self.environment.config.cwd}/game",
5465
)
5566
if output["returncode"] != 0:
@@ -60,15 +71,13 @@ def _run_single_simulation(self, cmd: str, idx: int) -> str:
6071

6172
def execute_round(self, agents: list[Player]):
6273
self.logger.debug("Starting game servers")
63-
cmd = []
6474
player2port = {}
6575
for idx, agent in enumerate(agents):
6676
port = 8001 + idx
6777
player2port[agent.name] = port
6878
# Surprisingly slow despite using &
6979
# Start server in background - just add & to run in background!
7080
self.environment.execute(f"PORT={port} python main.py &", cwd=f"/{agent.name}")
71-
cmd.append(f"--url http://0.0.0.0:{port} -n {agent.name}")
7281

7382
self.logger.debug(f"Waiting for ports: {player2port}")
7483
available_ports = self._wait_for_ports(list(player2port.values()))
@@ -83,17 +92,19 @@ def execute_round(self, agents: list[Player]):
8392
self._failed_to_start_player.append(player)
8493
return
8594

95+
if len(available_ports) < len(agents):
96+
raise RuntimeError(f"Only {len(available_ports)} players started: {available_ports}")
97+
8698
self.logger.debug("All ports are ready")
8799

88100
try:
89-
cmd = self.run_cmd_round + " " + " ".join(cmd)
90-
self.logger.info(f"Running game: {cmd}")
101+
self.logger.info(f"Running game with players: {list(player2port.keys())}")
91102

92103
# Use ThreadPoolExecutor for parallel execution
93104
with ThreadPoolExecutor(20) as executor:
94105
# Submit all simulations to the thread pool
95106
futures = [
96-
executor.submit(self._run_single_simulation, cmd, idx)
107+
executor.submit(self._run_single_simulation, player2port, idx)
97108
for idx in range(self.game_config["sims_per_round"])
98109
]
99110

0 commit comments

Comments
 (0)