# Dice - roll dice when asked, intended for RPGs # Copyright (C) 2010 Brian S. Stephan # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import math import re import random from extlib import irclib from Module import Module # Rolls dice, for RPGs mostly class Dice(Module): def do(self, connection, event, nick, userhost, replypath, what, admin_unlocked): whats = what.split(' ') if whats[0] == 'roll': rollitrs = re.split(';\s*', ' '.join(whats[1:])) reply = "" for count, roll in enumerate(rollitrs): pattern = '^(?:(\d+)#)?(?:(\d+)/)?(\d+)?d(\d+)(?:(\+|\-)(\d+))?(?:\s+(.*))?' regex = re.compile(pattern) matches = regex.search(roll) if matches is not None: # set variables including defaults for unspecified stuff faces = int(matches.group(4)) comment = matches.group(7) if matches.group(1) is None: times = 1 else: times = int(matches.group(1)) if matches.group(3) is None: dice = 1 else: dice = int(matches.group(3)) if matches.group(2) is None: top = dice else: top = int(matches.group(2)) if matches.group(5) is None or matches.group(6) is None: modifier = 0 else: if str(matches.group(5)) == '-': modifier = -1 * int(matches.group(6)) else: modifier = int(matches.group(6)) result = roll + ': ' for t in range(times): ressubstr = "" rolls = [] for d in range(dice): rolls.append(str(random.randint(1, faces))) rolls.sort() rolls.reverse() ressubstr = ','.join(rolls[0:top]) sum = 0 for r in rolls[0:top]: sum += int(r) sumplus = sum + modifier result += str(sumplus) + ' [' + ressubstr if modifier != 0: if modifier > 0: result += ' + ' + str(modifier) else: result += ' - ' + str(-1 * modifier) result += ']' if t != times-1: result += ', ' reply += result if count is not len(rollitrs)-1: reply += "; " if reply is not "": return self.reply(connection, replypath, nick + ': ' + reply) if whats[0] == 'ctech': rollitrs = re.split(';\s*', ' '.join(whats[1:])) reply = "" for count, roll in enumerate(rollitrs): pattern = '^(\d+)d(?:(\+|\-)(\d+))?(?:\s+(.*))?' regex = re.compile(pattern) matches = regex.search(roll) if matches is not None: dice = int(matches.group(1)) comment = '' modifier = 0 if matches.group(2) is not None and matches.group(3) is not None: if str(matches.group(2)) == '-': modifier = -1 * int(matches.group(3)) else: modifier = int(matches.group(3)) if matches.group(4) is not None: comment = matches.group(4) result = roll + ': ' rolls = [] for d in range(dice): rolls.append(random.randint(1, 10)) rolls.sort() rolls.reverse() # highest single die method method1 = rolls[0] # highest set method method2 = 0 rolling_sum = 0 for i, r in enumerate(rolls): # if next roll is same as current, sum and continue, else see if sum is best so far if i+1 < len(rolls) and rolls[i+1] == r: if rolling_sum == 0: rolling_sum = r rolling_sum += r else: if rolling_sum > method2: method2 = rolling_sum rolling_sum = 0 # check for set in progress (e.g. lots of 1s) if rolling_sum > method2: method2 = rolling_sum # straight method method3 = 0 rolling_sum = 0 count = 0 for i, r in enumerate(rolls): # if next roll is one less as current, sum and continue, else check len and see if sum is best so far if i+1 < len(rolls) and rolls[i+1] == r-1: if rolling_sum == 0: rolling_sum = r count += 1 rolling_sum += r-1 count += 1 else: if count >= 3 and rolling_sum > method3: method3 = rolling_sum rolling_sum = 0 # check for straight in progress (e.g. straight ending in 1) if count >= 3 and rolling_sum > method3: method3 = rolling_sum # get best roll best = max([method1, method2, method3]) # check for critical failure botch = False ones = 0 for r in rolls: if r == 1: ones += 1 if ones >= math.ceil(float(len(rolls))/2): botch = True if botch: result += 'BOTCH' else: result += str(best + modifier) rollres = '' for i,r in enumerate(rolls): rollres += str(r) if i is not len(rolls)-1: rollres += ',' result += ' [' + rollres if modifier != 0: if modifier > 0: result += ' +' + str(modifier) else: result += ' -' + str(modifier * -1) result += ']' reply += result if count is not len(rollitrs)-1: reply += "; " if reply is not "": return self.reply(connection, replypath, nick + ': ' + reply) # vi:tabstop=4:expandtab:autoindent # kate: indent-mode python;indent-width 4;replace-tabs on;