Catan game engine and bot development toolkit
Project description
catan-sdk
A Python game engine and bot development toolkit for Catan. Build a bot locally, test it against the engine, simulate thousands of games, watch replays on the hosted site, and register for the tournament — all from the command line.
Installation
Bot developers — install from PyPI:
pip install catan-sdk
# or with uv:
uv pip install catan-sdk
SDK contributors — clone and install in editable mode:
git clone https://github.com/SirjanK/catan-sdk.git
cd catan-sdk
uv sync --extra dev # installs all deps from uv.lock (reproducible)
# pip fallback: pip install -e ".[dev]"
Building a Bot
1. Implement the Player interface
Copy the example template and implement all seven methods:
cp submissions/example_bot.py submissions/my_bot.py
# submissions/my_bot.py
from catan.player import Player
from catan.models.state import GameState
from catan.models.actions import PlaceSettlement, PlaceRoad, RollDice, Pass
class MyBot(Player):
def __init__(self, player_id: int, seed: int = 0):
self.player_id = player_id
def setup_place_settlement(self, state: GameState) -> PlaceSettlement: ...
def setup_place_road(self, state, settlement_vid: int) -> PlaceRoad: ...
def pre_roll_action(self, state: GameState): ... # RollDice or PlayKnight
def discard_cards(self, state, required: int): ... # DiscardCards
def move_robber(self, state: GameState): ... # MoveRobber
def take_turn(self, state: GameState): ... # build / trade / Pass / …
def respond_to_trade(self, state, offer): ... # AcceptTrade or RejectTrade
The GameState you receive is a deep copy — mutate it freely. Opponent resource hands and dev cards are hidden (zeroed out); all board state, VP counts, piece counts, and resource_count / dev_cards_count are public.
See catan/players/basic_player.py for a complete reference implementation.
The 7 Player methods
| Method | Phase | Return type |
|---|---|---|
setup_place_settlement(state) |
Setup | PlaceSettlement |
setup_place_road(state, settlement_vid) |
Setup | PlaceRoad |
pre_roll_action(state) |
Start of turn | RollDice or PlayKnight |
discard_cards(state, required) |
After 7 rolled | DiscardCards |
move_robber(state) |
After knight/7 | MoveRobber |
take_turn(state) |
Main turn | Any valid action or Pass |
respond_to_trade(state, offer) |
Any player's turn | AcceptTrade or RejectTrade |
2. Validate your bot
Run the fixture test suite against your bot (31 tests covering every method and edge case):
pytest catan/tests/test_dev_validator.py --player=submissions.my_bot:MyBot -v
Each failing test shows the scenario, what your bot returned, why it was rejected, and a hint to fix it.
3. Play a game
Run your bot against the built-in reference bot and watch what happens:
python -m catan.run catan/examples/four_basic_players.yaml
# → writes tmp/games/<timestamp>.jsonl
To mix your bot in, edit the YAML:
players:
- type: custom
module: submissions.my_bot
class: MyBot
- type: basic
- type: basic
- type: basic
4. Watch the replay
Drag the .jsonl file into the hosted viewer at https://<tournament-site>/viewer.
- Arrow keys ← → step through actions frame by frame
- End key jumps to the final game state
- No login required
5. Simulate many games
python -m catan.sim \
--bot submissions.my_bot:MyBot \
--bot basic:BasicPlayer \
--games 200 \
--workers 4 \
--save-logs
Results — 200 games, random boards
Bot Games Wins Win% Avg VP Avg Place 1st 2nd 3rd 4th
MyBot 200 82 41.0% 7.6 1.8 41% 28% 21% 10%
BasicPlayer 200 38 19.0% 6.0 2.6 19% 24% 27% 30%
Logs saved to: tmp/sim/run_20260419_120000/
View results: upload tmp/sim/run_20260419_120000/index.json to the tournament site's Viewer → Batch Results tab
Key flags:
| Flag | Default | Description |
|---|---|---|
--games N |
100 | Number of games |
--workers N |
1 | Parallel processes |
--fixed-board |
off | Reuse one board across all games (isolates bot skill from board luck) |
--board-seed N |
same as --seed |
Seed for the fixed board |
--save-logs |
off | Write per-game .jsonl files |
--output FILE |
— | Write JSON summary to a file |
6. Browse simulation results on the hosted viewer
Upload the tmp/sim/<run>/ folder (or just index.json) to the Batch Results tab at https://<tournament-site>/viewer:
- Sortable/filterable table of all games with winner, VP, and turn count
- Click any game to step through it frame by frame inline
7. Package and register for the tournament
# Validate and package into a zip
python -m catan.submit submissions.my_bot:MyBot # → MyBot.zip
# Upload to the tournament server
python -m catan.register \
--url https://<tournament-site> \
--username player1 \
--zip MyBot.zip \
--name "My Bot v2" # optional; defaults to zip filename stem
catan.register caches your JWT at ~/.catan/tokens.json so you only need to enter your password once per day.
What's in the SDK
catan-sdk/
submissions/
README.md ← read this first
example_bot.py ← minimal stub — copy and implement all 7 methods
heuristic_bot.py ← advanced reference: strategic heuristic bot (~2.5× BasicPlayer win rate)
catan/
player.py ← Player ABC — implement this
models/ ← Pydantic v2 models (GameState, actions, enums, board)
engine/
engine.py ← CatanEngine — runs a full game
executor.py ← state mutation functions
validator.py ← action validation + resource cost constants
logger.py ← GameLogger — writes JSONL replay files
dev_validator.py ← 31 fixture tests for bot validation
board/ ← board generation and topology
players/
basic_player.py ← simple reference bot (builds city > settlement > road > dev card)
heuristic_bot.py ← advanced reference (see submissions/heuristic_bot.py)
helpers.py ← public utilities: vertex_pip_score, valid_settlement_spots, etc.
registry.py ← local bot registry for YAML-driven games ("basic", "heuristic")
config.py ← GameConfig, PlayerConfig (YAML → Pydantic)
run.py ← `python -m catan.run` CLI
sim.py ← `python -m catan.sim` batch simulation CLI
submit.py ← `python -m catan.submit` bot packager
register.py ← `python -m catan.register` tournament registration
tests/ ← engine correctness tests
examples/
four_basic_players.yaml
heuristic_vs_basic.yaml ← 1 HeuristicBot vs 3 BasicPlayers
Helper utilities
catan.players.helpers exposes common board-query functions so you don't have to reimplement them:
from catan.players.helpers import (
vertex_pip_score, # sum of pip weights at a vertex (use for placement scoring)
valid_settlement_spots, # vertices where you can build a settlement right now
valid_road_edges, # edges where you can build a road right now
best_city_vertex, # your most productive settlement to upgrade
has_resources, # bool: can the player afford this cost?
resource_deficit, # dict: resources still needed for a cost
)
Contributing to the engine
See CONTRIBUTING.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file catan_sdk-0.1.1.tar.gz.
File metadata
- Download URL: catan_sdk-0.1.1.tar.gz
- Upload date:
- Size: 147.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6187c0e7ebe1e03c177ca17618e06378a9c740a7d47830cce919fc24b9f45428
|
|
| MD5 |
1a96f2abf3d4a19ed787e4c6b5eab508
|
|
| BLAKE2b-256 |
aa5e77cfddf1e9bc1ee0234fb388dc0271405e9349e1ba4fe452f205de3a82e9
|
Provenance
The following attestation bundles were made for catan_sdk-0.1.1.tar.gz:
Publisher:
release.yml on SirjanK/catan-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
catan_sdk-0.1.1.tar.gz -
Subject digest:
6187c0e7ebe1e03c177ca17618e06378a9c740a7d47830cce919fc24b9f45428 - Sigstore transparency entry: 1384643740
- Sigstore integration time:
-
Permalink:
SirjanK/catan-sdk@8ed69fc71c2d31a6682ddfb4ec346cf1bb86b336 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/SirjanK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ed69fc71c2d31a6682ddfb4ec346cf1bb86b336 -
Trigger Event:
push
-
Statement type:
File details
Details for the file catan_sdk-0.1.1-py3-none-any.whl.
File metadata
- Download URL: catan_sdk-0.1.1-py3-none-any.whl
- Upload date:
- Size: 101.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
02f063bcc66b6a6b84c1fda5088ee186b88f62442c398f228c93b464215604fe
|
|
| MD5 |
18db8767b5a78f11b358dea590c5ba66
|
|
| BLAKE2b-256 |
399d5e7c1c82a08b5e2dd4cc9d83ba5dc722a2f899706926210e60b0d0b0b523
|
Provenance
The following attestation bundles were made for catan_sdk-0.1.1-py3-none-any.whl:
Publisher:
release.yml on SirjanK/catan-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
catan_sdk-0.1.1-py3-none-any.whl -
Subject digest:
02f063bcc66b6a6b84c1fda5088ee186b88f62442c398f228c93b464215604fe - Sigstore transparency entry: 1384643763
- Sigstore integration time:
-
Permalink:
SirjanK/catan-sdk@8ed69fc71c2d31a6682ddfb4ec346cf1bb86b336 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/SirjanK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8ed69fc71c2d31a6682ddfb4ec346cf1bb86b336 -
Trigger Event:
push
-
Statement type: