Skip to main content

Overview

The GameConfig class centralizes all game constants and configuration values for Codenames. It defines board size, word distributions, turn limits, and validation rules.

Classes

GameConfig

Game configuration constants for Codenames.

Board Configuration

BOARD_SIZE
int
default:"25"
Total number of words on the board
BLUE_WORDS
int
default:"9"
Number of blue team words (starting team gets +1)
RED_WORDS
int
default:"8"
Number of red team words
NEUTRAL_WORDS
int
default:"7"
Number of neutral words
BOMB_COUNT
int
default:"1"
Number of bomb/assassin words

Game Rules

MAX_TURNS
int
default:"50"
Maximum turns before game ends (prevents infinite loops)
MAX_GUESSES_PER_TURN
Optional[int]
default:"None"
Maximum guesses per turn. If None, uses hint_count + 1
STARTING_TEAM
str
default:"BLUE"
Which team starts: “BLUE” or “RED”

Validation

MIN_HINT_COUNT
int
default:"1"
Minimum number for hints
MAX_HINT_COUNT
int
default:"9"
Maximum number for hints (usually team words + 1)

Methods

validate()

Validate that the configuration is internally consistent.
def validate(self) -> bool
Raises:
  • ValueError: If board size < 9
  • ValueError: If board size is even (should be odd for fairness)
  • ValueError: If word counts don’t sum to board size
Returns: True if valid

custom()

Create a custom game configuration with different board size.
@classmethod
def custom(
    cls,
    board_size: int = 25,
    starting_team: str = "BLUE"
) -> GameConfig
board_size
int
default:"25"
Total number of words (must be odd for fair play)
starting_team
str
default:"BLUE"
Which team starts: “BLUE” or “RED”
Returns: New GameConfig instance with proportional word distributions

Usage Examples

Default Configuration

from config import GameConfig

# Use default 25-word configuration
config = GameConfig()

print(f"Board size: {config.BOARD_SIZE}")
print(f"Blue words: {config.BLUE_WORDS}")
print(f"Red words: {config.RED_WORDS}")
print(f"Neutral words: {config.NEUTRAL_WORDS}")
print(f"Bomb count: {config.BOMB_COUNT}")

# Validate configuration
config.validate()  # Returns True

Custom Board Size

from config import GameConfig

# Create 9-word mini game
mini_config = GameConfig.custom(board_size=9, starting_team="BLUE")

print(f"Mini game configuration:")
print(f"  Board size: {mini_config.BOARD_SIZE}")  # 9
print(f"  Blue words: {mini_config.BLUE_WORDS}")   # 4
print(f"  Red words: {mini_config.RED_WORDS}")     # 3
print(f"  Neutral words: {mini_config.NEUTRAL_WORDS}")  # 1
print(f"  Bomb count: {mini_config.BOMB_COUNT}")   # 1

Custom Parameters

from config import GameConfig

# Create configuration with custom parameters
config = GameConfig(
    BOARD_SIZE=25,
    BLUE_WORDS=10,
    RED_WORDS=9,
    NEUTRAL_WORDS=5,
    BOMB_COUNT=1,
    MAX_TURNS=100,
    MAX_GUESSES_PER_TURN=5,
    STARTING_TEAM="RED",
    MIN_HINT_COUNT=1,
    MAX_HINT_COUNT=10
)

# Validate before use
try:
    config.validate()
except ValueError as e:
    print(f"Invalid configuration: {e}")

Integration with Board

from game import Board
from config import GameConfig

# Create custom configuration
config = GameConfig.custom(board_size=15)

# Use with board
board = Board.from_word_list(words, config=config)

Integration with GameRunner

from orchestrator import GameRunner
from config import GameConfig, OrchestratorConfig

# Create configurations
game_config = GameConfig.custom(board_size=25, starting_team="BLUE")
orchestrator_config = OrchestratorConfig()

# Board will use game_config
board = Board.from_word_list(words, config=game_config)

# Runner will inherit config from board
runner = GameRunner(
    board=board,
    blue_hint_giver=blue_hg,
    blue_guesser=blue_g,
    red_hint_giver=red_hg,
    red_guesser=red_g,
    config=orchestrator_config
)

Validation Rules

Board Size Constraints

  1. Minimum size: 9 words (smallest playable game)
  2. Odd number: Board size should be odd for fair play
  3. Sum check: BLUE_WORDS + RED_WORDS + NEUTRAL_WORDS + BOMB_COUNT = BOARD_SIZE

Word Distribution

For custom board sizes, the custom() method calculates proportional distribution:
starting_words = (board_size - 1) // 3 + 1  # ~1/3 + 1
other_words = starting_words - 1
neutral_words = board_size - starting_words - other_words - 1
This ensures the starting team has exactly one more word than the opponent.

Configuration Presets

Standard Game (25 words)

GameConfig()  # Default
# Blue: 9, Red: 8, Neutral: 7, Bomb: 1

Mini Game (9 words)

GameConfig.custom(board_size=9)
# Blue: 4, Red: 3, Neutral: 1, Bomb: 1

Large Game (49 words)

GameConfig.custom(board_size=49)
# Blue: 17, Red: 16, Neutral: 15, Bomb: 1

Config

Main configuration class combining all config sections:
from config import Config

config = Config()
print(config.game.BOARD_SIZE)  # Access GameConfig
print(config.llm.MAX_RETRIES)  # Access LLMConfig
print(config.orchestrator.VERBOSE_DEFAULT)  # Access OrchestratorConfig

Global Configuration Instance

from config import default_config

# Access default configuration
print(default_config.game.BOARD_SIZE)  # 25
print(default_config.llm.DEFAULT_TEMPERATURE)  # 0.7

Backward Compatibility Constants

from config import BOARD_SIZE, BLUE_WORDS, RED_WORDS

# Module-level constants (for backward compatibility)
print(BOARD_SIZE)  # 25
print(BLUE_WORDS)  # 9
print(RED_WORDS)   # 8
Module-level constants are derived from default_config at import time and don’t reflect runtime changes. Use the Config class for dynamic configuration.

Build docs developers (and LLMs) love