Skip to content

DummyAgent

Simple test agent for development and debugging.

Overview

DummyAgent is a minimal agent implementation used for testing.

Implementation

codeclash.agents.dummy_agent.Dummy

Dummy(config: dict, environment: DockerEnvironment, game_context: GameContext)

Bases: Player

A dummy player that does nothing. Mainly for testing purposes.

Source code in codeclash/agents/player.py
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
def __init__(
    self,
    config: dict,
    environment: DockerEnvironment,
    game_context: GameContext,
) -> None:
    self.config = config
    self.name = config["name"]
    self._player_unique_id = str(uuid.uuid4())
    """Unique ID that doesn't clash even across multiple games. Used for git tags."""
    self.environment = environment
    self.game_context = game_context
    self.push = config.get("push", False)
    # Force the branch push (used on ladder resume, to overwrite an interrupted rung's partial
    # pushes). Safe here because a run's push branch has a single writer. Uses --force-with-lease.
    self._force_push = config.get("force_push", False)
    self.logger = get_logger(
        self.name,
        log_path=self.game_context.log_local / "players" / self.name / "player.log",
        emoji="👤",
    )
    self._branch_name = config.get("branch", f"{self.game_context.id}.{self.name}")
    self._metadata = {
        "name": self.name,
        "player_unique_id": self._player_unique_id,
        "created_timestamp": int(time.time()),
        "config": self.config,
        "initial_commit_hash": self._get_commit_hash(),
        "branch_name": self._branch_name,
        "round_tags": {},  # mapping round -> tag
        "agent_stats": {},  # mapping round -> agent stats
    }

    if self.push:
        self.logger.info("Will push agent gameplay as branch to remote repository after each round")
        token = os.getenv("GITHUB_TOKEN")
        if not token:
            raise ValueError("GITHUB_TOKEN environment variable is required")
        for cmd in [
            "git remote remove origin",
            f"git remote add origin https://x-access-token:{token}@github.com/{GH_ORG}/{self.game_context.name}.git",
        ]:
            assert_zero_exit_code(self.environment.execute(cmd), logger=self.logger)

    # Handle branch initialization
    if branch_init := config.get("branch_init"):
        # Fetch, then check out the initial branch (creating a tracking branch if needed).
        assert_zero_exit_code(
            self.environment.execute(f"git fetch origin && git checkout {branch_init}"),
            logger=self.logger,
        )
        self.logger.info(f"Checked out initial branch {branch_init}")

    if self._branch_name != branch_init:
        self.logger.info(f"Switching to branch {self._branch_name} for pushing changes")
        if branch_init:
            # Start the push branch at branch_init. get_environment() pre-created a
            # same-named branch at the default branch; a plain checkout would revert the
            # working tree to it, so use -B to re-point it at the current HEAD.
            assert_zero_exit_code(
                self.environment.execute(f"git checkout -B {self._branch_name}"),
                logger=self.logger,
            )
        else:
            # Resume the branch if a previous rung/round pushed it to the remote, else create it.
            # Reset the local branch to the fetched remote tip with -B.
            assert_zero_exit_code(self.environment.execute("git fetch origin"), logger=self.logger)
            if (
                self.environment.execute(f"git rev-parse --verify --quiet origin/{self._branch_name}").get(
                    "returncode", 1
                )
                == 0
            ):
                assert_zero_exit_code(
                    self.environment.execute(f"git checkout -B {self._branch_name} origin/{self._branch_name}"),
                    logger=self.logger,
                )
            else:
                self.logger.info(f"Branch {self._branch_name} doesn't exist on remote, creating it")
                assert_zero_exit_code(
                    self.environment.execute(f"git checkout -B {self._branch_name}"),
                    logger=self.logger,
                )

run

run()
Source code in codeclash/agents/dummy_agent.py
7
8
def run(self):
    pass

Usage

Useful for: - Testing game implementations - Debugging tournament infrastructure - Baseline performance comparison

Configuration

players:
  - name: DummyPlayer
    type: dummy