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.

🚀 BitBully: Getting Started with a Jupyter Notebook

This notebook introduces the main building blocks of BitBully:

  • Board: represent and manipulate Connect Four positions
  • BitBully: analyze positions and choose strong moves

All examples are designed to be copy-pasteable and easy to adapt for your own experiments.

Jupyter Notebook: notebooks/getting_started.ipynb

Open In Colab

🎮 Play a Game of Connect-4 with a simple Jupyter Notebook Widget

TODO: Screenshot here!

BitBully includes an interactive Connect-4 widget for Jupyter built with ipywidgets + Matplotlib. GuiC4 renders a 6x7 board using image sprites, supports click-to-play or column buttons, provides undo/redo, can trigger a computer move using the BitBully engine (optionally with an opening book database), and shows win/draw popups. It's intended for quick experimentation and demos inside notebooks (best with %matplotlib ipympl).

Jupyter Notebook: notebooks/game_widget.ipynb

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:


Further Ressources

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.73.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.73-pp311-pypy311_pp73-win_amd64.whl (480.4 kB view details)

Uploaded PyPyWindows x86-64

bitbully-0.0.73-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (356.7 kB view details)

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

bitbully-0.0.73-pp311-pypy311_pp73-macosx_11_0_arm64.whl (252.7 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

bitbully-0.0.73-pp310-pypy310_pp73-win_amd64.whl (478.9 kB view details)

Uploaded PyPyWindows x86-64

bitbully-0.0.73-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (355.3 kB view details)

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

bitbully-0.0.73-pp310-pypy310_pp73-macosx_11_0_arm64.whl (251.5 kB view details)

Uploaded PyPymacOS 11.0+ ARM64

bitbully-0.0.73-cp314-cp314-win_amd64.whl (491.6 kB view details)

Uploaded CPython 3.14Windows x86-64

bitbully-0.0.73-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.73-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (359.2 kB view details)

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

bitbully-0.0.73-cp314-cp314-macosx_11_0_arm64.whl (253.7 kB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

bitbully-0.0.73-cp313-cp313-win_amd64.whl (481.9 kB view details)

Uploaded CPython 3.13Windows x86-64

bitbully-0.0.73-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.73-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (359.0 kB view details)

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

bitbully-0.0.73-cp313-cp313-macosx_11_0_arm64.whl (253.2 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

bitbully-0.0.73-cp312-cp312-win_amd64.whl (481.8 kB view details)

Uploaded CPython 3.12Windows x86-64

bitbully-0.0.73-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.73-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (359.3 kB view details)

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

bitbully-0.0.73-cp312-cp312-macosx_11_0_arm64.whl (253.1 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

bitbully-0.0.73-cp311-cp311-win_amd64.whl (481.0 kB view details)

Uploaded CPython 3.11Windows x86-64

bitbully-0.0.73-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.73-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (356.8 kB view details)

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

bitbully-0.0.73-cp311-cp311-macosx_11_0_arm64.whl (252.5 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

bitbully-0.0.73-cp310-cp310-win_amd64.whl (479.8 kB view details)

Uploaded CPython 3.10Windows x86-64

bitbully-0.0.73-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.73-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (355.4 kB view details)

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

bitbully-0.0.73-cp310-cp310-macosx_11_0_arm64.whl (251.4 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: bitbully-0.0.73.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.73.tar.gz
Algorithm Hash digest
SHA256 1778183e99a91a0d22464ae4d585c1e9b08551a40f8c5240f0da5c7b0bd9b403
MD5 cc0ad63e93413e256ac1187320d93e98
BLAKE2b-256 cf9eab68f04d0ef03b24f009f23e2af7f967ede7aa279140e22567c3046fcdba

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73.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.73-pp311-pypy311_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-pp311-pypy311_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 f6a5a4ea58a1ac177d630ca5f3ff7d73c2739c955a47c60fc0a1647e7cac877d
MD5 cda37a78b760004b2225b164d0493671
BLAKE2b-256 2443381add068f64e2fbe594fb1cef9d88f72b5f4d7bc187220ce7e9572d3d6b

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9e260b1442e2541b831644563cf3a6bbca8d82b81f21c2e4130100a1b5a6a61e
MD5 cc8e377ebd629846d6bd754622137f0a
BLAKE2b-256 f8dafdcb07e61a025c932636a24ceea70883f24e4b9499c18b66eb75780cd095

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-pp311-pypy311_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-pp311-pypy311_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4f0714ac6a59a904ab9c901514759a349da01e1c62ea588759efcbd8d7a46b7f
MD5 1bc049c9d2c52ff39fbeb155a6d4361d
BLAKE2b-256 fc5b6bc7d88ad092f9f16ade73e54357c7ea8695a2260a5385d5b9a6c687fc42

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-pp310-pypy310_pp73-win_amd64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-pp310-pypy310_pp73-win_amd64.whl
Algorithm Hash digest
SHA256 64808f5dccdeba4e4b859c40c240ec8835959cf4eb4b8b34d877798b9101fa24
MD5 55e4694647106d164fbc8d846d9ea5a9
BLAKE2b-256 2a766b32ef0123f19fbf7a6f990a9d20e6f96a5b6570474c470b6ef4b8a44129

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-pp310-pypy310_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1c1155981f4d67841cb187bf51c363a238856dc2be91bbe1ffaf71ffda59a065
MD5 b257de1b56ad9168badce4284a9b7e01
BLAKE2b-256 b3a301a168933b559ffb8fa9e08ec4efa1203dffb09d3172fb8dddc0b3cbdf28

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-pp310-pypy310_pp73-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-pp310-pypy310_pp73-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1f221d99e4c500b5ec99dd5e96e7fdd61503e0e177ce90b0458c34d8ac0f539c
MD5 bf3c09ce34b315bd53d99a9c0cd6016e
BLAKE2b-256 058f732f59a177e84b882aef56ceef97e77d75e8bfcf705a1070e6dd0b966729

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.73-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 491.6 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.73-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 692429a60e50e3eedff1e5fd9959937842bcf33bf43140e8300dc2f5482c20f6
MD5 0c2967c1cc8843d7e7a9f991243f79fc
BLAKE2b-256 2e9dbdcdd72530a7afee05f1c006260468973caa5b9301ab282c1dbd341e4354

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp314-cp314-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d6610a24fa7ea3c20c74df562a3cda91b19b3f4bd032f9f7a45d652e59302d66
MD5 07977a8def9e69b87af9cb136a8318df
BLAKE2b-256 0ba5a2f6842810d79577929810f6d332789c78d783210f77a6266f9bc02ca83f

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 874987209e60823a10f1d6d21118711dbd3762d72a665418ba7a0483b78f3c2b
MD5 2f2a5013b44b9cdddc827367a72af33c
BLAKE2b-256 b89d51526dd0d826aedc6cfe6c0596aa676922d367af55109778fe1e971c3181

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 95104604737db92287344246b95b463bf33051152336ecf0a33f08e3da93cf05
MD5 f58ceca679b0b4b1b19b89eae754c082
BLAKE2b-256 5ebe09d37184011647d9682f0ceec47116b591a615e7a9cc3ef85cc8d51186b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.73-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 481.9 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.73-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 a8f82af81bab2bf64a8e959d14bdcc3beb905f6e3180c39a8c8ce9cc1f15b509
MD5 07ec0f0849195f37bb1d5cf59ebc809a
BLAKE2b-256 9d806299f819a832cc2999e683487db448937d66d45230f4f6c991da9a5bc875

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 227d07277aebba5781ecf38372f46d1e2f8f16f1e15939c1c435cb9628d1fafc
MD5 9312bf65e0e7f74f05733238f00347ae
BLAKE2b-256 4ca02a42fb2a365b7048964c237ad24f70a1c1c4c8a84c820832c3aa1952cda7

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 da236213442ab6323bfbe656eb8a0af58438929781fa76d99e3ff0eb34ec6d11
MD5 ce8e53e9423b512e640cd1edc9dd19fc
BLAKE2b-256 4d34f06b200642c8b5760b83f8331d9ab87dac5e8de0057f815fbcc82fda9b74

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 857056541f6c4a4d0d6050b8dbbbf123a17da41f9265df0b25adbb76710849eb
MD5 e71495d11b25edc8e531f94b8fbd11c0
BLAKE2b-256 af5ab416a3323a92f811eb3c242dee24bc1146eacab1409cd004c0cb386a1a05

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.73-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 481.8 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.73-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 107c42cfb90d974bd8a27de3cbe5d4373769daeead20f01ec00aff45c4cba8f6
MD5 609cbfafae375692d075f6d107866a36
BLAKE2b-256 c1e95f4db1b107891e753b2607181d348ad4e5547d6592902eb964af3a96acd7

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7e346534ba977b03df15e87d1a524bf8447ba9ee16ffeef1bcbb85ecd8b7c2fd
MD5 f111a502b840eaba391f0ec29ab37238
BLAKE2b-256 462895815ec724177d6bcdeb7467bd7593f1ef27bdd75763d52f38f1363be295

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7e33251848724d47c9c91ec86f5c44c5e10c03b819ace89fdbb75db9b5a1e6c3
MD5 73a236116a6eff4bb036dc0251a0872f
BLAKE2b-256 ec8555a3d339ece643a5351629718faa4d660861a94a5903adf6eb8a10cd076c

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 13fa42fce06bc137070087bad54a5d66bf50caa473117dc1c92d60acb231648f
MD5 85d3c6ed28c020cb6f47aa793f3f4b90
BLAKE2b-256 f88bd48a3feadbdca36156726c6e1fe1e7d1570dd5afdcdc680d5f2f4625641e

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.73-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 481.0 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.73-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 b4e1bf3eb48b25998476072ee0dc165ed4550ea64ab28db7cd7be300c4295ab4
MD5 3075642c2cff61dd601c7a72bebda2c7
BLAKE2b-256 f3afbffbd147f5adae12c32387f575b869fc05a2a1a2e45213cb980aea51fed3

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 cb0e993a8e406577547e4363cbb1ee739f966aeba6e5326f55f3028d6361e4fa
MD5 00f2f64a0ff72625d8e559dc0a03833a
BLAKE2b-256 dcdc6dbad1a36373f1337428449240045dfa3a97793b54d6bdf67de427fa104e

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 0c95cac3379b9a418473e45b0c114821c55d3192cc06d7ad2fa9e65fe90a992d
MD5 eadc8850aa28fb6f1e93c76bc6d40d04
BLAKE2b-256 96db9c6174bab12ad81e6de7ed8da3ee593ab7f6eb7c2666b12e41ae61e35446

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 af1524e7f0b0272ecbf04e6cfd7af65848167336889b31d7996de2d882f26a90
MD5 6d556b2501c354d8871ce7e77b775b73
BLAKE2b-256 97c74e766944bc2606093ee4b094c6588d69dfb49d89f9338227175f510f39cd

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: bitbully-0.0.73-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 479.8 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.73-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 e439fa8505ffb0008c0876698de1e4e1ae44f69cc0019bc4220c9e71b53dd244
MD5 1879a47259739f7f0f8f105f91324987
BLAKE2b-256 354a2303d0390127e1cebe46d50a93fa6b0d38dee7df8475c2e141f5901701fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e90a6a90b671382dd64588394ac3bddbd3aceb28d5ef5ad478599bba12ef43dc
MD5 8f44a90362e8d4a550601def605322a4
BLAKE2b-256 71d72881c500a1ce0cb7c5ab9d081e67ab6fd0281f133dfbb37b58965f2f1036

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a5fb86202b767286bae7ed9940cbf3d0d730e2bb02d2d6c7f3ad9abd75c218e2
MD5 1290bf140f88f762e51d94e8712ea939
BLAKE2b-256 19381c9412550af1b071e6dea65cda2271973c16ec87c2390b1e8bc1d809798e

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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.73-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bitbully-0.0.73-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 843b1404730d0ee9224135686235188ac25731030f610eec7eeef8e27ff4c257
MD5 33865d0afdae548c391fba836c0db173
BLAKE2b-256 8b9eb4bbcc93a457942945b00e0e2314e62624ee78cc97ec5e88c8ca86dd54df

See more details on using hashes here.

Provenance

The following attestation bundles were made for bitbully-0.0.73-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