roll/roll/cli/__init__.py

95 lines
2.6 KiB
Python

from typing import Literal
import click
from roll.__about__ import __version__
from roll.cli.roll_param import ROLL
from roll.roll import Roll
from roll.throw import Throw
CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]}
@click.group(context_settings=CONTEXT_SETTINGS, invoke_without_command=True)
@click.version_option(version=__version__, prog_name="roll")
@click.argument("roll", type=ROLL, default="1d20")
def cli(roll: Roll | Literal["advantage"] | Literal["disadvantage"]) -> None:
"""throw a ROLL and print the results
ROLL is specified as
DdS[(+|-)M]
where D = # of dice, S = sides per die, and M = optional modifier
if no ROLL is provided, a 1d20 is thrown
instead of a ROLL specifier, you can use a substring of "advantage"
or "disadvantage" to throw 2d20 and take the appropriate result
example usage:
\b
$ roll 2d20+3
rolling 2d20+3:
1: | 2
2: | 13
mod: +3
total: 18
\b
$ roll
rolling 1d20:
1: | 11
total: 11
\b
$ roll advantage
rolling 2d20 with advantage:
1: | 13
1: | 2
total: 13
\b
$ roll dis
rolling 2d20 with disadvantage:
1: | 1
2: | 19
total: 1
critical miss!
"""
if isinstance(roll, str):
throw = _advantage(roll)
else:
throw = _throw(roll)
total = f" {throw.total}"
click.secho(f"total:\t{total:╶>5}", bold=True)
if throw.is_critical_hit: # pragma: no cover (random)
click.secho("critical hit!", fg="green", bold=True)
elif throw.is_critical_miss: # pragma: no cover (random)
click.secho("critical miss!", fg="red", bold=True)
def _advantage(advantage: str) -> Throw:
"""print the results of an advantage or disadvantage roll"""
click.echo(f"throwing 2d20 with {advantage}:")
roll = Roll()
fst = roll.throw()
snd = roll.throw()
click.echo(f"1:\t{fst.total: >5}")
click.echo(f"2:\t{snd.total: >5}")
if advantage == "advantage":
throw = fst if fst.total > snd.total else snd
else:
throw = fst if fst.total < snd.total else snd
return throw
def _throw(roll: Roll) -> Throw:
"""print the results of a roll"""
click.echo(f"throwing {roll.to_str()}:")
throw = roll.throw()
for i, result in enumerate(throw.results, start=1):
click.echo(f"{i}:\t{result: >5}")
if roll.modifier:
color = "green" if roll.modifier > 0 else "red"
click.secho(f"mod:\t{roll.modifier_str(): >5}", fg=color)
return throw