Catan game engine and bot development toolkit
Project description
catan-sdk
Public Python SDK for building, testing, simulating, packaging, and registering Catan bots. This is the repo bot authors should start in.
The hosted tournament site is catan.bot.
Quick Start
If you want to build a bot from scratch, this is the shortest sensible path:
- Clone the repo and install dependencies
- Copy the example bot and describe the strategy you want
- Use an agent like Codex or Claude to help implement and iterate
- Run the validator harness until it is clean
- Simulate against
BasicPlayerandHeuristicBot - Package and register the bot
- Browse catan.bot for open tournaments, uploaded bots, and replays
Clone and install
git clone https://github.com/SirjanK/catan-sdk.git
cd catan-sdk
uv sync --extra dev
Start a bot
cp submissions/example_bot.py submissions/my_bot.py
Good prompt for an agent:
Help me build a Catan bot in
submissions/my_bot.py. Keep it legal under the validator, start fromBasicPlayer-level competence, and improve placement, bank trades, and robber targeting step by step.
Best references while iterating:
submissions/example_bot.py— minimal starting stubcatan/players/basic_player.py— simplest complete legal botsubmissions/heuristic_bot.py— stronger strategic baselinesubmissions/planner_bot.py— cleaner goal-oriented strategy example
Validate locally
uv run pytest catan/tests/test_dev_validator.py --player=submissions.my_bot:MyBot -v
That pytest file runs 33 tests, backed by 31 internal DevValidator checks. All of them should pass before you upload.
Simulate
uv run python -m catan.sim \
--bot submissions.my_bot:MyBot \
--bot basic:BasicPlayer \
--games 200 \
--workers 4
uv run python -m catan.sim \
--bot submissions.my_bot:MyBot \
--bot submissions.heuristic_bot:HeuristicBot \
--games 200 \
--workers 4
Package and register
uv run python -m catan.submit submissions.my_bot:MyBot
uv run python -m catan.register \
--username your_username \
--zip MyBot.zip
catan.register defaults to https://catan.bot. Override it with --url or CATAN_SERVER_URL when targeting a local or private deployment.
After uploading, sign in at catan.bot, browse tournaments, and join any open bracket you are eligible for.
Installation
Bot developers
Install from PyPI:
pip install catan-sdk
# or
uv pip install catan-sdk
SDK contributors
Use an editable checkout:
git clone https://github.com/SirjanK/catan-sdk.git
cd catan-sdk
uv sync --extra dev
Building a Bot
1. Implement the Player interface
cp submissions/example_bot.py submissions/my_bot.py
from catan.player import Player
from catan.models.state import GameState
from catan.models.actions import PlaceSettlement, PlaceRoad
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: GameState, settlement_vertex_id: int) -> PlaceRoad: ...
def pre_roll_action(self, state: GameState): ...
def discard_cards(self, state: GameState, count: int): ...
def move_robber(self, state: GameState): ...
def take_turn(self, state: GameState): ...
def respond_to_trade(self, state: GameState, proposal): ...
The GameState passed to your bot is a deep copy. Opponent hands are hidden, but board state, piece counts, public VP, resource_count, and dev_cards_count are visible.
The 7 Player methods
| Method | Phase | Return type |
|---|---|---|
setup_place_settlement(state) |
Setup | PlaceSettlement |
setup_place_road(state, settlement_vertex_id) |
Setup | PlaceRoad |
pre_roll_action(state) |
Start of turn | RollDice or PlayKnight |
discard_cards(state, count) |
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, proposal) |
Any player's turn | AcceptTrade or RejectTrade |
2. Validate your bot
uv run pytest catan/tests/test_dev_validator.py --player=submissions.my_bot:MyBot -v
The local harness covers setup, robber movement, discards, dev card timing, trade responses, piece limits, and state immutability.
3. Run a game locally
uv run python -m catan.run catan/examples/four_basic_players.yaml
To mix your own bot into a YAML:
players:
- type: custom
module: submissions.my_bot
class: MyBot
- type: basic
- type: basic
- type: basic
4. Watch replays
Drag a .jsonl replay into the public viewer at https://catan.bot/viewer.
Use:
- left/right arrow keys to step through frames
- End to jump to the final state
- Batch Results to inspect full simulation folders
5. Simulate many games
uv run python -m catan.sim \
--bot submissions.my_bot:MyBot \
--bot basic:BasicPlayer \
--games 200 \
--workers 4 \
--save-logs
Example output:
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%
Useful flags:
| Flag | Default | Description |
|---|---|---|
--games N |
100 | Number of games |
--workers N |
1 | Parallel processes |
--fixed-board |
off | Reuse one board across all games |
--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 |
With --save-logs, upload tmp/sim/<run>/ or index.json to https://catan.bot/viewer.
6. Package and register for the tournament
uv run python -m catan.submit submissions.my_bot:MyBot
uv run python -m catan.register \
--token ctn_<your_token> \
--zip MyBot.zip \
--name "My Bot v2"
You can also use username/password:
uv run python -m catan.register \
--username your_username \
--zip MyBot.zip
API tokens are created from the logged-in site at Settings -> API Tokens.
Unsupported Dependencies
Bot submissions are only allowed to import from the approved runtime dependency set. If you need a package that is not currently supported:
- open an issue or PR in
catan-sdk - explain the use case and why the dependency is needed for bots
- update both:
pyproject.tomlunder[project.optional-dependencies.bot-extras]catan/approved_imports.py
- include any validator or packaging adjustments if the new dependency changes the bot author workflow
That PR can then be reviewed for safety, footprint, and tournament compatibility before the dependency is made available to bot authors.
What's in the SDK
catan-sdk/
submissions/
README.md ← quick-start bot builder guide
example_bot.py ← minimal stub — copy this first
heuristic_bot.py ← advanced reference bot
planner_bot.py ← planning-style reference bot
catan/
player.py ← Player ABC
models/ ← Pydantic v2 models
engine/
engine.py ← full game loop
executor.py ← state mutation functions
validator.py ← action validation + cost helpers
dev_validator.py ← bot validation harness
logger.py ← JSONL replay logger
board/ ← board generation + topology
players/
basic_player.py ← baseline legal bot
heuristic_bot.py ← advanced reference implementation
helpers.py ← public utilities for bot authors
registry.py ← YAML short-name registry
run.py ← local game CLI
sim.py ← batch simulation CLI
submit.py ← bot packaging CLI
register.py ← tournament registration CLI
Helper utilities
from catan.players.helpers import (
vertex_pip_score,
valid_settlement_spots,
valid_road_edges,
best_city_vertex,
has_resources,
resource_deficit,
)
Contributing
See CONTRIBUTING.md if you want to contribute to the SDK itself.
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.2.tar.gz.
File metadata
- Download URL: catan_sdk-0.1.2.tar.gz
- Upload date:
- Size: 144.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b5b1bc6f0ca965a779cb3f71bd5f8d389f08d7f87960911e21c61d5fc581050
|
|
| MD5 |
09d57de8e62d62b3079d0960c3fbfb0c
|
|
| BLAKE2b-256 |
440c0444f5a08adabce74da104a3e1f1a8df744d1d803017cdc7fc0a89f2e7cd
|
Provenance
The following attestation bundles were made for catan_sdk-0.1.2.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.2.tar.gz -
Subject digest:
3b5b1bc6f0ca965a779cb3f71bd5f8d389f08d7f87960911e21c61d5fc581050 - Sigstore transparency entry: 1391765833
- Sigstore integration time:
-
Permalink:
SirjanK/catan-sdk@0153d3995f2680685834a52dbaa927f6861685db -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/SirjanK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0153d3995f2680685834a52dbaa927f6861685db -
Trigger Event:
push
-
Statement type:
File details
Details for the file catan_sdk-0.1.2-py3-none-any.whl.
File metadata
- Download URL: catan_sdk-0.1.2-py3-none-any.whl
- Upload date:
- Size: 101.8 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 |
a3657d9ccec6e83d0d587735984c3653be96f828368e745b6a6fa5bca473fb5e
|
|
| MD5 |
b72e9ce45fdf9d73af41495d8fc810cd
|
|
| BLAKE2b-256 |
aee1771d9180983783d410aef4cbbd2a6065a811ce6f48d363db61b91497b9cf
|
Provenance
The following attestation bundles were made for catan_sdk-0.1.2-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.2-py3-none-any.whl -
Subject digest:
a3657d9ccec6e83d0d587735984c3653be96f828368e745b6a6fa5bca473fb5e - Sigstore transparency entry: 1391765835
- Sigstore integration time:
-
Permalink:
SirjanK/catan-sdk@0153d3995f2680685834a52dbaa927f6861685db -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/SirjanK
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@0153d3995f2680685834a52dbaa927f6861685db -
Trigger Event:
push
-
Statement type: