Skip to main content

A fast Connect-4 Solver for Python & C++

Project description

BitBully: A fast and perfect-playing Connect-4 Agent for Python 3 & C/C++

bitbully-logo-full


GitHub Repo stars GitHub forks Python Python Python Docs pre-commit PyPI - Version PyPI - Downloads PyPI - License Coverage Status Wheels Doxygen CMake Build Buy Me a Coffee

BitBully is a high-performance Connect-4 solver built using C++ and Python bindings, leveraging advanced algorithms and optimized bitwise operations. It provides tools for solving and analyzing Connect-4 games efficiently, designed for both developers and researchers.

BitBully evaluates millions of nodes per second in pure C++ and supports constant-time opening book lookups for early-game positions.

Connect4 opening Connect4 mid-game Connect4 victory

From opening to victory: three key stages of a Connect 4 match — early game, mid-game tension, and the final winning position.

Quickstart

import bitbully as bb

agent = bb.BitBully()
board = bb.Board()

while not board.is_game_over():
    board.play(agent.best_move(board))

print(board)
print("Winner:", board.winner())

Table of Contents


Features

  • Fast Solver: Implements MTD(f) and null-window search algorithms for Connect-4.
  • Bitboard Representation: Efficiently manages board states using bitwise operations.
  • Advanced Features: Includes transposition tables, threat detection, and move prioritization.
  • Python Bindings: Exposes core functionality through the bitbully_core Python module using pybind11.
  • Cross-Platform: Build and run on Linux, Windows, and macOS.
  • Open-Source: Fully accessible codebase for learning and contribution.

Who is this for?

  • Just want to play or analyze Connect-4 in Python? → Read Quickstart + Usage (High-level Python API)

  • Interested in performance, algorithms, or C++ integration? → See Low-level C++ bindings (advanced)

  • Working on research, solvers, or databases? → See Opening Books and BoardCore

Installation

Prerequisites

  • Python: Version 3.10 or higher, PyPy 3.10 or higher

Build and Install

From PyPI (Recommended)

The easiest way to install the BitBully package is via PyPI:

pip install bitbully

This will automatically download and install the pre-built package, including the Python bindings.


Python API Docs

Please refer to the docs here: https://markusthill.github.io/BitBully/.

The docs for the opening databases can be found here: https://markusthill.github.io/bitbully-databases/


Usage

⚠️ Note bitbully_core exposes low-level C++ bindings intended for advanced users. Most users should use the high-level bitbully Python API with the classes Board and BitBully.

BitBully currently supports standard Connect-4 (7 columns × 6 rows). Generalized board sizes are not supported.

Start with a simple Widget on Colab

Open In Colab

High-level Python API (recommended)

Empty board + play moves incrementally

import bitbully as bb

board = bb.Board()
assert board.play(3)          # single move (int)
assert board.play([2, 4, 3])  # multiple moves (list)
assert board.play("001122")   # multiple moves (string)

print(board)

Initialize directly from a move sequence

import bitbully as bb

board_a = bb.Board([3, 3, 3, 1, 1])
board_b = bb.Board("33311")

assert board_a == board_b
print(board_a)

Create positions (moves, strings, arrays) and round-trip them

import bitbully as bb

# From a move list
b1 = bb.Board([3, 3, 3, 1, 1])

# From a compact move string
b2 = bb.Board("33311")

assert b1 == b2
print(b1)

# From a 2D array (row-major 6x7 or column-major 7x6 both work)
arr = b1.to_array()  # default: column-major 7x6
b3 = bb.Board(arr)

assert b1 == b3

Legal moves and remaining moves

import bitbully as bb

board = bb.Board("33333111")

print(board.legal_moves())                 # all legal columns
print(board.legal_moves(order_moves=True)) # ordered (center-first)
print("Moves left:", board.moves_left())
print("Tokens:", board.count_tokens())

Some board utilities

import bitbully as bb

board = bb.Board("332311")
print(board)

print("Can win next (any):", board.can_win_next())
print("Can win next in col 4:", board.can_win_next(4))

assert board.play(4)  # play winning move
print(board)

print("Has win:", board.has_win())
print("Game over:", board.is_game_over())
print("Winner:", board.winner())  # 1

Solver Quickstart: evaluate a position and pick a move

import bitbully as bb

agent = bb.BitBully()          # loads default opening book ("12-ply-dist")
board = bb.Board()             # empty board

print(board)

scores = agent.score_all_moves(board)
print("Move scores:", scores)

best_col = agent.best_move(board)
print("Best move:", best_col)

Play a small game loop (agent vs. itself)

import bitbully as bb

agent = bb.BitBully()
board = bb.Board()

while not board.is_game_over():
    col = agent.best_move(board, tie_break="random")
    assert board.play(col)

print(board)
print("Winner:", board.winner())  # 1, 2, or None for draw

Tie-breaking strategies for best_move

import bitbully as bb
import random

agent = bb.BitBully()
board = bb.Board("341")  # arbitrary position

print(board)

print("Center tie-break:", agent.best_move(board, tie_break="center"))
print("Leftmost tie-break:", agent.best_move(board, tie_break="leftmost"))

rng = random.Random(42) # optional own random generator
print("Random tie-break (seeded):", agent.best_move(board, tie_break="random", rng=rng))

Different Search Algorithms

import bitbully as bb

agent = bb.BitBully()
board, _ = bb.Board.random_board(n_ply=14, forbid_direct_win=True)

s1 = agent.mtdf(board)
s2 = agent.negamax(board)
s3 = agent.null_window(board)

assert s1 == s2 == s3
print("Score:", s1)

Low-level C++ bindings (advanced)

Use the BitBullyCore and BoardCore classes directly in Python:

BoardCore Examples

The low-level BoardCore API gives you full control over Connect-4 positions: you can play moves, generate random boards, mirror positions, and query win conditions or hashes.

Create and Print a Board
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()
print(board)          # Human-readable 7x6 board
print(board.movesLeft())   # 42 on an empty board
print(board.countTokens()) # 0 on an empty board

Play Moves and Check for Winning Positions
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()

# Play a small sequence of moves (columns 0–6)
for col in [3, 2, 3, 2, 3, 4, 3]:
    assert board.play(col)

print(board)

# Check if the side to move has an immediate winning move
print(board.canWin())      # False
print(board.hasWin())      # True, since the last move created 4-in-a-row

You can also check if a specific column is a winning move:

board = bbc.BoardCore()
board.setBoard([3, 3, 3, 3, 2, 2, 4, 4])

print(board.canWin())  # True
print(board.canWin(1))  # True  – playing in column 1 wins
print(board.canWin(3))  # False – no win in column 3

Set a Board from a Move List or Array
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()

# From a move sequence (recommended)
assert board.setBoard([0, 1, 2, 3, 3, 2, 1, 0])

# Convert to 7x6 array (columns × rows)
array = board.toArray()
print(len(array), len(array[0]))  # 7 x 6

# From a 7x6 array of tokens (1 = Yellow, 2 = Red)
array_board = [[0 for _ in range(6)] for _ in range(7)]
array_board[3][0] = 1  # Yellow in center column bottom row
b2 = bbc.BoardCore()
assert b2.setBoard(array_board)

Generate Random Boards
import bitbully.bitbully_core as bbc

board, moves = bbc.BoardCore.randomBoard(10, True)

print(board)   # Random, valid board
print(moves)   # List of 10 column indices
print(board.canWin())  # Usually False for random boards in this setup

Mirroring Boards and Symmetry
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()
board.setBoard([0, 1, 2])      # Left side

mirrored = board.mirror()      # Mirror around center column
print(board)
print(mirrored)

# Double-mirroring returns the original position
assert board == mirrored.mirror()

Hashing, Equality, and Copies
import bitbully.bitbully_core as bbc

b1 = bbc.BoardCore()
b2 = bbc.BoardCore()

moves = [0, 1, 2, 3]
for m in moves:
    b1.play(m)
    b2.play(m)

assert b1 == b2
assert b1.hash() == b2.hash()
assert b1.uid() == b2.uid()

# Copying a board
b3 = b1.copy()           # or bbc.BoardCore(b1)
assert b3 == b1

b3.play(4)               # Modify the copy
assert b3 != b1
assert b3.hash() != b1.hash()

These examples are based on the internal test suite and show typical ways of interacting with BoardCore programmatically.

BitBullyCore: Connect-4 Solver Examples

The BitBullyCore module provides a high-performance Connect-4 solver written in C++ and exposed to Python. You can evaluate positions, score all legal moves, or run the full MTD(f) search.


Solve a Position with MTD(f)
import bitbully.bitbully_core as bbc

# Construct a position: alternate moves into the center column
board = bbc.BoardCore()
for _ in range(6):
    board.play(3)  # Column 3

solver = bbc.BitBullyCore()
score = solver.mtdf(board, first_guess=0)

print("Best score:", score)

mtdf returns an integer score from the perspective of the side to move (positive = winning, negative = losing).


Score All Moves in a Position

scoreMoves(board) returns a list of 7 integers: the evaluated score for playing in each column (0–6). Illegal moves (full columns) are still included in the list.

import bitbully.bitbully_core as bbc

board = bbc.BoardCore()
board.setBoard([3, 4, 1, 1, 0, 2, 2, 2])

solver = bbc.BitBullyCore()
scores = solver.scoreMoves(board)

print("Move scores:", scores)
# Example output:
# [-3, -3, 1, -4, 3, -2, -2]

Using the Solver in a Loop (Move Selection)
import bitbully.bitbully_core as bbc
import time

board = bbc.BoardCore()
solver = bbc.BitBullyCore()

for move in [3, 4, 1, 1, 0, 2, 2, 2]:  # Example opening
    board.play(move)

start = time.perf_counter()
scores = solver.scoreMoves(board)
best_move = max(range(7), key=lambda c: scores[c])
print(f"Time: {round(time.perf_counter() - start, 2)} seconds!")
print("Scores:", scores)
print("Best move suggestion:", best_move)
# best move is into column 4

Further Examples using the BitBully Solver

You can initialize a board using an array with shape (7, 6) (columns first) and solve it:

from bitbully import bitbully_core

# Define a Connect-4 board as an array (7 columns x 6 rows)
# You may also define the board using a numpy array if numpy is installed
# 0 = Empty, 1 = Yellow, 2 = Red
# Here, the left column represents the bottom row of the board
board_array = [
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [1, 2, 1, 2, 1, 0],
    [0, 0, 0, 0, 0, 0],
    [2, 1, 2, 0, 0, 0],
    [0, 0, 0, 0, 0, 0]
]

# Convert the array to the BoardCore board
board = bitbully_core.BoardCore()
assert board.setBoard(board_array), "Invalid board!"

print(board)

# Solve the position
solver = bitbully_core.BitBullyCore()
score = solver.mtdf(board, first_guess=0)
print(f"Best score for the current board: {score}") # expected score: 1

Run the Bitbully solver with an opening book (here: 12-ply opening book with winning distances):

from bitbully import bitbully_core as bbc
import bitbully_databases as bbd
import importlib.resources

db_path = bbd.BitBullyDatabases.get_database_path("12-ply-dist")
bitbully = bbc.BitBullyCore(db_path)
b = bbc.BoardCore()  # Empty board
bitbully.scoreMoves(b)  # expected result: [-2, -1, 0, 1, 0, -1, -2]

Further Usage Examples for BitBully Core

Create all Positions with (up to) n tokens starting from Board b:

from bitbully import bitbully_core as bbc

b = bbc.BoardCore()  # empty board
board_list_3ply = b.allPositions(3, True)  # All positions with exactly 3 tokens
len(board_list_3ply)  # should be 238 according to https://oeis.org/A212693

Opening Book Examples

BitBully Databases provide fast lookup tables (opening books) for Connect-4, allowing you to query evaluated positions, check if a board is known, and retrieve win/loss/distance values.

Load an Opening Book
import bitbully_databases as bbd
import bitbully.bitbully_core as bbc

# Load the 8-ply opening book (no distances)
db_path = bbd.BitBullyDatabases.get_database_path("8-ply")
book = bbc.OpeningBookCore(db_path, is_8ply=True, with_distances=False)

print(book.getBookSize())  # e.g., 34515
print(book.getNPly())      # -> 8

Accessing Entries

Each entry consists of (key, value) where:

  • key is the Huffman-encoded board state
  • value is the evaluation (win/loss/draw or distance)
k, v = book.getEntry(0)
print(k, v)

Evaluating a Board Position
import bitbully.bitbully_core as bbc

board = bbc.BoardCore()
board.setBoard([2, 3, 3, 3, 3, 3, 5, 5])  # Sequence of column moves

value = book.getBoardValue(board)
print("Evaluation:", value)

Check Whether a Position Is in the Opening Book

The books only contain one variant for mirror-symmetric positions:

board = bbc.BoardCore()
board.setBoard([1, 3, 4, 3, 4, 4, 3, 3])

print(book.isInBook(board))              # e.g., False
print(book.isInBook(board.mirror()))     # e.g., True, checks symmetric position

Advanced Build and Install

Prerequisites

  • Python: Version 3.10 or higher
  • CMake: Version 3.15 or higher
  • C++ Compiler: A compiler supporting C++-17 (e.g., GCC, Clang, MSVC)
  • Python Development Headers: Required for building the Python bindings

From Source

  1. Clone the repository:

    git clone https://github.com/MarkusThill/BitBully.git
    cd BitBully
    git submodule update --init --recursive # – Initialize and update submodules.
    
  2. Build and install the Python package:

    pip install .
    

Building Static Library with CMake

  1. Create a build directory and configure the project:

    mkdir build && cd build
    cmake .. -DCMAKE_BUILD_TYPE=Release
    
  2. Build the a static library:

    cmake --build . --target cppBitBully
    

Contributing & Development

Whether you're fixing a bug, optimizing performance, or extending BitBully with new features, contributions are highly appreciated. The full development guide provides everything you need to work on the project efficiently:

📘 Complete Development Documentation https://markusthill.github.io/BitBully/develop/

It covers all essential workflows, including:

  • Repository setup: cloning, submodules, virtual environments
  • Development environment: installing dev dependencies, using editable mode
  • Code quality tools: ruff, mypy/pyrefly, clang-format, pre-commit, commitizen
  • Building the project: local wheels, CMake, cibuildwheel, sdist
  • Testing: running pytest, filtering tests, coverage, CI integration
  • Release workflow: semantic versioning, version bumping, tagging, PyPI/TestPyPI publishing
  • Debugging & tooling: GDB, Doxygen, mkdocs, stub generation for pybind11
  • Platform notes: Debian/Linux setup, gcov matching, MSVC quirks
  • Cheatsheets: Git, submodules, CMake, Docker, Ruby/Jekyll, npm, environment management

If you're contributing code, please:

  1. Follow the coding standards and formatting tools (ruff, mypy, clang-format).
  2. Install and run pre-commit hooks before committing.
  3. Write or update tests for all behavioral changes.
  4. Use Commitizen for semantic commit messages and versioning.
  5. Open an issue or discussion for major changes.

Pull requests are welcome — thank you for helping improve BitBully! 🚀


License

This project is licensed under the AGPL-3.0 license.


Contact

If you have any questions or feedback, feel free to reach out:


Acknowledgments

Many of the concepts and techniques used in this project are inspired by the outstanding Connect-4 solvers developed by Pascal Pons and John Tromp. Their work has been invaluable in shaping this effort:


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bitbully-0.0.71.tar.gz (8.1 MB view details)

Uploaded Source

Built Distributions

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

bitbully-0.0.71-pp311-pypy311_pp73-win_amd64.whl (468.7 kB view details)

Uploaded PyPyWindows x86-64

bitbully-0.0.71-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (345.1 kB view details)

Uploaded PyPymanylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.71-pp311-pypy311_pp73-macosx_11_0_arm64.whl (241.1 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

bitbully-0.0.71-pp310-pypy310_pp73-win_amd64.whl (467.3 kB view details)

Uploaded PyPyWindows x86-64

bitbully-0.0.71-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (343.6 kB view details)

Uploaded PyPymanylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.71-pp310-pypy310_pp73-macosx_11_0_arm64.whl (239.9 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

bitbully-0.0.71-cp314-cp314-win_amd64.whl (480.0 kB view details)

Uploaded CPython 3.14Windows x86-64

bitbully-0.0.71-cp314-cp314-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ x86-64

bitbully-0.0.71-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (347.6 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.71-cp314-cp314-macosx_11_0_arm64.whl (242.0 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

bitbully-0.0.71-cp313-cp313-win_amd64.whl (470.2 kB view details)

Uploaded CPython 3.13Windows x86-64

bitbully-0.0.71-cp313-cp313-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

bitbully-0.0.71-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (347.3 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.71-cp313-cp313-macosx_11_0_arm64.whl (241.6 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

bitbully-0.0.71-cp312-cp312-win_amd64.whl (470.2 kB view details)

Uploaded CPython 3.12Windows x86-64

bitbully-0.0.71-cp312-cp312-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

bitbully-0.0.71-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (347.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.71-cp312-cp312-macosx_11_0_arm64.whl (241.5 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

bitbully-0.0.71-cp311-cp311-win_amd64.whl (469.3 kB view details)

Uploaded CPython 3.11Windows x86-64

bitbully-0.0.71-cp311-cp311-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

bitbully-0.0.71-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (345.2 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.71-cp311-cp311-macosx_11_0_arm64.whl (240.9 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

bitbully-0.0.71-cp310-cp310-win_amd64.whl (468.1 kB view details)

Uploaded CPython 3.10Windows x86-64

bitbully-0.0.71-cp310-cp310-musllinux_1_2_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ x86-64

bitbully-0.0.71-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (343.7 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bitbully-0.0.71-cp310-cp310-macosx_11_0_arm64.whl (239.7 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file bitbully-0.0.71.tar.gz.

File metadata

  • Download URL: bitbully-0.0.71.tar.gz
  • Upload date:
  • Size: 8.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.71.tar.gz
Algorithm Hash digest
SHA256 f67544cb50cd5e420efccbd167664adafda867012bdce905d18d6143598e8b16
MD5 e0fd70defa23ae64eca0a2dbbf79b931
BLAKE2b-256 0ad70bb69c2ecd79a467692ca7774d7eda00b77b2b050e66b0f9c9fceedab13a

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71.tar.gz:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-pp311-pypy311_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-pp311-pypy311_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 f32ddd88366b97801895744f973f369710d5e8effc8003cc9462d03f30805732
MD5 87639f885fd69f2e14975a633c52302c
BLAKE2b-256 2f37121afd050ef05cc0c195b5ac4c152cc1f75a2e0ef823dc10bf3b7ed75ca1

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-pp311-pypy311_pp73-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d8e4976461f1bcc51cf05f7308dd16a0abb5d0555d386be6eb321171d28915de
MD5 01fc10f525f6668ff9e2f309e95c35eb
BLAKE2b-256 659b827d45918109b2ad7ce92b0a0410cb634871f7ba35cf80f676f4dd97bdaf

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-pp311-pypy311_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-pp311-pypy311_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e1c8f12d370120ba368b24b108a250fb7e1e026f7c285154948c6656a27fafed
MD5 7c7d5049a2d33f0fcb22fbbb3ab55461
BLAKE2b-256 8b925df5994826e877168eb98c86e5e8de3589a73486ef13c37323da53a412f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-pp311-pypy311_pp73-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-pp310-pypy310_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-pp310-pypy310_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 66b9487ab4ebd694d9fe610be3c3c41fb16214ae166303345f33077c197e254b
MD5 d21b078790ba213d05c4e460eb1e861d
BLAKE2b-256 66be4bce02537bfdfe4194d2522a8237af692638c56adfba4f0c1a340a77c1ff

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-pp310-pypy310_pp73-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 090ea5157fde19bc42447d5c4647d7564f10286580b0bc91e47cb63822fb6658
MD5 919b0171c18f4c5bdbd55ec5ed15b672
BLAKE2b-256 9a44ce171f25f0c702e562fc68a1b57f6d022cb91607a666c10987133844d300

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-pp310-pypy310_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-pp310-pypy310_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 22553e85c04264b6738cfcdd9cc3f186be8af6a64fbd1b839f3fee700596414a
MD5 22948073103a7d5300ae85ca5eaf5cd7
BLAKE2b-256 380df0f2b73c4a90e9a38e6091d33f0b8300449d37ece03e192c1657707905ff

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-pp310-pypy310_pp73-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.71-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 480.0 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.71-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 7f9d74cdaabf9596af012aa3ef16b05e85d424e11649bac46074dd17f67a74ca
MD5 245920e961cdc34a9bb885cf7815c8b8
BLAKE2b-256 301383ddf8fc92239f361b565279b94b831ca8d5b5be16941c36338362fa0d95

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp314-cp314-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp314-cp314-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d603b06cfbd06045eb3fa29d1408e9c9a1b8419a25a8a50d08b46e5f8b7a0138
MD5 e4cd4374e2cd58828b2fda9a027d0772
BLAKE2b-256 d45563afa6bc530cc5b1617bf10d3b352adcd5df6693ead02e847cb2848c07f9

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp314-cp314-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e982a1c3d6997a3034ba2546ec3629f763c4a4c72d8dfd9b0f4f654691587d3a
MD5 ac9c2c0015a15baf365efd5f247ee729
BLAKE2b-256 6d530915046a5ee3d20f75c76f3e8b38b9a903b106aaec9b4d64ff3abf19d199

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f82b2015297634bcc958b1fdf229743116fdedb78b5558a6d3cd6ef2e3b10d08
MD5 7dc32f7cb63bc399749d3f7ef9a1bf2f
BLAKE2b-256 83a37a70f890344ee2fc945cfffb30d808202636f111edb6bdebc22e713cd153

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.71-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 470.2 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.71-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 e9cc7c7a177db8fd3e50976cbbfad527f0337ac08cd75f5b82909426b5cd2886
MD5 7ce7ad1291222763b56433f11ac058ea
BLAKE2b-256 07287984c907c0792e318d8f95a29d5943d7b2685726f383e7a07d3fb116a15b

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp313-cp313-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1917af55945afe028878abc2b6b8a8e136082091f0fecc07f8ade1e730dfa996
MD5 7e21be90b921298b89f1aa8f6b9fb026
BLAKE2b-256 4cd1c9f0d3a0e8c1e42c283227b6bc0fa3fa0f79f616211a66043beb1e7573ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp313-cp313-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 48ab57301cd91f937fc7c2313d994980d4acf4a77f68c4bd72e1bd3d0ad39a8a
MD5 e25831a88b66099d2756fef55c1fe67e
BLAKE2b-256 cbd0ef2351484580b3a5cce7ab4968bff59068214e407965fa76f8f46b099627

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5b7b6f035276c2d07858980da4051883cf48cf08118baaa590fc54642b258eb7
MD5 dc44011be54346acc281c4ec7a0ac61d
BLAKE2b-256 7fd1facd78d521124031e79fffc396019324c532cdddb0968462f00cd19e9c68

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.71-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 470.2 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.71-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 4ed88d2222e698801d3148270f09ff00cf88f81e5edbaca115e9a941fea0a7ae
MD5 93c6519f38f276bc9ca3098d1afe24e3
BLAKE2b-256 2fc43dcdef7db2c8995f6b226f81f1432121d0d75dff444ed085a565f2e7b945

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp312-cp312-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 ca1489ed4c3e59f70c740e95a43b01f51b41c0b807817fef26bf431a88347193
MD5 7ae91471be33eeb67e81f4bb3db360e5
BLAKE2b-256 b0fccf8219ee885b1579b3fe52f2e4cfcf4b59ad7b01d044a959c8f4960e7f9a

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp312-cp312-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0a42f65f2553a00a7a2a3fa75cece31f3856a36cf1712efe33ecbf6328fd0a47
MD5 df3eb5be861ae50b88be1741463e4b08
BLAKE2b-256 c02e1fa5d8cbd6af876d52e74246505284120ea11f5adc864b298e42a6508c83

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 be6da1a8319c15d0d0f23b1853f42ce8acfe9e1996619f382b32d510de91a95f
MD5 4d1852f52b42115c09ec0fe17a4a0e9c
BLAKE2b-256 a3218b68d6933339e5ceb3ffb6bde6f209f117bc168372c30a0d59aff5efb348

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.71-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 469.3 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.71-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 a01da19637b6b310cc48943e75e155a639778a152a9a805b27715fe2b1870abe
MD5 78e00585c983259586d32e1f82d289ba
BLAKE2b-256 b4ae4cd5767aa5eac1e8d673e259562947ea86812d13b45a1472527b64919eb2

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp311-cp311-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 ecb402e779d6c67bb78d3ea18429cd4ed9745ee30ae1c8e0d5a8840e63d69ba8
MD5 0426929d91661ff85edeccaccf79dfa6
BLAKE2b-256 542707253c2537ca7001bf3b917045f4d9ebee00134c64aab9a5382fcc7fedb4

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp311-cp311-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a8cf83299538573a95d25cc6680f6ae261c0f7b0a887bf7227d055325789cc29
MD5 1e3dcbb8428a526899aafb86ee2bdfd5
BLAKE2b-256 09a64ed758b42e694834cc7212b2dfda131f751d9ddb030415d055118981bda2

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9ae4ea9b530bc224a615093dec0d37ba82daf256d5648bf3de2aa929168e2242
MD5 164f69446f6218b900f7d8a900100ad8
BLAKE2b-256 0dde313c4ad4752d0edaa0146693a9e76ae3043018c649eb78deef913c08b6e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.71-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 468.1 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for bitbully-0.0.71-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 b7df431018d481a7628d87b091f3b5478293627581d964eb6155851c94c1b684
MD5 1fc088a20e5275f84ae705b0de97eef7
BLAKE2b-256 29febe37663b2e3ea28e6218e39d5b899b9611ae295b739d29b605a033cab4e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp310-cp310-win_amd64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 16b3cdb9fa333593bebe0583e92db59bf4bca2d7f53f3016f87e5c9c166d1629
MD5 fc8bee0b080505641effc62a9838572c
BLAKE2b-256 9c6a95afbcd916a0401a6eb6719e999d63dbe7740fc38f2a418f79eebdbc8e7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp310-cp310-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 601678121545e8a8009f8a0c56fa88f820ef9401b641209b2f4615dd8028af62
MD5 5a86c1698adc0876e00b97c677dcc241
BLAKE2b-256 7aa7520434ac4a69b265c87c51c9b37074fbf57c9dd478067673c519d7607cff

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bitbully-0.0.71-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.71-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e486e5240ab70356bd4740edde365f2d020f41f05926ede00112c45bb803dc51
MD5 167a2feaba5a3b084f7496c32c20403e
BLAKE2b-256 2aeb14c8a4ddb608000ad73823b8c48947071e2a69c861b139fb20878a6f91fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.71-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: wheels.yml on MarkusThill/BitBully

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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