# Penny Ante
[](https://pypi.org/project/penny-ante)
[](https://pypi.org/project/penny-ante)
A Python implementation of a roulette wheel game simulator with a realistic game architecture. This package provides classes for managing roulette games, including American and European wheel types, table management, croupier operations, player management, and comprehensive chip handling.
## Features
- **Realistic Game Architecture**: Modeled after real game operations with Table, Croupier, and Layout classes
- **Multiple Wheel Types**: Support for both American (38 spaces) and European (37 spaces) roulette wheels
- **Professional Table Management**: Integrated wheel and betting layout management
- **Croupier Operations**: Dedicated croupier for handling game operations and wheel spinning
- **Betting Layout**: Proper roulette table layout with space positioning and lookup functionality
- **Advanced Player Management**: Full player lifecycle with chip purchasing and management
- **Comprehensive Chip System**: Complete chip handling with cash value calculation and transaction management
- **Random Number Generation**: Cryptographically secure random number generation using `os.urandom()`
- **Type Safety**: Full type hints throughout the codebase for better development experience
- **Comprehensive Testing**: Full test coverage for all components with 43 test cases
## Installation
```console
pip install penny-ante
```
## Quick Start
```python
from penny_ante.game import Game
# Create a new game with American table
game = Game(table_type='AMERICAN')
# Add players and give them chips
game.add_player('Alice')
game.add_player('Bob')
# Players can buy chips
game.players['Alice'].buy_chips(count=10, value=5) # 10 chips worth $5 each
game.players['Bob'].buy_chips(count=20, value=1) # 20 chips worth $1 each
# Spin the wheel
game.spin_wheel()
print(f"Landed on: {game.current_space.value} ({game.current_space.color})")
print(f"Alice has ${game.players['Alice'].chips.cash_value()} in chips")
```
## Architecture Overview
The package uses a realistic game architecture:
- **Game**: Main game controller that orchestrates all components
- **Table**: Manages the physical roulette table with wheel and betting layout
- **Croupier**: Handles game operations, wheel spinning, and bet management
- **Layout**: Manages the betting grid and space positioning for bet placement
- **Wheel**: The roulette wheel with cryptographically secure spinning
- **Player**: Individual players with chip management capabilities
- **Chips**: Chip collections with value tracking and transaction handling
- **Space**: Individual spaces on the wheel with position and color information
## Key Features
### 🎯 **Overlay Configuration System**
Create custom rules that inherit from defaults - no need to specify complete configurations!
```python
# Only specify what you want to change
overlay = {
"table_limits": {"minimum_bet": 25, "maximum_bet": 5000000},
"payout_ratios": {"straight_up": 40} # Higher than standard 35:1
}
game = Game(table_type="AMERICAN", overlay_rules=overlay)
# Everything else inherits from American defaults
```
**Benefits:**
- ✅ **Simplified customization** - specify only what changes
- ✅ **Automatic inheritance** - missing values use sensible defaults
- ✅ **Type-safe** - full validation and error handling preserved
- ✅ **Backward compatible** - existing code works unchanged
See `examples/overlay_rules_demo.py` for comprehensive examples.
## Usage
### Creating a Game
```python
from penny_ante.game import Game
# American table (38 spaces: 0, 00, 1-36)
game = Game(table_type='AMERICAN')
# European table (37 spaces: 0, 1-36)
game = Game(table_type='EUROPEAN')
# Access table components
print(f"Wheel type: {game.table.wheel.type}")
print(f"Layout type: {game.table.layout.type}")
print(f"Number of spaces: {len(game.table.wheel.spaces)}")
```
### Managing Players and Chips
```python
# Add players
game.add_player('Player1')
game.add_player('Player2')
# Players can buy chips
player1 = game.players['Player1']
player1.buy_chips(count=50, value=1) # 50 chips worth $1 each
# Check chip values
print(f"Player1 has {player1.chips.count} chips")
print(f"Total value: ${player1.chips.cash_value()}")
# Add more chips of the same value
player1.chips.change_chips(count=25) # Add 25 more chips
print(f"Now has {player1.chips.count} chips worth ${player1.chips.cash_value()}")
```
### Working with the Table and Croupier
```python
# The croupier manages the game
croupier = game.croupier
croupier.spin_wheel()
# Access the table layout
layout = game.table.layout
space_1 = layout.find_space('1') # Find space with value '1'
print(f"Space 1 is at row {space_1.layout_row}, column {space_1.layout_column}")
# Direct table access
table = game.table
print(f"Table has {len(table.wheel.spaces)} spaces")
```
### Spinning the Wheel
```python
# Spin via game (recommended)
game.spin_wheel()
# Or spin via croupier directly
game.croupier.spin_wheel()
# Or spin via table directly
game.table.spin_wheel()
# Access the result
current_space = game.current_space
print(f"Value: {current_space.value}")
print(f"Color: {current_space.color}")
print(f"Wheel location: {current_space.wheel_location}")
print(f"Layout position: ({current_space.layout_row}, {current_space.layout_column})")
```
### Advanced Chip Operations
```python
from penny_ante.chips import Chips
# Create chip collections
red_chips = Chips(value=5)
red_chips.change_chips(count=10) # Add 10 chips
blue_chips = Chips(value=25)
blue_chips.change_chips(count=4) # Add 4 chips
print(f"Red chips: {red_chips.count} × ${red_chips.value} = ${red_chips.cash_value()}")
print(f"Blue chips: {blue_chips.count} × ${blue_chips.value} = ${blue_chips.cash_value()}")
# Combine chip collections (must be same value)
more_red = Chips(value=5)
more_red.change_chips(count=5)
red_chips.change_chips(chips=more_red) # Merge collections
print(f"Combined red chips: {red_chips.count} × ${red_chips.value} = ${red_chips.cash_value()}")
```
## Development
This project uses [Poe the Poet](https://poethepoet.natn.io/) for task management.
### Prerequisites
Install these tools globally with [pipx](https://pypa.github.io/pipx/) (recommended):
```console
# Install pipx if you haven't already
pip install pipx
# Install global development tools
pipx install poethepoet
pipx install black
pipx install build
```
> **Why pipx?** pipx installs tools in isolated environments, preventing dependency conflicts while making them available globally. This is the recommended way to install Python CLI tools.
Alternatively, you can install poe locally:
```console
pip install poethepoet
```
### Development Setup
**Quick setup (recommended):**
```console
# Run the automated setup script
./setup-dev.sh
```
**Manual setup:**
```console
# Install the package in development mode
poe install-dev
# Show version info
poe info
```
### Testing
```console
# Run all tests
poe test
# Run tests with coverage
poe test-all
# Run tests quickly (stop on first failure)
poe test-fast
# Generate HTML coverage report
poe test-cov-html
```
### Code Quality
```console
# Format code with Black
poe format
# Check formatting
poe format-check
# Show formatting diff
poe format-diff
# Run all quality checks
poe check-all
```
### Development Utilities
```console
# Demo: spin wheel once
poe demo
# Demo: spin wheel 5 times
poe wheel-demo
# Clean build artifacts
poe clean
# Build package
poe build
```
### Composite Tasks
```console
# Setup development environment
poe dev-setup
# Pre-commit checks (format + all checks)
poe pre-commit
# CI pipeline (format-check + test with coverage)
poe ci
# Release readiness check
poe release-check
```
### Available Tasks
Run `poe --help` to see all available tasks:
- **Testing**: `test`, `test-fast`, `test-cov`, `test-cov-report`, `test-cov-html`, `test-all`
- **Code Quality**: `format`, `format-check`, `format-diff`, `lint`, `check-all`
- **Development**: `demo`, `wheel-demo`, `info`, `clean`, `build`, `install-dev`, `setup`
- **Composite**: `dev-setup`, `pre-commit`, `ci`, `release-check`
### Project Structure
```
src/penny_ante/
├── __init__.py
├── game.py # Main game controller
├── table.py # Roulette table management
├── croupier.py # Croupier operations
├── layout.py # Betting layout management
├── wheel.py # Roulette wheel implementation
├── player.py # Player management with chip support
├── space.py # Individual wheel spaces
└── chips.py # Comprehensive chip handling
```
## API Reference
### Core Classes
- **`Game`**: Main game controller with table, croupier, and player management
- **`Table`**: Manages wheel and betting layout for a roulette table
- **`Croupier`**: Handles game operations and wheel spinning
- **`Layout`**: Manages betting grid with space positioning and lookup
- **`Wheel`**: Roulette wheel with cryptographically secure spinning
- **`Player`**: Individual player with chip management capabilities
- **`Chips`**: Chip collection with value tracking and transactions
- **`Space`**: Individual wheel space with position and color information
### Key Methods
- **`Game.spin_wheel()`**: Spin the wheel via the croupier
- **`Game.add_player(name)`**: Add a new player to the game
- **`Player.buy_chips(count, value)`**: Purchase chips for the player
- **`Chips.change_chips(count, value, chips)`**: Modify chip collection
- **`Chips.cash_value()`**: Calculate total cash value of chips
- **`Layout.find_space(value)`**: Find a space on the betting layout
- **`Wheel.spin()`**: Spin the wheel and set current_space
## License
`penny-ante` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.
Raw data
{
"_id": null,
"home_page": null,
"name": "penny-ante",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "betting, casino, gambling, game, roulette, simulation, wheel",
"author": null,
"author_email": "Peter Bowen <peter@bowenfamily.org>",
"download_url": "https://files.pythonhosted.org/packages/89/84/f7cd30ac26773fdd1ed52e641acb42d8805ff66586cacf1a5ad6870db734/penny_ante-1.0.0.tar.gz",
"platform": null,
"description": "# Penny Ante\n\n[](https://pypi.org/project/penny-ante)\n[](https://pypi.org/project/penny-ante)\n\nA Python implementation of a roulette wheel game simulator with a realistic game architecture. This package provides classes for managing roulette games, including American and European wheel types, table management, croupier operations, player management, and comprehensive chip handling.\n\n## Features\n\n- **Realistic Game Architecture**: Modeled after real game operations with Table, Croupier, and Layout classes\n- **Multiple Wheel Types**: Support for both American (38 spaces) and European (37 spaces) roulette wheels\n- **Professional Table Management**: Integrated wheel and betting layout management\n- **Croupier Operations**: Dedicated croupier for handling game operations and wheel spinning\n- **Betting Layout**: Proper roulette table layout with space positioning and lookup functionality\n- **Advanced Player Management**: Full player lifecycle with chip purchasing and management\n- **Comprehensive Chip System**: Complete chip handling with cash value calculation and transaction management\n- **Random Number Generation**: Cryptographically secure random number generation using `os.urandom()`\n- **Type Safety**: Full type hints throughout the codebase for better development experience\n- **Comprehensive Testing**: Full test coverage for all components with 43 test cases\n\n## Installation\n\n```console\npip install penny-ante\n```\n\n## Quick Start\n\n```python\nfrom penny_ante.game import Game\n\n# Create a new game with American table\ngame = Game(table_type='AMERICAN')\n\n# Add players and give them chips\ngame.add_player('Alice')\ngame.add_player('Bob')\n\n# Players can buy chips\ngame.players['Alice'].buy_chips(count=10, value=5) # 10 chips worth $5 each\ngame.players['Bob'].buy_chips(count=20, value=1) # 20 chips worth $1 each\n\n# Spin the wheel\ngame.spin_wheel()\nprint(f\"Landed on: {game.current_space.value} ({game.current_space.color})\")\nprint(f\"Alice has ${game.players['Alice'].chips.cash_value()} in chips\")\n```\n\n## Architecture Overview\n\nThe package uses a realistic game architecture:\n\n- **Game**: Main game controller that orchestrates all components\n- **Table**: Manages the physical roulette table with wheel and betting layout\n- **Croupier**: Handles game operations, wheel spinning, and bet management\n- **Layout**: Manages the betting grid and space positioning for bet placement\n- **Wheel**: The roulette wheel with cryptographically secure spinning\n- **Player**: Individual players with chip management capabilities\n- **Chips**: Chip collections with value tracking and transaction handling\n- **Space**: Individual spaces on the wheel with position and color information\n\n## Key Features\n\n### \ud83c\udfaf **Overlay Configuration System**\nCreate custom rules that inherit from defaults - no need to specify complete configurations!\n\n```python\n# Only specify what you want to change\noverlay = {\n \"table_limits\": {\"minimum_bet\": 25, \"maximum_bet\": 5000000},\n \"payout_ratios\": {\"straight_up\": 40} # Higher than standard 35:1\n}\n\ngame = Game(table_type=\"AMERICAN\", overlay_rules=overlay)\n# Everything else inherits from American defaults\n```\n\n**Benefits:**\n- \u2705 **Simplified customization** - specify only what changes\n- \u2705 **Automatic inheritance** - missing values use sensible defaults \n- \u2705 **Type-safe** - full validation and error handling preserved\n- \u2705 **Backward compatible** - existing code works unchanged\n\nSee `examples/overlay_rules_demo.py` for comprehensive examples.\n\n## Usage\n\n### Creating a Game\n\n```python\nfrom penny_ante.game import Game\n\n# American table (38 spaces: 0, 00, 1-36)\ngame = Game(table_type='AMERICAN')\n\n# European table (37 spaces: 0, 1-36)\ngame = Game(table_type='EUROPEAN')\n\n# Access table components\nprint(f\"Wheel type: {game.table.wheel.type}\")\nprint(f\"Layout type: {game.table.layout.type}\")\nprint(f\"Number of spaces: {len(game.table.wheel.spaces)}\")\n```\n\n### Managing Players and Chips\n\n```python\n# Add players\ngame.add_player('Player1')\ngame.add_player('Player2')\n\n# Players can buy chips\nplayer1 = game.players['Player1']\nplayer1.buy_chips(count=50, value=1) # 50 chips worth $1 each\n\n# Check chip values\nprint(f\"Player1 has {player1.chips.count} chips\")\nprint(f\"Total value: ${player1.chips.cash_value()}\")\n\n# Add more chips of the same value\nplayer1.chips.change_chips(count=25) # Add 25 more chips\nprint(f\"Now has {player1.chips.count} chips worth ${player1.chips.cash_value()}\")\n```\n\n### Working with the Table and Croupier\n\n```python\n# The croupier manages the game\ncroupier = game.croupier\ncroupier.spin_wheel()\n\n# Access the table layout\nlayout = game.table.layout\nspace_1 = layout.find_space('1') # Find space with value '1'\nprint(f\"Space 1 is at row {space_1.layout_row}, column {space_1.layout_column}\")\n\n# Direct table access\ntable = game.table\nprint(f\"Table has {len(table.wheel.spaces)} spaces\")\n```\n\n### Spinning the Wheel\n\n```python\n# Spin via game (recommended)\ngame.spin_wheel()\n\n# Or spin via croupier directly\ngame.croupier.spin_wheel()\n\n# Or spin via table directly\ngame.table.spin_wheel()\n\n# Access the result\ncurrent_space = game.current_space\nprint(f\"Value: {current_space.value}\")\nprint(f\"Color: {current_space.color}\")\nprint(f\"Wheel location: {current_space.wheel_location}\")\nprint(f\"Layout position: ({current_space.layout_row}, {current_space.layout_column})\")\n```\n\n### Advanced Chip Operations\n\n```python\nfrom penny_ante.chips import Chips\n\n# Create chip collections\nred_chips = Chips(value=5)\nred_chips.change_chips(count=10) # Add 10 chips\n\nblue_chips = Chips(value=25)\nblue_chips.change_chips(count=4) # Add 4 chips\n\nprint(f\"Red chips: {red_chips.count} \u00d7 ${red_chips.value} = ${red_chips.cash_value()}\")\nprint(f\"Blue chips: {blue_chips.count} \u00d7 ${blue_chips.value} = ${blue_chips.cash_value()}\")\n\n# Combine chip collections (must be same value)\nmore_red = Chips(value=5)\nmore_red.change_chips(count=5)\nred_chips.change_chips(chips=more_red) # Merge collections\n\nprint(f\"Combined red chips: {red_chips.count} \u00d7 ${red_chips.value} = ${red_chips.cash_value()}\")\n```\n\n## Development\n\nThis project uses [Poe the Poet](https://poethepoet.natn.io/) for task management. \n\n### Prerequisites\n\nInstall these tools globally with [pipx](https://pypa.github.io/pipx/) (recommended):\n\n```console\n# Install pipx if you haven't already\npip install pipx\n\n# Install global development tools\npipx install poethepoet\npipx install black\npipx install build\n```\n\n> **Why pipx?** pipx installs tools in isolated environments, preventing dependency conflicts while making them available globally. This is the recommended way to install Python CLI tools.\n\nAlternatively, you can install poe locally:\n```console\npip install poethepoet\n```\n\n### Development Setup\n\n**Quick setup (recommended):**\n```console\n# Run the automated setup script\n./setup-dev.sh\n```\n\n**Manual setup:**\n```console\n# Install the package in development mode\npoe install-dev\n\n# Show version info\npoe info\n```\n\n### Testing\n\n```console\n# Run all tests\npoe test\n\n# Run tests with coverage\npoe test-all\n\n# Run tests quickly (stop on first failure)\npoe test-fast\n\n# Generate HTML coverage report\npoe test-cov-html\n```\n\n### Code Quality\n\n```console\n# Format code with Black\npoe format\n\n# Check formatting\npoe format-check\n\n# Show formatting diff\npoe format-diff\n\n# Run all quality checks\npoe check-all\n```\n\n### Development Utilities\n\n```console\n# Demo: spin wheel once\npoe demo\n\n# Demo: spin wheel 5 times\npoe wheel-demo\n\n# Clean build artifacts\npoe clean\n\n# Build package\npoe build\n```\n\n### Composite Tasks\n\n```console\n# Setup development environment\npoe dev-setup\n\n# Pre-commit checks (format + all checks)\npoe pre-commit\n\n# CI pipeline (format-check + test with coverage)\npoe ci\n\n# Release readiness check\npoe release-check\n```\n\n### Available Tasks\n\nRun `poe --help` to see all available tasks:\n\n- **Testing**: `test`, `test-fast`, `test-cov`, `test-cov-report`, `test-cov-html`, `test-all`\n- **Code Quality**: `format`, `format-check`, `format-diff`, `lint`, `check-all`\n- **Development**: `demo`, `wheel-demo`, `info`, `clean`, `build`, `install-dev`, `setup`\n- **Composite**: `dev-setup`, `pre-commit`, `ci`, `release-check`\n\n### Project Structure\n\n```\nsrc/penny_ante/\n\u251c\u2500\u2500 __init__.py\n\u251c\u2500\u2500 game.py # Main game controller\n\u251c\u2500\u2500 table.py # Roulette table management\n\u251c\u2500\u2500 croupier.py # Croupier operations\n\u251c\u2500\u2500 layout.py # Betting layout management\n\u251c\u2500\u2500 wheel.py # Roulette wheel implementation\n\u251c\u2500\u2500 player.py # Player management with chip support\n\u251c\u2500\u2500 space.py # Individual wheel spaces\n\u2514\u2500\u2500 chips.py # Comprehensive chip handling\n```\n\n## API Reference\n\n### Core Classes\n\n- **`Game`**: Main game controller with table, croupier, and player management\n- **`Table`**: Manages wheel and betting layout for a roulette table\n- **`Croupier`**: Handles game operations and wheel spinning\n- **`Layout`**: Manages betting grid with space positioning and lookup\n- **`Wheel`**: Roulette wheel with cryptographically secure spinning\n- **`Player`**: Individual player with chip management capabilities\n- **`Chips`**: Chip collection with value tracking and transactions\n- **`Space`**: Individual wheel space with position and color information\n\n### Key Methods\n\n- **`Game.spin_wheel()`**: Spin the wheel via the croupier\n- **`Game.add_player(name)`**: Add a new player to the game\n- **`Player.buy_chips(count, value)`**: Purchase chips for the player\n- **`Chips.change_chips(count, value, chips)`**: Modify chip collection\n- **`Chips.cash_value()`**: Calculate total cash value of chips\n- **`Layout.find_space(value)`**: Find a space on the betting layout\n- **`Wheel.spin()`**: Spin the wheel and set current_space\n\n## License\n\n`penny-ante` is distributed under the terms of the [MIT](https://spdx.org/licenses/MIT.html) license.\n",
"bugtrack_url": null,
"license": null,
"summary": "A Python roulette wheel game simulator with realistic game architecture",
"version": "1.0.0",
"project_urls": {
"Documentation": "https://github.com/huntsberg/python_penny-ante#readme",
"Issues": "https://github.com/huntsberg/python_penny-ante/issues",
"Source": "https://github.com/huntsberg/python_penny-ante"
},
"split_keywords": [
"betting",
" casino",
" gambling",
" game",
" roulette",
" simulation",
" wheel"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "9a8b6645659e9b9ec5f83499d9a37c715d98d5c2e170c143fdd7d4e94896df28",
"md5": "5ba29c59f995f4b0e349db60e2a03b78",
"sha256": "c4a850cdb906b917f38acf2b092a18bc659b726096ca44683a76903b6142384d"
},
"downloads": -1,
"filename": "penny_ante-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5ba29c59f995f4b0e349db60e2a03b78",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 26118,
"upload_time": "2025-08-13T05:23:16",
"upload_time_iso_8601": "2025-08-13T05:23:16.623371Z",
"url": "https://files.pythonhosted.org/packages/9a/8b/6645659e9b9ec5f83499d9a37c715d98d5c2e170c143fdd7d4e94896df28/penny_ante-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8984f7cd30ac26773fdd1ed52e641acb42d8805ff66586cacf1a5ad6870db734",
"md5": "09ede393a530f789c4146a7bbf36def6",
"sha256": "4443d1db18dc6f0bdb97513fd3a5dc0e1d836a3249eea296bcc73da0eb598977"
},
"downloads": -1,
"filename": "penny_ante-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "09ede393a530f789c4146a7bbf36def6",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 69372,
"upload_time": "2025-08-13T05:23:18",
"upload_time_iso_8601": "2025-08-13T05:23:18.390694Z",
"url": "https://files.pythonhosted.org/packages/89/84/f7cd30ac26773fdd1ed52e641acb42d8805ff66586cacf1a5ad6870db734/penny_ante-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-13 05:23:18",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "huntsberg",
"github_project": "python_penny-ante#readme",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "penny-ante"
}