42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
|
"""Dice rolling operations (outside of the lex/yacc roller)."""
|
||
|
import random
|
||
|
|
||
|
import numexpr
|
||
|
|
||
|
rand = random.SystemRandom()
|
||
|
|
||
|
|
||
|
def cypher_roll(difficulty=None, mods=0):
|
||
|
"""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')
|
||
|
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:
|
||
|
effect = '+1 damage'
|
||
|
elif roll == 18:
|
||
|
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)
|