Simplified implementations of the HappyHex game components and hexagonal system in Rust.
Project description
hpyhex-rs
Simplified implementations of the HappyHex game components and hexagonal system in Rust.
This is a drop-in replacement for the original hpyhex package, optimized for performance and memory usage.
Installation
pip install hpyhex-rs
Important Notes
-
Conflicting with Native Python Package
hpyhex-rsconflicts with the existinghpyhexpackage on PyPI. If you havehpyhexinstalled, please uninstall it first using:pip uninstall hpyhex
-
Difference in Importing Modules
In
hpyhex-rs, all main classes and functions are located directly under thehpyhexmodule. For example, to import theHexclass, use:from hpyhex import Hex, Game
In contrast, the original
hpyhexpackage requires importing from submodules (hexandgame), such as:from hpyhex.hex import Hex from hpyhex.game import Game
For the best import compatibility, use the following pattern:
try: from hpyhex import Hex, Game # hpyhex-rs hpyhex_version = "hpyhex-rs" except ImportError: from hpyhex.hex import Hex # hpyhex from hpyhex.game import Game # hpyhex hpyhex_version = "hpyhex"
This code attempts to import from
hpyhex-rsfirst, and falls back to the originalhpyhexpackage if that fails, allowing your code to work with either package seamlessly. -
Not Interoperable with Original Package
Due to differences in the Rust implementation,
hpyhex-rsobjects cannot be mixed with the originalhpyhexpackage objects. TheHexofhpyhex-rsis not compatible and cannot be converted to/from theHexofhpyhex, for example.This matters primarily in serialization scenarios, but not in regular usage, as you would typically use either
hpyhexorhpyhex-rsexclusively in a project.If you are using built-in APIs in
hpyhexto serialize data structures (e.g.,int(piece_value),Piece(integer_value)), you can load them back usinghpyhex-rs, and vice versa. The byte representation of pieces is compatible between the two packages.However, if you use a python tool to serialize data structures from
hpyhexas Python objects (e.g.,pickle), you cannot load them back usinghpyhex-rs, and vice versa.hpyhex-rsoffersserializeanddeserializefunctions for its own data structures. -
Does Not Contain
benchmarkModule (Yet)The original
hpyhexpackage contains abenchmarkmodule for performance testing of machine learned, heuristic, determinstic, and random algorithms. This module is not yet implemented inhpyhex-rs, but may be added in future releases. The source code for the benchmark module is very short and can be found online. You may copy it into your project if needed. -
Updates Can Lag Behind Original Package
This package currently targets the 0.2.0 version of
hpyhex. Features from later versions may not be fully supported yet, but may be added in future releases.
Features
- Hexagonal grid representation
- Basic game mechanics for HappyHex
- Utility functions for hexagonal calculations
Author
Developed by William Wu.
License
This project is licensed under the MIT License. See the LICENSE file for details.
Quickstart
- Install the package:
pip install hpyhex
- Import and use the main classes as shown above.
- Create custom algorithms to interact with the game environment.
Main Classes
- Hex: Represents a hexagonal grid coordinate using a custom line-based system. Supports arithmetic, hashing, and tuple compatibility.
- Piece: Represents a shape made of 7 blocks, optimized for memory and performance. Use
PieceFactoryto create pieces by name or byte value. - HexEngine: Manages the hexagonal grid, supports adding pieces, eliminating lines, and computing entropy.
- PieceFactory: Utility for creating pieces by name, byte, or randomly. Provides access to all predefined pieces.
- Game: Manages the game state, piece queue, score, and turn. Supports adding pieces and making moves with algorithms.
Usage
from hpyhex import Hex, Piece, HexEngine
from hpyhex import Game, PieceFactory
# Create a hexagonal coordinate
coo = Hex(0, 1)
# Create a piece by name
piece = PieceFactory.get_piece("triangle_3_a")
# Create a game engine with radius 3
engine = HexEngine(radius=3)
# Add a piece to the engine
engine.add_piece(piece, coo)
# Eliminate lines and get score
score = len(engine.eliminate()) * 5
# Create a game with engine radius and queue size
game = Game(engine=3, queue=5)
print(game)
# Make a move using a custom algorithm
def simple_algorithm(engine, queue):
# Always place the first piece at the center
return 0, Hex(0, 0)
game.make_move(simple_algorithm)
Usage Advices
Use Objects Provided by This Package
When using hpyhex-rs, ensure that you create and manipulate objects (like Hex, Piece, HexEngine, etc.) using the classes provided by this package. Although the API, which is defined in the original hpyhex package, accepts various types of inputs (like tuples for coordinates), using the native classes from hpyhex-rs ensures optimal performance and compatibility.
For example, following the original flyweight pattern in the Hex coordinate class, which uses a cache for small coordinates, the Hex class in hpyhex-rs also has a similar cache in Rust memory, which is not held by the GIL. Effectively, this means small Hex objects do not contain actual data, but just a pointer to a shared object in Rust memory. There are multiple ways to represent a Hex coordinate, either as a tuple (i, k), (i, j, k), or a Hex object. While all of them are accepted by most functions in the API, only Hex participates in the caching mechanism. Therefore, for frequently used coordinates, it is recommended to create and reuse Hex objects from hpyhex-rs instead of using tuples.
Take another example of Piece objects. Like the original optimized Piece in hpyhex, no pieces are created at all. Since there are only a total of 127 pieces made out of blocks, all pieces are pre-defined and stored in a global registry. When you create a piece using Piece(), it simply returns a reference to the corresponding pre-defined piece object. The Rust implementation further optimizes this by storing all piece objects in Rust memory, removing them from the control of the GIL. When expensive piece operations such as count_neighbors are performed, the Rust implementation quickly accesses the piece data and performs raw arithmetic and bit operations in Rust, significantly improving performance compared to the original Python implementation. None of those benefits are provided if integers are used instead of Piece objects, although they may seem smaller in memory. (Remember all Python objects have overhead in memory, and an integer is a Python object too.)
Use Optimized Methods Provided by This Package
When using hpyhex-rs, prefer using methods provided by this package for better performance. If a function is already provided by the package, don't write your own implementation in Python, as it may be less efficient.
To illustrate this, take the example of check_positions of HexEngine. The original hpyhex package implements check_positions in Python as follows:
def check_positions(self, piece: Union[Piece, int]) -> List[Hex]:
if isinstance(piece, int):
piece = Piece(piece)
elif not isinstance(piece, Piece):
raise TypeError("Piece must be an instance of Piece or an integer representing a Piece state")
positions = []
for a in range(self.radius * 2):
for b in range(self.radius * 2):
hex = Hex(a, b)
if self.check_add(hex, piece):
positions.append(hex)
return positions
Obviously, if the fact that hpyhex-rs provides a Rust-backed implementation of check_positions is ignored, the above Python implementation can be used as hpyhex-rs also provides the radius attribute and check_add method. However, this implementation is inefficient as it creates various temporary Python objects, which are managed by the GIL, and performs various method calls (such as range) in Python, which are slow.
The hpyhex-rs package provides a Rust-backed implementation of check_positions, which performs all operations in Rust memory, avoiding the overhead of Python object management and method calls. In the entire expensive process of checking all possible positions, the GIL is only acquired once. The radius is not passed as a Python object, but as a direct integer in the Rust struct. The nested loops are performed in Rust, and Hex objects are created directly as structs without going through Python constructors. Further, instead of calling the check_add method, a special version of check_add that takes in raw Rust structs representing Hex and Piece is used, avoiding the overhead of interacting with Python objects at all. These optimizations mean the Rust-backed check_positions is more than 100 times faster than the native Python implementation, as per benchmarking results.
Don't Reinvent the Wheel
It is tempting to implement your own versions of the various abstractions provided by this package, such as Game, which intuitively is just a combination of HexEngine and a piece queue, and does not offer too much extra customization. Unless your purpose is different from the original intention of hpyhex, it is recommended to use the provided Game class directly, as it interacts with the optimized Rust versions of HexEngine and PieceFactory without the overhead of creating intermediate Python objects. For extra functionality, consider building on top of Game instead of re-implementing it completely.
Not Enough for GUI Applications
If you are building a GUI application for a simple version of HappyHex and deeply hated the original Java codebase, you possibly have pondered upon this package for performance, as it advertises itself as a high-performance implementation of the Python hpyhex package, which has a simple and useful API. Unless you already did a lot of work in Python, however, you should not use Python for your GUI applications, as it is not well-suited for GUI development and may lead to performance issues and a poor user experience. The hpyhex-rs Rust crate, which is inspired by the Python API, not only provides similar functionality and abstractions, which make your transition to that package easier, but also provides further abstractions such as thread-safe guards, extended HexEngine with potential attributes for each cell, and an integrated game environment designed specifically for GUI threading needs. Consider using Rust as your main programming language for GUI applications, or integrate with C++ via FFI to use existing C++ GUI frameworks.
The Statistics
(See bench directory for full benchmarking code and results.)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
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 hpyhex_rs-0.1.1-cp312-cp312-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp312-cp312-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 368.3 kB
- Tags: CPython 3.12, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b5f09b30e6bcce7b9b406c767f92324ee7b4bb3df7dc3ad39dd80921f75a822
|
|
| MD5 |
f058f25d90de4ff63e5ff9b4faf7ee2f
|
|
| BLAKE2b-256 |
59ef2842e1c9ae24c4fc0d0772723b5ded700df81daac7fd8c80b8ef344da251
|
File details
Details for the file hpyhex_rs-0.1.1-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 338.8 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
61afd49da84e43bbbc83dc47e347d522a681c728ca942de96bce1796649d0046
|
|
| MD5 |
4c869a28f5a5c39ea3ba82cb39e3c4d1
|
|
| BLAKE2b-256 |
aafa0c0b1b71cc954dd73761c596a1b6f99c88d0637af10818897a40b6d7eff0
|
File details
Details for the file hpyhex_rs-0.1.1-cp311-cp311-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp311-cp311-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 365.1 kB
- Tags: CPython 3.11, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a741c2e2a0c6d0ccab435fadc6fcdfcdd11f8ea61e0efafb5e8f167a478c2a5
|
|
| MD5 |
c9a202eda78fd81b20eecaf30f97aa68
|
|
| BLAKE2b-256 |
c83da7c688dde6d1237cf1e842bd7ab6a323b732c49a766c4706d619e3039333
|
File details
Details for the file hpyhex_rs-0.1.1-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 335.5 kB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dadccb950c872ddd856b0d75e6ea7066d72b44b1d163aaf25f5f7e00b65addb9
|
|
| MD5 |
7cd8ed34f5dcbfeba37a43179819e541
|
|
| BLAKE2b-256 |
9474e5a5c83420c9b4eb05bc9b4499f5e73b2e4a0097f801f8ad6c4e213a6b93
|
File details
Details for the file hpyhex_rs-0.1.1-cp310-cp310-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp310-cp310-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 365.0 kB
- Tags: CPython 3.10, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58dbdecdbb13efcbb726222907a5500671b074243e6a7024e62cb67c58d70e40
|
|
| MD5 |
b7d7198ea2a04c3583be71ba3a2e21fe
|
|
| BLAKE2b-256 |
789577627b2ba536aed95be4b27722964c6abc468f839c66c4445b9eadfe29fa
|
File details
Details for the file hpyhex_rs-0.1.1-cp310-cp310-macosx_11_0_arm64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp310-cp310-macosx_11_0_arm64.whl
- Upload date:
- Size: 335.4 kB
- Tags: CPython 3.10, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e98aaa8a0cbab52ffe98febd14e7f136930d6dce966f16e5652def06ce2e573
|
|
| MD5 |
d01e27efc3d6e566c6415bfb62cd7869
|
|
| BLAKE2b-256 |
a706e754d8132bc3a56adca09b3aa2fcdc6fa4a05575e67d97861c3dd20bee07
|
File details
Details for the file hpyhex_rs-0.1.1-cp39-cp39-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp39-cp39-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 366.0 kB
- Tags: CPython 3.9, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fee7977ec1fbc3656ecfe36a6b5f970bda2bdc291d1d3f93cfa16a29595af00e
|
|
| MD5 |
cab4321b693e63056cade547280f2682
|
|
| BLAKE2b-256 |
f465ff2b24fe5989a0d6215cb8fc4a424e91b9ce0d5e0cbb18bf311ea46c1fec
|
File details
Details for the file hpyhex_rs-0.1.1-cp39-cp39-macosx_11_0_arm64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp39-cp39-macosx_11_0_arm64.whl
- Upload date:
- Size: 336.6 kB
- Tags: CPython 3.9, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
456181ae7784c2229b4d29d7fd5beca2060b7e727e5bfe2c52b3e827f582add4
|
|
| MD5 |
ebdf849756563d7fc63fcc6f6ffd7aa6
|
|
| BLAKE2b-256 |
d1f26ac316ed2f162a006febe45d4b4a3ee252310c459a29200512b8ce78ee7e
|
File details
Details for the file hpyhex_rs-0.1.1-cp38-cp38-manylinux_2_34_aarch64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp38-cp38-manylinux_2_34_aarch64.whl
- Upload date:
- Size: 366.5 kB
- Tags: CPython 3.8, manylinux: glibc 2.34+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ba7e000c0a28272e4801c47bc567907322ef6528bbc8a9f2da3c4070929e8d52
|
|
| MD5 |
4ffcf7e78da6944f6938810eec362ac3
|
|
| BLAKE2b-256 |
d66a5c699fce3f87993e29ab33d061dc98fe94affe6fc5ee608033d843de0821
|
File details
Details for the file hpyhex_rs-0.1.1-cp38-cp38-macosx_11_0_arm64.whl.
File metadata
- Download URL: hpyhex_rs-0.1.1-cp38-cp38-macosx_11_0_arm64.whl
- Upload date:
- Size: 337.2 kB
- Tags: CPython 3.8, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
754f6213f09ce65bf6d1f70bc15d3a8aa8213c8b9417dbf07fdb061c07f6e0f4
|
|
| MD5 |
e267a9b23887a64382c5c45f7434c981
|
|
| BLAKE2b-256 |
a48819b16555c679e09a7ed3f42e383be2cbc602bcd86986c8043b49bb85cdcf
|