Skip to content

Commit 50a4fc5

Browse files
committed
Ref: Move most of main() logic to Game class
1 parent 4869a33 commit 50a4fc5

11 files changed

Lines changed: 48 additions & 39 deletions

File tree

codeclash/agents/abstract.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from abc import ABC, abstractmethod
33

44
from dotenv import load_dotenv
5-
from minisweagent import Environment
5+
from minisweagent.environments.docker import DockerEnvironment
66

77
from codeclash.agents.utils import GameContext
88
from codeclash.constants import GH_ORG
@@ -16,7 +16,7 @@ class Player(ABC):
1616
def __init__(
1717
self,
1818
config: dict,
19-
environment: Environment,
19+
environment: DockerEnvironment,
2020
game_context: GameContext,
2121
):
2222
self.config = config

codeclash/agents/minisweagent.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88

99
import yaml
1010
from jinja2 import Template
11-
from minisweagent import Environment, Model
11+
from minisweagent import Model
1212
from minisweagent.agents.default import AgentConfig, DefaultAgent
13+
from minisweagent.environments.docker import DockerEnvironment
1314
from minisweagent.models.litellm_model import LitellmModel
1415
from minisweagent.run.utils.save import save_traj
1516
from rich.console import Console
@@ -28,7 +29,7 @@ class ClashAgent(DefaultAgent):
2829
def __init__(
2930
self,
3031
model: Model,
31-
env: Environment,
32+
env: DockerEnvironment,
3233
name: str,
3334
game_context: GameContext,
3435
*,
@@ -69,7 +70,7 @@ class MiniSWEAgent(Player):
6970
"""Player with agentic code editing capabilities"""
7071

7172
def __init__(
72-
self, config: dict, environment: Environment, game_context: GameContext
73+
self, config: dict, environment: DockerEnvironment, game_context: GameContext
7374
):
7475
super().__init__(config, environment=environment, game_context=game_context)
7576

codeclash/games/__init__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@
77

88

99
# might consider postponing imports to avoid loading things we don't need
10-
def get_game(config: dict) -> CodeGame:
10+
def get_game(config: dict, **kwargs) -> CodeGame:
1111
game = {
12-
x.name: x for x in [
12+
x.name: x
13+
for x in [
1314
BattleCodeGame,
1415
BattleSnakeGame,
1516
CoreWarGame,
1617
RoboCodeGame,
17-
RobotRumbleGame
18+
RobotRumbleGame,
1819
]
1920
}.get(config["game"]["name"])
2021
if game is None:
2122
raise ValueError(f"Unknown game: {config['game']['name']}")
22-
return game(config)
23+
return game(config, **kwargs)

codeclash/games/abstract.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,15 @@
2424
class CodeGame(ABC):
2525
name: str
2626

27-
def __init__(self, config: dict):
27+
def __init__(self, config: dict, *, push_agent: bool = False):
2828
self.url_gh: str = f"git@github.com:{GH_ORG}/{self.name}.git"
2929
self.artifacts: list[Path] = []
3030
"""Artifact objects that we might want to clean up after the game."""
3131
self.scoreboard: list[tuple[int, str]] = []
3232
"""List of (round number, winner (player id))"""
3333
self.game_config: dict = config["game"]
3434
self.config: dict = config
35+
self.push_agent: bool = push_agent
3536
self.rounds: int = self.game_config.get("rounds", 1)
3637
self.round: int = 0
3738
self.game_id: str = f"{self.name}{time.strftime('%y%m%d%H%M%S')}"
@@ -43,6 +44,13 @@ def __init__(self, config: dict):
4344
self.environment: DockerEnvironment = self.get_environment()
4445
assert len(config["players"]) >= 2, "At least two players are required"
4546

47+
# Initialize agents
48+
from codeclash.agents import get_agent
49+
50+
self.agents: list[Player] = []
51+
for agent_conf in config["players"]:
52+
self.agents.append(get_agent(agent_conf, config["prompts"], self))
53+
4654
@property
4755
def image_name(self) -> str:
4856
return f"codeclash/{self.name.lower()}"
@@ -192,6 +200,21 @@ def _post_round_setup(self, agents: list[Player]):
192200
)
193201
self.logger.info(f"Round {self.round} completed.")
194202

203+
def run(self, cleanup: bool = False):
204+
"""
205+
Run the full game with all configured agents.
206+
"""
207+
try:
208+
for _ in range(self.rounds):
209+
self.run_round(self.agents)
210+
for agent in self.agents:
211+
agent.run()
212+
finally:
213+
self.end(cleanup)
214+
if self.push_agent:
215+
for agent in self.agents:
216+
agent.push()
217+
195218
def run_round(self, agents: list[Player]):
196219
"""
197220
Run a single round of the game with the given agents.

codeclash/games/battlecode/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
class BattleCodeGame(CodeGame):
99
name: str = "BattleCode"
1010

11-
def __init__(self, config):
12-
super().__init__(config)
11+
def __init__(self, config, **kwargs):
12+
super().__init__(config, **kwargs)
1313
assert len(config["players"]) == 2, "BattleCode is a two-player game"
1414
self.run_cmd_round: str = "python run.py run"
1515
for arg, val in self.game_config.get("args", {}).items():

codeclash/games/battlesnake/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
class BattleSnakeGame(CodeGame):
1010
name: str = "BattleSnake"
1111

12-
def __init__(self, config):
13-
super().__init__(config)
12+
def __init__(self, config, **kwargs):
13+
super().__init__(config, **kwargs)
1414
self.run_cmd_round: str = "./battlesnake play"
1515
for arg, val in self.game_config.get("args", {}).items():
1616
if isinstance(val, bool):

codeclash/games/corewar/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
class CoreWarGame(CodeGame):
88
name: str = "CoreWar"
99

10-
def __init__(self, config):
11-
super().__init__(config)
10+
def __init__(self, config, **kwargs):
11+
super().__init__(config, **kwargs)
1212
self.run_cmd_round: str = "./src/pmars"
1313
for arg, val in self.game_config.get("args", {}).items():
1414
if isinstance(val, bool):

codeclash/games/robocode/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
class RoboCodeGame(CodeGame):
99
name: str = "RoboCode"
1010

11-
def __init__(self, config):
12-
super().__init__(config)
11+
def __init__(self, config, **kwargs):
12+
super().__init__(config, **kwargs)
1313
self.run_cmd_round: str = "./robocode.sh"
1414
for arg, val in self.game_config.get("args", {}).items():
1515
if isinstance(val, bool):

codeclash/games/robotrumble/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
class RobotRumbleGame(CodeGame):
77
name: str = "RobotRumble"
88

9-
def __init__(self, config):
10-
super().__init__(config)
9+
def __init__(self, config, **kwargs):
10+
super().__init__(config, **kwargs)
1111
assert len(config["players"]) == 2, "RobotRumble is a two-player game"
1212
self.run_cmd_round: str = "./rumblebot run term"
1313

main.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,15 @@
22

33
import yaml
44

5-
from codeclash.agents import get_agent
6-
from codeclash.agents.abstract import Player
75
from codeclash.games import get_game
86
from codeclash.games.abstract import CodeGame
97

108

119
def main(config_path: str, cleanup: bool = False, push_agent: bool = False):
1210
with open(config_path, "r") as f:
1311
config = yaml.safe_load(f)
14-
game: CodeGame = get_game(config)
15-
agents: list[Player] = []
16-
for agent_conf in config["players"]:
17-
agents.append(get_agent(agent_conf, config["prompts"], game))
18-
19-
try:
20-
for _ in range(game.rounds):
21-
game.run_round(agents)
22-
for agent in agents:
23-
agent.run()
24-
finally:
25-
game.end(cleanup)
26-
if push_agent:
27-
for agent in agents:
28-
agent.push()
12+
game: CodeGame = get_game(config, push_agent=push_agent)
13+
game.run(cleanup=cleanup)
2914

3015

3116
if __name__ == "__main__":

0 commit comments

Comments
 (0)