Python SDK for building and running Game Arena competition bots
Project description
Game Arena Python SDK
Build Python bots for Game Arena. Implement on_move(); the SDK handles
authentication, matchmaking, game connections, and the turn protocol.
Requires Python 3.11+. Game rules and board formats live in the Bot Docs page of the Game Arena web app.
Install and prepare
pip install --upgrade game-ai-arena-sdk
Use SDK 0.6.1 or newer for continuous ranked play.
Create a bot in the web app and save its Bot ID and API key. The key may only be shown once. Then configure the matchmaker URL supplied by your administrator:
export MATCHMAKER_URL="wss://<arena-host>/matchmaking/ws"
Use ws:// only for an arena served without HTTPS.
Your first bot
This complete FlipFlop bot chooses a random legal move:
import random
from game_ai_arena_sdk import Bot, GameStateLoop, Move, start_continuous
class MyBot(Bot):
async def on_move(self, state: GameStateLoop) -> Move:
piece = random.choice(state.legal_moves)
destination = random.choice(piece.valid_moves)
return Move(from_pos=piece.pos, to_pos=destination)
bot = MyBot(bot_id="YOUR_BOT_ID", api_key="YOUR_API_KEY")
if __name__ == "__main__":
start_continuous(bot)
python my_bot.py
start_continuous() verifies and displays the bot's registered game and arena
before joining ranked matchmaking. Its compact live display shows the runner
state, opponent, Bot Run record, and last committed result without flooding the
terminal. Its commands are pause, resume, status, stop, help,
display compact, and display verbose. Commands remain editable while games
update the display. Stop and Ctrl-C finish any active game before disconnecting.
Adapt it for your game
Always choose from state.legal_moves, then preserve the fields required by
that game:
| Game | GameType |
Returned Move |
|---|---|---|
| FlipFlop 3x3 | GameType.FLIPFLOP_3X3 |
Move(from_pos=piece.pos, to_pos=destination) |
| FlipFlop 5x5 | GameType.FLIPFLOP_5X5 |
Move(from_pos=piece.pos, to_pos=destination) |
| FlipFour | GameType.FLIPFOUR |
Also pass side for a piece in "HAND" |
| Amoeba | GameType.AMOEBA |
Also pass the legal move's splitting value |
# FlipFour
side = piece.name if piece.pos == "HAND" else None
return Move(from_pos=piece.pos, to_pos=destination, side=side)
# Amoeba
return Move(
from_pos=piece.pos,
to_pos=destination,
splitting=piece.splitting,
)
Missing these fields is a common cause of INVALID_MOVE.
Build a better bot
The random bot only proves the connection works. A stronger bot should:
- Parse
state.boardusing its game's documented format. - Evaluate every legal action from
state.my_sideusing heuristics, search, or a model. - Return the best action with its game-specific fields intact.
- Run in Practice Mode before entering ranked play.
Keeping this logic in choose_move(state) -> Move separates bot strategy from
SDK lifecycle code.
Execution modes
start*() functions block and suit ordinary scripts. run*() functions are
coroutines for code that already uses asyncio.
| Need | API |
|---|---|
| Interactive continuous ranked play (recommended) | start_continuous(bot, display="compact") |
| Headless continuous ranked play | await run_continuous(bot, game_type) |
| One ranked game | start(bot, game_type) / await run(bot, game_type) |
| One practice game | start_practice(...) / await run_practice(...) |
| Custom continuous controls | ContinuousRunner |
start_continuous() detects the registered game and adds terminal controls.
Compact display is the default; pass display="verbose" or switch modes while
running. Redirected input or output automatically uses plain verbose output.
Headless run_continuous() requires an explicit GameType and returns the
final immutable RunnerStatus, including safe failure details when the runner
fails.
Practice Mode connects directly to a room from the web app and does not affect rating:
from game_ai_arena_sdk import start_practice
start_practice(
bot,
room_id="ROOM_ID_FROM_PRACTICE_ARENA",
game_server_ws="wss://GAME_SERVER_URL_FROM_PRACTICE_ARENA",
)
For custom operation, ContinuousRunner provides pause(), resume(),
status(), stop(), and wait().
If phase visibility changes while the bot is queued, the continuous runner rejoins automatically on the same Bot Run and preserves whether it was paused. A switch to Blind removes an earlier rating from public status and the compact display even when the bot is already playing.
Core data
| Type | Important fields |
|---|---|
GameStateLoop |
board, my_side, current_turn, legal_moves |
PieceMovesInfo |
name, pos, valid_moves, optional splitting |
Move |
from_pos, to_pos, optional side, optional splitting |
MatchFinishedResult |
result, end_reason, opponent, run, finished_at, optional rating |
RunnerStatus |
state, run, opponent, last_result, safe failure fields |
board is game-specific. legal_moves is the server-provided set of allowed
actions. MatchFinishedResult is immutable and arrives after a continuous
ranked result is committed; its rating is absent during phases that hide it.
Lifecycle hooks
Override only what you need. on_move() is the only required hook.
| Hook | Called when |
|---|---|
on_move(state) -> Move |
Your turn requires a move |
on_ready() |
The SDK connects |
on_queue_entry() |
The bot joins matchmaking |
on_queue_exit() |
The bot leaves the queue or finds a match |
on_match_found(game_id) |
A game is assigned |
on_room_joined(room_id) |
The game room is joined |
on_game_start(state) |
Gameplay starts |
on_game_end(winner, state) |
Gameplay ends |
on_match_finished(result) |
The ranked result is committed in continuous play |
on_disconnect(reason) |
Reserved for disconnect notifications |
There is no on_error hook. Handle decision errors inside on_move() and SDK
failures around the chosen entry point.
Errors and troubleshooting
Game-server protocol failures raise GameArenaProtocolError with code,
message, and optional details. Continuous play fails closed after an
uncertain failure instead of silently joining another game.
| Problem | Check |
|---|---|
| Authentication rejected | Bot ID and API key |
INVALID_MOVE |
Use legal_moves; preserve side or splitting |
| Cannot connect | Arena hostname and ws:// versus wss:// |
| Two test bots never match | Bots owned by the same user cannot match |
| Continuous play stops | Read the display or RunnerStatus.failure_code and failure_message; unsafe requeueing is prevented |
For game rules, coordinates, strategy, arena URLs, and deeper troubleshooting, open Bot Docs in the Game Arena web app.
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 game_ai_arena_sdk-0.6.1.tar.gz.
File metadata
- Download URL: game_ai_arena_sdk-0.6.1.tar.gz
- Upload date:
- Size: 33.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b70a7434535a9cff567d846cb7f92130bac2c1f58e75f827baba8168dcc8ae6
|
|
| MD5 |
ac7f2d22b927bc9ca8babfb3117b98b9
|
|
| BLAKE2b-256 |
a8a3f5c2e6794e76e873f0e9093c3ac4268854a6fc9e5715cd1a7347da46fab5
|
File details
Details for the file game_ai_arena_sdk-0.6.1-py3-none-any.whl.
File metadata
- Download URL: game_ai_arena_sdk-0.6.1-py3-none-any.whl
- Upload date:
- Size: 47.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
301846e0cd5aec507fa0926e05590c9d823dfc7a96d20be3519b4bf40ab2520f
|
|
| MD5 |
546ec5d34d9cfc95826ce1f33da7fe1d
|
|
| BLAKE2b-256 |
89869429ba99b327199887750e60b8541746c7915e99036e4e1fed12cce3fdce
|