Skip to main content

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

  1. Conflicting with Native Python Package

    hpyhex-rs conflicts with the existing hpyhex package on PyPI. If you have hpyhex installed, please uninstall it first using:

    pip uninstall hpyhex
    
  2. Difference in Importing Modules

    In hpyhex-rs, all main classes and functions are located directly under the hpyhex module. For example, to import the Hex class, use:

    from hpyhex import Hex, Game
    

    In contrast, the original hpyhex package requires importing from submodules (hex and game), 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-rs first, and falls back to the original hpyhex package if that fails, allowing your code to work with either package seamlessly.

  3. Not Interoperable with Original Package

    Due to differences in the Rust implementation, hpyhex-rs objects cannot be mixed with the original hpyhex package objects. The Hex of hpyhex-rs is not compatible and cannot be converted to/from the Hex of hpyhex, for example.

    This matters primarily in serialization scenarios, but not in regular usage, as you would typically use either hpyhex or hpyhex-rs exclusively in a project.

    If you are using built-in APIs in hpyhex to serialize data structures (e.g., int(piece_value), Piece(integer_value)), you can load them back using hpyhex-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 hpyhex as Python objects (e.g., pickle), you cannot load them back using hpyhex-rs, and vice versa. hpyhex-rs offers serialize and deserialize functions for its own data structures.

  4. Does Not Contain benchmark Module (Yet)

    The original hpyhex package contains a benchmark module for performance testing of machine learned, heuristic, determinstic, and random algorithms. This module is not yet implemented in hpyhex-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.

  5. 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

  1. Install the package:
    pip install hpyhex
    
  2. Import and use the main classes as shown above.
  3. 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 PieceFactory to 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

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

hpyhex_rs-0.1.1-cp312-cp312-manylinux_2_34_aarch64.whl (368.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ ARM64

hpyhex_rs-0.1.1-cp312-cp312-macosx_11_0_arm64.whl (338.8 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

hpyhex_rs-0.1.1-cp311-cp311-manylinux_2_34_aarch64.whl (365.1 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.34+ ARM64

hpyhex_rs-0.1.1-cp311-cp311-macosx_11_0_arm64.whl (335.5 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

hpyhex_rs-0.1.1-cp310-cp310-manylinux_2_34_aarch64.whl (365.0 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.34+ ARM64

hpyhex_rs-0.1.1-cp310-cp310-macosx_11_0_arm64.whl (335.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

hpyhex_rs-0.1.1-cp39-cp39-manylinux_2_34_aarch64.whl (366.0 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.34+ ARM64

hpyhex_rs-0.1.1-cp39-cp39-macosx_11_0_arm64.whl (336.6 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

hpyhex_rs-0.1.1-cp38-cp38-manylinux_2_34_aarch64.whl (366.5 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.34+ ARM64

hpyhex_rs-0.1.1-cp38-cp38-macosx_11_0_arm64.whl (337.2 kB view details)

Uploaded CPython 3.8macOS 11.0+ ARM64

File details

Details for the file hpyhex_rs-0.1.1-cp312-cp312-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp312-cp312-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 9b5f09b30e6bcce7b9b406c767f92324ee7b4bb3df7dc3ad39dd80921f75a822
MD5 f058f25d90de4ff63e5ff9b4faf7ee2f
BLAKE2b-256 59ef2842e1c9ae24c4fc0d0772723b5ded700df81daac7fd8c80b8ef344da251

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 61afd49da84e43bbbc83dc47e347d522a681c728ca942de96bce1796649d0046
MD5 4c869a28f5a5c39ea3ba82cb39e3c4d1
BLAKE2b-256 aafa0c0b1b71cc954dd73761c596a1b6f99c88d0637af10818897a40b6d7eff0

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp311-cp311-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp311-cp311-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 2a741c2e2a0c6d0ccab435fadc6fcdfcdd11f8ea61e0efafb5e8f167a478c2a5
MD5 c9a202eda78fd81b20eecaf30f97aa68
BLAKE2b-256 c83da7c688dde6d1237cf1e842bd7ab6a323b732c49a766c4706d619e3039333

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dadccb950c872ddd856b0d75e6ea7066d72b44b1d163aaf25f5f7e00b65addb9
MD5 7cd8ed34f5dcbfeba37a43179819e541
BLAKE2b-256 9474e5a5c83420c9b4eb05bc9b4499f5e73b2e4a0097f801f8ad6c4e213a6b93

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp310-cp310-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp310-cp310-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 58dbdecdbb13efcbb726222907a5500671b074243e6a7024e62cb67c58d70e40
MD5 b7d7198ea2a04c3583be71ba3a2e21fe
BLAKE2b-256 789577627b2ba536aed95be4b27722964c6abc468f839c66c4445b9eadfe29fa

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7e98aaa8a0cbab52ffe98febd14e7f136930d6dce966f16e5652def06ce2e573
MD5 d01e27efc3d6e566c6415bfb62cd7869
BLAKE2b-256 a706e754d8132bc3a56adca09b3aa2fcdc6fa4a05575e67d97861c3dd20bee07

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp39-cp39-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp39-cp39-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 fee7977ec1fbc3656ecfe36a6b5f970bda2bdc291d1d3f93cfa16a29595af00e
MD5 cab4321b693e63056cade547280f2682
BLAKE2b-256 f465ff2b24fe5989a0d6215cb8fc4a424e91b9ce0d5e0cbb18bf311ea46c1fec

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 456181ae7784c2229b4d29d7fd5beca2060b7e727e5bfe2c52b3e827f582add4
MD5 ebdf849756563d7fc63fcc6f6ffd7aa6
BLAKE2b-256 d1f26ac316ed2f162a006febe45d4b4a3ee252310c459a29200512b8ce78ee7e

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp38-cp38-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp38-cp38-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 ba7e000c0a28272e4801c47bc567907322ef6528bbc8a9f2da3c4070929e8d52
MD5 4ffcf7e78da6944f6938810eec362ac3
BLAKE2b-256 d66a5c699fce3f87993e29ab33d061dc98fe94affe6fc5ee608033d843de0821

See more details on using hashes here.

File details

Details for the file hpyhex_rs-0.1.1-cp38-cp38-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for hpyhex_rs-0.1.1-cp38-cp38-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 754f6213f09ce65bf6d1f70bc15d3a8aa8213c8b9417dbf07fdb061c07f6e0f4
MD5 e267a9b23887a64382c5c45f7434c981
BLAKE2b-256 a48819b16555c679e09a7ed3f42e383be2cbc602bcd86986c8043b49bb85cdcf

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page