Skip to content

AbstractTournament

The base class for all tournament types in CodeClash.

Overview

The AbstractTournament class provides:

  • Tournament initialization and configuration
  • Logging infrastructure
  • Metadata collection
  • Common utilities for tournament orchestration

Specific tournament types (PvP, SinglePlayer) extend this class.

Tournament Structure

Configuration

All tournaments are configured via YAML files:

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

players:
  - name: Agent1
    model: gpt-4
  - name: Agent2
    model: claude-3

Output Directory Structure

logs/
└── {tournament_id}/
    ├── tournament.log          # Main tournament log
    ├── game.log               # Game-specific log
    ├── everything.log         # Combined log
    ├── metadata.json          # Tournament metadata
    ├── players/
    │   └── {player_name}/
    │       ├── player.log
    │       └── changes_r{N}.json
    └── rounds/
        └── {round_num}/
            └── game logs...

Metadata

Tournament metadata is stored in metadata.json:

{
  "name": "pvp",
  "tournament_id": "pvp.BattleCode.251104123456",
  "created_timestamp": 1730736896,
  "config": {
    "game": {...},
    "players": [...]
  }
}

See Also

Class Reference

codeclash.tournaments.tournament.AbstractTournament

AbstractTournament(config: dict, *, name: str, output_dir: Path, **kwargs)
Source code in codeclash/tournaments/tournament.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def __init__(self, config: dict, *, name: str, output_dir: Path, **kwargs):
    self.config: dict = config
    self.name: str = name
    self.tournament_id: str = f"{self.name}.{config['game']['name']}.{time.strftime('%y%m%d%H%M%S')}"
    self._output_dir: Path = output_dir
    self._metadata: dict = {
        "name": self.name,
        "tournament_id": self.tournament_id,
        "config": self.config,
        "created_timestamp": int(time.time()),
        "aws": get_aws_metadata(),
    }
    self.logger = get_logger(self.name, log_path=self.local_output_dir / "tournament.log", emoji="🏆")
    self._root_file_handler = add_root_file_handler(self.local_output_dir / "everything.log")

config instance-attribute

config: dict = config

name instance-attribute

name: str = name

tournament_id instance-attribute

tournament_id: str = f'{name}.{config['game']['name']}.{strftime('%y%m%d%H%M%S')}'

logger instance-attribute

logger = get_logger(name, log_path=local_output_dir / 'tournament.log', emoji='🏆')

local_output_dir property

local_output_dir: Path

get_metadata

get_metadata() -> dict
Source code in codeclash/tournaments/tournament.py
34
35
def get_metadata(self) -> dict:
    return self._metadata

cleanup_handlers

cleanup_handlers() -> None

Close and remove file handlers to prevent file descriptor leaks.

Source code in codeclash/tournaments/tournament.py
37
38
39
40
41
42
43
44
45
46
def cleanup_handlers(self) -> None:
    """Close and remove file handlers to prevent file descriptor leaks."""
    # Close the root file handler
    remove_file_handler(logging.getLogger(), self._root_file_handler)

    # Close logger's file handlers
    for handler in self.logger.handlers[:]:  # Copy list to avoid modification during iteration
        if isinstance(handler, logging.FileHandler):
            self.logger.removeHandler(handler)
            handler.close()