A Gymnasium chess environment for quality-latency research with language agents
Project description
gym-bullet-chess
gym-bullet-chess is a Gymnasium environment for studying whether an agent can
trade move quality against the time consumed by its own reasoning.
The package does not contain a chess engine. python-chess is used only for
rules, legal moves, and outcomes. A language agent may reason, call tools, or
inspect a VLM-ready board image, but all work performed before it submits a move
can consume its clock.
Install
python -m pip install -e ".[dev]"
Python 3.10 or newer is required.
Real-time evaluation
RealTimeClock measures from the instant an observation is returned until the
next action reaches step(). Model inference, network latency, and tool calls
inside that interval are charged to the side to move. Environment execution is
excluded from the next decision's budget.
import gymnasium as gym
import gym_bullet_chess
from gym_bullet_chess import RealTimeClock
env = gym.make(
"BulletChess-v0",
initial_seconds=60.0,
increment_seconds=0.0,
include_board_image=True,
)
env = RealTimeClock(env)
observation, info = env.reset(seed=7)
action = int(observation["action_mask"].nonzero()[0][0])
observation, reward, terminated, truncated, info = env.step(action)
Reproducible latency experiments
Wall time is appropriate for evaluation but unsuitable for deterministic
training. SimulatedClock injects a constant or scheduled latency while
preserving the exact Discrete action contract.
from gym_bullet_chess import BulletChessEnv, SimulatedClock
env = SimulatedClock(
BulletChessEnv(initial_seconds=10.0, increment_seconds=0.1),
think_time=lambda decision_index, action: 0.05 + decision_index * 0.01,
)
The unwrapped environment also exposes
step_timed(action, elapsed_seconds) for explicit experiment orchestration.
Invalid, negative, NaN, and infinite durations are rejected.
Language and vision agents
Set include_board_image=True to include a headless RGB array:
| Key | Shape | Type | Meaning |
|---|---|---|---|
board |
(8, 8, 18) |
float32 |
12 piece planes, turn, castling rights, and en-passant target |
state |
(10,) |
float32 |
Rule state including repetition and claimable-draw features |
clocks |
(2,) |
float32 |
Raw white and black seconds |
action_mask |
(20481,) |
int8 |
Legal move and draw-claim actions |
board_image |
(image_size, image_size, 3) |
uint8 |
Optional Cburnett RGB board image |
info contains the FEN, legal UCI moves, both clocks, current view, last move,
outcome, and timing fields. For language-model tools, use UCIActionWrapper
and format_position_for_llm:
from gym_bullet_chess import (
BulletChessEnv,
RealTimeClock,
UCIActionWrapper,
format_position_for_llm,
)
env = RealTimeClock(UCIActionWrapper(BulletChessEnv(include_board_image=True)))
observation, info = env.reset()
prompt_context = format_position_for_llm(info)
observation, reward, terminated, truncated, info = env.step("e2e4")
The string claim_draw is accepted when a draw is legally claimable.
Actions and perspectives
The discrete action space covers all standard legal moves:
((from_square * 64) + to_square) * 5 + promotion_slot
Promotion slots are none, queen, rook, bishop, and knight. Action 20480 is a
draw claim. This supports underpromotions instead of silently forcing a queen.
With perspective="side_to_move" (the default), board coordinates, images,
action encoding, and action masks all rotate together for Black. Fixed
white, black, and agent perspectives are also available. The helpers
action_for_uci() and uci_for_action() avoid manual encoding.
Play modes
opponent=None: self-play. Each step advances one ply and terminal reward is relative to the side that submitted the action.opponent="random": a seeded legal-move baseline responds automatically. Reward is always relative toagent_color.- Custom opponents implement
select_move(board, rng)and returnOpponentDecision(move, elapsed_seconds). Their latency is charged to their own clock.
The random opponent is a baseline for integration tests, not a substitute for an LLM agent or an evaluation opponent.
Rewards and endings
A win returns +1.0, a loss returns -1.0, and a draw returns 0.0. In
self-play the result is relative to the actor that submitted the terminal action;
against an opponent it is relative to agent_color. Illegal actions terminate
the episode with illegal_move_reward (default -1.0). Clock expiration is a
draw when the non-flagging side lacks mating material.
Experiment trace
env.unwrapped.episode_trace stores one record per decision with actor, source,
integer action, UCI/SAN move, elapsed time, remaining time, and event. Terminal
info["outcome"] records winner, result, and termination cause.
License and assets
The project is GPL-3.0-or-later because python-chess is GPL-3.0-or-later.
Cburnett piece images are freshly downloaded Wikimedia rasterizations. The
upstream multi-license, selected BSD-3-Clause terms, source URL for every file,
and SHA-256 hashes are recorded in
src/gym_bullet_chess/assets/ATTRIBUTION.md.
Other dependency licenses are listed in
THIRD_PARTY_LICENSES.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 gym_bullet_chess-0.1.0.tar.gz.
File metadata
- Download URL: gym_bullet_chess-0.1.0.tar.gz
- Upload date:
- Size: 88.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
392222f1ae81426752ab7037a74c66afe0fd8158cad3835cc7b057f78d79e2cc
|
|
| MD5 |
8fcb722d14fd4cb01a082726720d0fbd
|
|
| BLAKE2b-256 |
4f81cdb652b9ede41d7bb99c7ebf717c66425451718f4ee08e7d291dcf344640
|
Provenance
The following attestation bundles were made for gym_bullet_chess-0.1.0.tar.gz:
Publisher:
release.yml on ChoiCube84/gym-bullet-chess
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gym_bullet_chess-0.1.0.tar.gz -
Subject digest:
392222f1ae81426752ab7037a74c66afe0fd8158cad3835cc7b057f78d79e2cc - Sigstore transparency entry: 2257559260
- Sigstore integration time:
-
Permalink:
ChoiCube84/gym-bullet-chess@f8cf0047604519f7914d3542e6b660de330c938a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ChoiCube84
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f8cf0047604519f7914d3542e6b660de330c938a -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file gym_bullet_chess-0.1.0-py3-none-any.whl.
File metadata
- Download URL: gym_bullet_chess-0.1.0-py3-none-any.whl
- Upload date:
- Size: 89.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a39433c42a98be783d2b39599da49c92c7dd5bad6e0d0d92fa40e6be8c898bd
|
|
| MD5 |
62ff55c3f863899624c2df33e7c57947
|
|
| BLAKE2b-256 |
82b2a2b38987b892158bc8d714c9c787c2ad70f3b50a9d0a118c0e63fc29c99f
|
Provenance
The following attestation bundles were made for gym_bullet_chess-0.1.0-py3-none-any.whl:
Publisher:
release.yml on ChoiCube84/gym-bullet-chess
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gym_bullet_chess-0.1.0-py3-none-any.whl -
Subject digest:
4a39433c42a98be783d2b39599da49c92c7dd5bad6e0d0d92fa40e6be8c898bd - Sigstore transparency entry: 2257559298
- Sigstore integration time:
-
Permalink:
ChoiCube84/gym-bullet-chess@f8cf0047604519f7914d3542e6b660de330c938a -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ChoiCube84
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f8cf0047604519f7914d3542e6b660de330c938a -
Trigger Event:
workflow_dispatch
-
Statement type: