"""Dice rolling operations (outside of the lex/yacc roller).""" import random import numexpr rand = random.SystemRandom() def cypher_roll(difficulty=None, mods=0, is_attack=False): """Make a Cypher System roll. Args: difficulty: the original difficulty to beat; if provided, success or failure is indicated in the results mods: eases(-) and hindrances(+) to apply to the check, as a string (e.g. '-3+1') is_attack: if the roll is an attack (in which case the damage-only effects are included) Returns: tuple of: - the result on the d20 - the highest difficulty beaten - if the difficulty is known, if the target was beat - miscellaneous effects """ roll = rand.randint(1, 20) if roll == 1: return (roll, None, False if difficulty else None, 'a GM intrusion') effect = None if roll == 17 and is_attack: effect = '+1 damage' elif roll == 18 and is_attack: effect = '+2 damage' elif roll == 19: effect = 'a minor effect' elif roll == 20: effect = 'a MAJOR EFFECT' # if we know the difficulty, the mods would adjust the difficulty, but for the case where we don't, # and maybe just in general, it's easier to modify the difficulty that the roll beats, so we flip the logic # if incoming eases are a negative number, they should add to the difficulty the roll beats beats = (roll // 3) - (numexpr.evaluate(mods).item() if mods else 0) beats = 0 if beats < 0 else beats return (roll, beats, difficulty <= beats if difficulty else None, effect) def reaction_roll(): """Make a reaction roll, which gives some oracle-like randomness to uncertain situations (for solo play or similar). Returns: tuple of: - the result on the d20 - the label for the result - a summary of the result ('++', '+', '~', '-', '--') (best to worst) """ roll = rand.randint(1, 20) if 1 == roll: label = 'VERY negative' summary = '--' elif 2 <= roll <= 6: label = 'negative' summary = '-' elif 7 <= roll <= 14: label = 'positive, with complications' summary = '~' elif 15 <= roll <= 19: label = 'positive' summary = '+' else: label = 'VERY positive' summary = '++' return (roll, label, summary)