Skip to content

RobotRumble

Rust-based robot programming game with modern language features.

Overview

RobotRumble is a programming game where players write Rust code to control robots in arena battles.

Game Rules

  • Programs written in Rust
  • Robots battle in 2D grid
  • Move, attack, and coordinate
  • Team with most units wins

Configuration Example

game:
  name: RobotRumble
  rounds: 10
  sims_per_round: 3
  timeout: 300

players:
  - name: RustBot1
    model: gpt-4
  - name: RustBot2
    model: claude-3

Implementation

codeclash.arenas.robotrumble.robotrumble.RobotRumbleArena

RobotRumbleArena(config, **kwargs)

Bases: CodeArena

Source code in codeclash/arenas/robotrumble/robotrumble.py
26
27
28
29
30
31
32
33
34
35
36
37
38
def __init__(self, config, **kwargs):
    super().__init__(config, **kwargs)
    assert len(config["players"]) == 2, "RobotRumble is a two-player game"
    self.run_cmd_round: str = "./rumblebot run term"
    self.sim_ext = "txt"
    for arg, val in self.game_config.get("args", self.default_args).items():
        if isinstance(val, bool):
            if val:
                self.run_cmd_round += f" --{arg}"
                if arg == "raw":
                    self.sim_ext = "json"
        else:
            self.run_cmd_round += f" --{arg} {val}"

name class-attribute instance-attribute

name: str = 'RobotRumble'

description class-attribute instance-attribute

description: str = 'RobotRumble is a turn-based coding battle where you program a team of robots in Python or JavaScript to move, attack, and outmaneuver your opponent on a grid.\nEvery decision is driven by your code, and victory comes from crafting logic that positions robots smartly, times attacks well, and adapts over the 100-turn match.\nNOTE: Please ensure that your code runs efficiently (under 60 seconds). Code that exceeds this run time will automatically forfeit the round.'

default_args class-attribute instance-attribute

default_args: dict = {'raw': True}

submission class-attribute instance-attribute

submission: str = 'robot.js'

run_cmd_round instance-attribute

run_cmd_round: str = './rumblebot run term'

sim_ext instance-attribute

sim_ext = 'txt'

execute_round

execute_round(agents: list[Player])
Source code in codeclash/arenas/robotrumble/robotrumble.py
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def execute_round(self, agents: list[Player]):
    self.logger.info(f"Running game with players: {[agent.name for agent in agents]}")
    args = []
    for agent in agents:
        executable = agent.environment.execute(f"cat {ROBOTRUMBLE_HIDDEN_EXEC}")["output"].strip()
        args.append(f"/{agent.name}/{executable}")
    cmd = f"{self.run_cmd_round} {shlex.join(args)}"
    self.logger.info(f"Running game: {cmd}")

    with ThreadPoolExecutor(8) as executor:
        # Submit all simulations to the thread pool
        futures = [
            executor.submit(self._run_single_simulation, agents, idx, cmd)
            for idx in range(self.game_config.get("sims_per_round", 100))
        ]

        # Collect results as they complete
        i_completed = 0
        for future in as_completed(futures):
            future.result()
            i_completed += 1
            self.logger.info(f"Completed {i_completed} of {len(futures)} simulations")

get_results

get_results(agents: list[Player], round_num: int, stats: RoundStats)
Source code in codeclash/arenas/robotrumble/robotrumble.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
def get_results(self, agents: list[Player], round_num: int, stats: RoundStats):
    winners = []
    for idx in range(self.game_config.get("sims_per_round", 100)):
        output_file = self.log_round(round_num) / f"sim_{idx}.{self.sim_ext}"
        if not output_file.exists():
            self.logger.warning(f"Simulation {idx} not found, skipping")
            continue
        winners.append(
            self._get_winner_txt(output_file, agents)
            if self.sim_ext == "txt"
            else self._get_winner_json(output_file, agents)
        )

    # Count wins
    win_counts = Counter(winners)

    # Find all winners with the maximum count
    max_wins = max(win_counts.values())
    overall_winners = [name for name, count in win_counts.items() if count == max_wins]

    # Update stats
    stats.winner = RESULT_TIE if len(overall_winners) > 1 else overall_winners[0]
    stats.details.append(f"In this round, {agents[0].name} was Blue and {agents[1].name} was Red.")
    stats.scores = dict(win_counts)
    for player, score in win_counts.items():
        if player != RESULT_TIE:
            stats.player_stats[player].score = score

validate_code

validate_code(agent: Player) -> tuple[bool, str | None]
Source code in codeclash/arenas/robotrumble/robotrumble.py
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
def validate_code(self, agent: Player) -> tuple[bool, str | None]:
    # Determine if robot.js or robot.py exists
    ext, exists = None, False
    for possible_ext in MAP_EXT_TO_HEADER.keys():
        exists_output = agent.environment.execute(f"test -f robot.{possible_ext} && echo 'exists'")["output"]
        if "exists" == exists_output.strip():
            ext = possible_ext
            exists = True
            break
    if not exists:
        return False, "There should be a `robot.js` or `robot.py` file"
    agent.environment.execute(f'echo "robot.{ext}" > {ROBOTRUMBLE_HIDDEN_EXEC}')

    # Check that the robot function is defined
    header = MAP_EXT_TO_HEADER[ext]
    if header not in agent.environment.execute(f"cat robot.{ext}")["output"]:
        return (
            False,
            f"robot.{ext} does not contain the required robot function. It should be defined as '{header}'.",
        )
    test_run_cmd = f"{self.run_cmd_round} robot.{ext} robot.{ext} -t 1"
    try:
        test_run = agent.environment.execute(test_run_cmd, timeout=10)["output"]
    except subprocess.TimeoutExpired:
        return (
            False,
            f"Running robot.{ext} (with `{test_run_cmd}`) timed out (10 seconds). Please ensure your code runs efficiently.",
        )
    if "Some errors occurred:" in test_run:
        return False, f"Running robot.{ext} (with `{test_run_cmd}`) resulted in errors:\n{test_run}"
    return True, None