I'm working on a simple dice roller for a Python IRC bot. The particular game this roller is for uses six different kinds of dice, which I've defined using a simple base class, and created six instances of it, passing a string array with the possible values of each dice.
class DiceBag(object):
def __init__(self, dice: List[str]):
self.bag = dice
def draw(self, count: int) -> str:
return [random.choice(self.bag) for _ in range(0, count)]
An example of the instances:
proficiency_dice = DiceBag(['', 'S', 'S', 'SS', 'SS', 'A', 'AS', 'AS', 'AS', 'AA', 'AA', '!'])
boost_dice = DiceBag(['', '', 'AA', 'A', 'SA', 'S'])
Now for a user to actually access this function, they must write a textual dice expression in the IRC channel. An example usage:
<user> ?roll 2p1b
<bot> Result: P(A, AA) B(S)
So I need a way to quickly convert from the dice expression provided by the user, to call the draw
method on the appropriate class.
I'm using a regular expression to evaluate the dice expression, so named capture groups seem like the most straightforward way to handle this - at the possible cost of my immortal soul, since I'm eval-ing the group name to the proper instance of DiceBag.
#User's input comes in as a string on the dice var
rex = (r'(?P<setback>\ds)?'
r'(?P<ability>\da)?'
r'(?P<difficulty>\dd)?'
r'(?P<proficiency>\dp)?')
to_roll = re.match(rex, dice).groups()
for group in to_roll:
if group: # We don't care about the Nones
dicetype = group.split('')[1]
dicecnt = group.split('')[0] # handle the extra rolls later
eval(dicetype + "_dice" + ".draw(" + dicecnt + ")")
Is there a better, or saner, or more pythonic, or perhaps less evil way I could be handling this use case?
proficiency_dice
andboost_dice
constant (and other dice types)? \$\endgroup\$