A fast, reusable Python engine for Hexo on an infinite hex grid.
Project description
Hexo Engine
Hexo is a Python engine for the Hexo game played on an infinite hex grid.
The goal of this repository is to provide a clean, reusable engine API (similar in spirit to python-chess) so others can build bots, analysis tools, and frontends without re-implementing game logic.
Game rules are documented in RULES.md. Agent handoff context is documented in AGENT_CONTEXT.md.
Features
- Deterministic game engine with strict rule validation
- Infinite hex-grid coordinate model
- Opening and turn rules enforced by the engine
- Win detection (connect 6 on any hex axis)
- Undo support for search algorithms
Installation
Requirements
- UV package manager
Clone the repository
git clone https://github.com/<your-org>/hexo.git
cd hexo
Initialize your environment
uv sync
uv run pre-commit install
API
Public entry point is the Hexo class.
Hexo.new(config=None) -> Hexo: create a new game withP1already placed at(0, 0).Hexo.from_state(state, config=None) -> Hexo: restore a game from serialized state.game.to_state() -> dict: serialize committed turns and any in-progress partial turn.game.turn() -> Player: return the player currently placing stones.game.status() -> GameStatus: returnONGOING,P1_WON, orP2_WON.game.moves_left_in_turn() -> int: return remaining moves in current turn (2or1).game.pending_moves() -> tuple[Coord, ...]: return moves already made in the current turn.game.is_legal_move(coord) -> tuple[bool, str | None]: validate one submove.game.legal_moves -> Collection[Coord]: property that returns legal single-move candidates as a live iterable view.game.push(coord) -> TurnRecord | None: play one move; returnsNoneif turn is still partial, orTurnRecordwhen the turn completes (or wins early).game.is_legal(move) -> tuple[bool, str | None]: validate a full 2-stone move (only when no partial turn is active).game.play(move) -> TurnRecord: convenience wrapper that places two stones in sequence.game.undo() -> TurnRecord: undo the last placement (works for both partial and completed turns).game.at(coord) -> Player | None: inspect occupancy at a coordinate.game.board() -> dict[Coord, Player]: get a snapshot of all occupied coordinates.
Notes:
Hexo.new()starts withP1already placed at(0, 0).- Every played turn is a 2-stone move.
Quickstart
from hexo import Hexo
game = Hexo.new()
print(game.turn()) # Player.P2
legal, reason = game.is_legal_move((1, 0))
if not legal:
raise ValueError(reason)
game.push((1, 0))
# Hook point for engines: run a search after first placement.
# ... search code here ...
record = game.push((0, 1)) # turn completes here
print(record) # TurnRecord
print(game.moves_left_in_turn()) # 2
state = game.to_state()
restored = Hexo.from_state(state)
print(restored.turn())
Tests, linting and formatting
uv run pytest
uvx ruff check . --fix
uvx ruff format .
Run all hooks manually:
uv run pre-commit run --all-files
Benchmarks
Benchmarking uses pytest-benchmark and is kept separate from normal tests.
Run benchmarks:
uv run pytest benchmarks --benchmark-only
Save a baseline:
uv run pytest benchmarks --benchmark-only --benchmark-save=baseline
Compare with a saved baseline:
uv run pytest benchmarks --benchmark-only --benchmark-compare=baseline
Contributing
See CONTRIBUTING.md for:
- issue reporting guidelines
- feature proposal flow
- pull request requirements
- code style and testing expectations
License
This project is licensed under the MIT LICENSE
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 hexo-0.2.0.tar.gz.
File metadata
- Download URL: hexo-0.2.0.tar.gz
- Upload date:
- Size: 49.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0954d04311acf1ca21e10ec30fa837b13fcbbd25c449aa10c9a980e58407c2b
|
|
| MD5 |
fd97e97a25f9897b81ee41cfbf6560e0
|
|
| BLAKE2b-256 |
6ba45919884549da4d82129122232674ea71fefbdb356ea754e579f4f57bec4b
|
Provenance
The following attestation bundles were made for hexo-0.2.0.tar.gz:
Publisher:
python-publish.yml on PierreLapolla/hexo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hexo-0.2.0.tar.gz -
Subject digest:
c0954d04311acf1ca21e10ec30fa837b13fcbbd25c449aa10c9a980e58407c2b - Sigstore transparency entry: 1193053062
- Sigstore integration time:
-
Permalink:
PierreLapolla/hexo@7915362b62736dfdd4a8e0ad2f0a814c95ff2234 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/PierreLapolla
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@7915362b62736dfdd4a8e0ad2f0a814c95ff2234 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hexo-0.2.0-py3-none-any.whl.
File metadata
- Download URL: hexo-0.2.0-py3-none-any.whl
- Upload date:
- Size: 10.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e4c36c086cadf3c2321b4e4874411542f163449124255476fe71f430224c367d
|
|
| MD5 |
f57a788030b913f5902ec91a719247a2
|
|
| BLAKE2b-256 |
547e1410d82baa1afc576dc7d92112db06541f08872c04ed032dae3198f11cdc
|
Provenance
The following attestation bundles were made for hexo-0.2.0-py3-none-any.whl:
Publisher:
python-publish.yml on PierreLapolla/hexo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hexo-0.2.0-py3-none-any.whl -
Subject digest:
e4c36c086cadf3c2321b4e4874411542f163449124255476fe71f430224c367d - Sigstore transparency entry: 1193053090
- Sigstore integration time:
-
Permalink:
PierreLapolla/hexo@7915362b62736dfdd4a8e0ad2f0a814c95ff2234 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/PierreLapolla
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@7915362b62736dfdd4a8e0ad2f0a814c95ff2234 -
Trigger Event:
push
-
Statement type: