Source code for opend6_tools.die_simplification
r"""
Creates the Die Code Simplification table from first principles.
This script emits the **published** wild-die table:
.. csv-table::
:header: Die Code, 5D, Wild Die
:math:`n`, :math:`\lfloor 0.5 + 3.5(n-5) \rfloor`, :math:`\lfloor 0.5 + 3.5(n-1) \rfloor`
Alternate
=========
There might be **slightly** more accurate approach, but it doesn't seem any more playable.
Any given die roll of :math:`n` die has two components: Ordinary Die and Wild Die.
- **Ordinary Die**. Average is :math:`(n-1) \times 3.5`.
- **Wild Die**. There are three possible outcomes.
- :math:`\frac{1}{6}` Critical Failure. This can reduce the total.
The simplification however, doesn't change the total. Die value is 1.
Contribution to the total is about 0.17.
- :math:`\frac{1}{6}` Critical Success. Roll this Wild Die again, accumulating the values.
There can be multiple re-rolls of the wild die.
- :math:`\frac{5}{6}` the re-roll is not 6.
Expected value is :math:`\frac{1}{6} + (6 + 3\times\frac{5}{6}) = \frac{17}{12} \approx 1.42`.
- :math:`\frac{1}{6} \times \frac{5}{6}` the first re-roll is 6, the second is not 6.
Expected value is :math:`\frac{1}{6}^2 \times (12 + 3\times\frac{5}{6}) = \frac{29}{72} \approx 0.4`.
- :math:`(\frac{1}{6})^3 \frac{5}{6}` three re-rolls.
Expected value is :math:`\frac{1}{6}^3 \times (18 + 3\times\frac{5}{6}) = \frac{41}{432} \approx 0.095`.
- etc. :math:`\sum 6\times\frac{1}{6}^n = \frac{6}{5}` for :math:`n` re-rolls.
Total is :math:`\frac{1}{6} (\frac{6}{5} + 3\times\frac{5}{6}) = \frac{27}{10} = 2.7`.
- :math:`\frac{4}{6}` Nothing Special. Die average is 3.5.
Contribution to the total is about 2.3.
Total: :math:`\frac{31}{6} \approx 5.16`.
This is too small a difference to justify the more complicated computation.
Rolling :math:`n` die seems to be :math:`(n-1) \times 3.5 + \frac{31}{6}`.
Implementation
==============
.. autofunction:: die_code
.. autofunction:: main
"""
from collections.abc import Iterator
import csv
import sys
import typer
[docs]
def die_code(
start: int = 1, stop: int = 51, step: int = 1
) -> Iterator[tuple[str, str, str]]:
"""Emits the sequence of die code simplifications as triples.
(Die code, 5D, Wild Die).
:param start: starting Die code (default 1)
:param stop: ending Die code (default 51)
:param step: step vvalue (default 1)
"""
for n in range(start, stop, step):
if n >= 5:
d5 = int(0.5 + (n - 5) * 3.5)
else:
d5 = 0
if n >= 2:
wd = int(0.5 + (n - 1) * 3.5)
else:
wd = 0
yield f"{n}D", f"+{d5}", f"+{wd}"
[docs]
def main(start: int = 1, stop: int = 51) -> None:
"""Produce CSV-formatted table of Die Code simplifications."""
target = csv.writer(sys.stdout)
target.writerow(("Die Code", "5D", "Wild Die"))
target.writerows(die_code(start, stop))
app = typer.Typer()
app.command()(main)
if __name__ == "__main__": # pragma: no cover
app()