Skip to content

Commit

Permalink
[dice] Handle negative numbers and uppercase letters.
Browse files Browse the repository at this point in the history
First, add case-insensitivity to the "d" and "v" letters in the input
regex by capturing [dD] and [vV] in regexes.

Next, make sure we can handle negative numbers properly by capturing
a possible "-" in front of any numbers. If dice_num or dice_type ends
up negative, abort _roll_dice early (dice_type already had a negative
check that wasn't being hit because "-" wasn't captured).
  • Loading branch information
Ganon11 committed Dec 10, 2015
1 parent 2ab08a8 commit bb4af03
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions sopel/modules/dice.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,10 @@ def get_number_of_faces(self):
def _roll_dice(bot, dice_expression):
result = re.search(
r"""
(?P<dice_num>\d*)
(?P<dice_num>-?\d*)
d
(?P<dice_type>\d+)
(v(?P<drop_lowest>\d+))?
(?P<dice_type>-?\d+)
(v(?P<drop_lowest>-?\d+))?
$""",
dice_expression,
re.IGNORECASE | re.VERBOSE)
Expand All @@ -140,6 +140,11 @@ def _roll_dice(bot, dice_expression):
bot.reply("I don't have any dice with %d sides. =(" % dice_type)
return None # Signal there was a problem

# Can't roll a negative number of dice.
if dice_num < 0:
bot.reply("I'd rather not roll a negative amount of dice. =(")
return None # Signal there was a problem

# Upper limit for dice should be at most a million. Creating a dict with
# more than a million elements already takes a noticeable amount of time
# on a fast computer and ~55kB of memory.
Expand Down Expand Up @@ -176,15 +181,15 @@ def roll(bot, trigger):
"""
# This regexp is only allowed to have one captured group, because having
# more would alter the output of re.findall.
dice_regexp = r"\d*d\d+(?:v\d+)?"
dice_regexp = r"-?\d*[dD]-?\d+(?:[vV]-?\d+)?"

# Get a list of all dice expressions, evaluate them and then replace the
# expressions in the original string with the results. Replacing is done
# using string formatting, so %-characters must be escaped.
if not trigger.group(2):
return bot.reply("No dice to roll.")
arg_str = trigger.group(2)
dice_expressions = re.findall(dice_regexp, arg_str, re.IGNORECASE)
dice_expressions = re.findall(dice_regexp, arg_str)
arg_str = arg_str.replace("%", "%%")
arg_str = re.sub(dice_regexp, "%s", arg_str)

Expand Down

0 comments on commit bb4af03

Please sign in to comment.