Metadata-Version: 2.4
Name: ProbabilityPewter
Version: 0.5.0
Summary: A package for simulating and visualising probability, for gaming, statistics, and other uses.
Author: Feamaika
Author-email: 6xx122r3f@mozmail.com
Project-URL: GitHub, https://github.com/Feamaika/ProbabilityPewter
Project-URL: Changelog, https://github.com/Feamaika/ProbabilityPewter/blob/main/HISTORY.md
Keywords: dice,distributions,probability,rpg,simulation
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Information Technology
Classifier: Intended Audience :: Other Audience
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Games/Entertainment :: Simulation
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24.0
Requires-Dist: py-rolldice>=0.4.0
Requires-Dist: matplotlib>=3.5.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: keywords
Dynamic: license-file
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# ProbabilityPewter
**My first public Python package.**  
***Craft odds like metals!***  
The idea is my own, and the inspiration to publish it comes from [DataCamp](https://app.datacamp.com/learn/courses/developing-python-packages).

## What This Package Is For
ProbabilityPewter is a collection of probability tools for RPG play, practical statistics, and easy exploratory analysis.

Its contents are currently divided into three parts:
- [**calculator**](#1-calculator): calculation tools for directly working with probabilities
- [**roll_stats**](#2-roll-stats): roll statistics tools for dice rolls and comparisons in game design and play
- [**visualiser**](#3-visualiser): visualisation tools for easily plotting probability distributions and highlighting probabilities of interest

## Installation
The easiest way to install the package is to install it from PyPI:
```bash
pip install ProbabilityPewter
```

## Quick Start
```python
import ProbabilityPewter as PP

PP.plot_normal() # One of the core functions exposed at top level, for easier access
```

## Package Modules

### 1) Calculator
Functions for direct probability calculations.

#### combined_prob
Calculate combined probability for independent events, like the odds of both winning the lottery and being struck by lightning in any given year:

```python
combined_prob(A=0.0000000715, B=0.000001, output_scale='odds')
# 1:14000000000000
```

#### bayes_updater
Apply Bayes' theorem to update a prior probability after evidence.

A clear Bayes example: estimate the probability that a person is a smoker, given that the person has been diagnosed with lung cancer.

Suppose:
- P(smoker) = 0.10
- P(lung cancer | smoker) = 0.13
- P(lung cancer | not smoker) = 0.015

```python
from ProbabilityPewter.calculator.bayes import bayes_updater

p_smoker_given_cancer = bayes_updater(
    prior_A=0.10,
    likelihood_B_given_A=0.13,
    likelihood_B_given_not_A=0.015,
)

print(p_smoker_given_cancer)
# 0.49056603773584906
```

So in this example, the probability is about 49%.

#### at_least_k_of_n
Compute the probability of getting at least k successes in n Bernoulli trials.

```python
from ProbabilityPewter.calculator.series import at_least_k_of_n

# Probability of at least 1 six in 6 rolls
at_least_k_of_n(1, 6, 1/6)
# 0.6651020233196159
```

#### gambler_ruin
Calculate the probability of ending up in a specific state after a series of wins and losses, given the probability of winning a bet each round.

```python
from ProbabilityPewter.calculator.series import gambler_ruin
gambler_ruin(2, 4, 0.25) # P of ending up with €4, after starting at €2, when the chance of winning €1 is p=0.25
# 0.1
``` 

### 2) Roll Stats
Functions for exact dice-expression comparison and simulation-style play support.

#### rpg_dice
Roll RPG notation and optionally show a verbose breakdown.

```python
import random
random.seed(42)
rpg_dice('4D10*2', output='verbose')
# Rolling 4D10 with * 2:
#   Result: [2, 1, 5, 4] = 12
#           12 * 2 = 24
# 24
```

#### prob_table (compare)
Compare one or more dice expressions using exact probabilities.

```python
from ProbabilityPewter.roll_stats.compare import prob_table

print(prob_table(['1D8', '2D4', '1D6+2'], target=5))
# expression   mean    std  min  max  p_beat
# 1D8         4.500  2.291    1    8   0.500
# 2D4         5.000  1.581    2    8   0.625
# 1D6+2       5.500  1.708    3    8   0.667
```

#### combat_odds / risk_odds / ti_odds / aa_odds
Estimate combat win probabilities for popular strategy games. Currently supported games are Risk, Twilight Imperium 4 (TI), and Axis & Allies.

```python
from ProbabilityPewter.roll_stats import ti_odds

r = ti_odds({'Cruiser+': 2}, {'Carrier': 1, 'Fighter': 3}, output='result')
plot_combat(r)
```

The TI and Axis & Allies functions use Monte Carlo simulation, while `risk_odds` uses exact state probabilities. The `combat_odds` function is a unified entrypoint for all supported games, and will call the appropriate function based on the `game` parameter.

```python
combat_odds(10, 8, game='risk')
# Risk odds - attacker win: 64.64%, defender win: 35.36%, avg survivors (A/D): 4.05/1.23
```

### 3) Visualiser
Plot exact and analytical distributions with highlight options.

#### plot_dice
Plot exact distribution of a dice expression.

```python
plot_dice('2D6+3', highlight=8, highlight_type='>=')
```
<p float="left">
<img src="screenshots/distribution2D6+3.png" title="Example dice roll distribution, showing all outcomes >=8 highlighted, with an annotation of the probability P for that outcome" alt="[Screenshot example dice plot]" style="width:80%; height:auto;">
</p>

#### plot_normal
Plot a standard or custom normal distribution with calculations around specific values, _z_-scores or percentiles:

```python
plot_normal(mean=100, std=15, highlight=2.2, highlight_type='above', as_z=True)
```
<p float="left">
<img src="screenshots/distribution100-15-above2.2.png" title="Example normal distribution, with an annotation of how much area falls above the given z-score" alt="[Screenshot example normal distribution]" style="width:80%; height:auto;">
</p>


#### compare_normals
Overlay two normal distributions, shade their overlap, and report the exact probability that one exceeds the other, along with the overlap coefficient and the Cohen's _d_ effect size. Handy for quick A/B-test intuition, since the difference of two independent normals is itself normal, so P(A > B) is exact - no simulation needed.

```python
from ProbabilityPewter.visualiser import compare_normals

compare_normals(a=(104, 10), b=(100, 15), labels=('New', 'Control'))
# P(New > Control) = 58.8%, Overlap = 77.8%, Cohen's d = 0.31 (small)
```

#### plot_poisson
Plot a Poisson distribution with optional highlighted outcomes, similar to the other plot functions in the submodule:

```python
from ProbabilityPewter.visualiser.distributions import plot_poisson

plot_poisson(lam=4.5, highlight=6, highlight_type='>=')
```

## API Overview

| Function | Module | Purpose | Core |
|---|---|---|---|
| combined_prob | calculator.combiner | Combine independent events (AND/OR/NOT/XOR/etc.) | ✅ |
| bayes_updater | calculator.bayes | Bayes update for posterior probability |  |
| at_least_k_of_n | calculator.series | At least k successes in n trials |  |
| gambler_ruin | calculator.series | Probability of reaching a target without reaching 0 |  |
| rpg_dice | roll_stats.dice | Roll RPG dice notation | ✅ |
| prob_table | roll_stats.compare | Exact comparison stats for dice expressions | ✅ |
| combat_odds | roll_stats.combat | Unified battle-odds entrypoint (Risk/TI/A&A) | ✅ |
| risk_odds | roll_stats.combat | Exact Risk battle odds |  |
| ti_odds | roll_stats.combat | TI4 battle odds via simulation |  |
| aa_odds | roll_stats.combat | Axis & Allies battle odds via simulation |  |
| plot_dice | visualiser.distributions | Exact discrete dice distribution plot | ✅ |
| plot_normal | visualiser.distributions | Normal distribution plot with highlights | ✅ |
| plot_poisson | visualiser.distributions | Poisson distribution plot with highlights |  |
| compare_normals | visualiser.distributions | Overlay two normals and report exact P(A > B) |  |
| plot_combat | roll_stats.combat | Bar chart for combat outcome probabilities | ✅ |

## Dice Syntax
Dice syntax for `rpg_dice` is the same as in the [py-rolldice](https://github.com/fionafibration/py-rolldice/) package from Fiona Blackett, which itself is based on CritDice.

## Changelog
See the [changelog](https://github.com/Feamaika/ProbabilityPewter/blob/main/HISTORY.md) for a history of notable changes.

## Suggestions
If you have any other ideas for features, just make a suggestion and I will see what I can do.

## Planned Features
- Adopt an alternative dependency for the `rpg_dice` function, since the aforementioned py-rolldice module uses `node.n`, which will be removed in newer Python versions, potentially breaking the package.
- Expand dice roll visualisation to support rolls for specific RPG systems like Savage Worlds and Shadowrun.
- Support for more than two events in `combined_prob`.
- ...

## Support
If you had fun or were helped by my code, feel free to buy me a coffee:  
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/E1E81X4KSI)
