#!/usr/bin/env python3 import random import sys from pathlib import Path import re def roll_die(num_dice: int, dice_type: int, modifier: int) -> list[int]: rolls: list[int] = [] for _ in range(num_dice): rolls.append(random.randint(1, dice_type) + modifier) return rolls def parse_dice_notation(dice_notation: str) -> tuple[int, int, int]: # Define the regular expression pattern pattern = re.compile(r"(\d+)d(\d+)([+-]\d+)?") # Search the pattern in the dice notation string match = pattern.match(dice_notation) if not match: raise ValueError(f"Invalid dice notation: {dice_notation}") # Extract the groups from the match groups = match.groups() # Convert the groups to integers and handle the optional modifier num_dice = int(groups[0]) dice_type = int(groups[1]) modifier = int(groups[2]) if groups[2] else 0 return num_dice, dice_type, modifier def summary(rolls: list[int]) -> None: print(rolls) print(f"Min: {min(rolls)}") print(f"Max: {max(rolls)}") if len(rolls) > 1: print(f"Total: {sum(rolls)}") print(f"Avg: {sum(rolls)/len(rolls):.2f}") def main(): if len(sys.argv) != 2: path = Path(sys.argv[0]).parts[-1] print(f"Usage: {path} xdy[(+|y)z]") print("Rolls x number of y sided die, optionally using a modifier z") print() print("Examples:") print("\t2d4+2 Rolls two four sided die adding 2 to each roll") print("\t1d20-1 Rolls a single twenty and subtracts 1 from the roll") sys.exit(1) dice_notation = sys.argv[1] try: num_die, die_type, modifier = parse_dice_notation(dice_notation) except ValueError as e: print(e) sys.exit(1) rolls = roll_die(num_die, die_type, modifier) summary(rolls) if __name__ == "__main__": main()