126 lines
4.5 KiB
Python
126 lines
4.5 KiB
Python
"""Roll dice when asked, intended for RPGs."""
|
||
import logging
|
||
import random
|
||
import re
|
||
|
||
from django.conf import settings
|
||
|
||
from irc.client import NickMask
|
||
|
||
from dice.lib import cypher_roll
|
||
from dice.roller import DiceRoller
|
||
from ircbot.lib import Plugin
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
CYPHER_ROLL_REGEX = r'(T(?P<difficulty>\d+))?(?P<mods>(?:\s*(-|\+)\d+)*)\s*(?P<comment>.*)?'
|
||
CYPHER_COMMAND_REGEX = r'^!cypher\s+(' + CYPHER_ROLL_REGEX + ')'
|
||
|
||
|
||
class Dice(Plugin):
|
||
"""Roll simple or complex dice strings."""
|
||
|
||
def __init__(self, bot, connection, event):
|
||
"""Set up the plugin."""
|
||
self.roller = DiceRoller()
|
||
|
||
super(Dice, self).__init__(bot, connection, event)
|
||
|
||
def start(self):
|
||
"""Set up the handlers."""
|
||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], CYPHER_COMMAND_REGEX,
|
||
self.handle_cypher_roll, -20)
|
||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!roll\s+(.*)$',
|
||
self.handle_roll, -20)
|
||
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], r'^!random\s+(.*)$',
|
||
self.handle_random, -20)
|
||
|
||
super(Dice, self).start()
|
||
|
||
def stop(self):
|
||
"""Tear down handlers."""
|
||
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_roll)
|
||
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_random)
|
||
|
||
super(Dice, self).stop()
|
||
|
||
def handle_cypher_roll(self, connection, event, match):
|
||
"""Handle the !cypher roll."""
|
||
nick = NickMask(event.source).nick
|
||
task = match.group(1)
|
||
|
||
task_group = re.search(CYPHER_ROLL_REGEX, task)
|
||
difficulty = int(task_group.group('difficulty')) if task_group.group('difficulty') else None
|
||
mods = task_group.group('mods')
|
||
comment = task_group.group('comment')
|
||
result, beats, success, effect = cypher_roll(difficulty=difficulty, mods=mods)
|
||
|
||
if success is not None:
|
||
if success:
|
||
if effect:
|
||
result_str = f"9succeeded, with {effect}!"
|
||
else:
|
||
result_str = "9succeeded!"
|
||
else:
|
||
if effect:
|
||
result_str = f"4failed, with {effect}!"
|
||
else:
|
||
result_str = "4failed."
|
||
else:
|
||
if effect:
|
||
result_str = f"beats a difficulty {beats} task, with {effect}!"
|
||
else:
|
||
result_str = f"beats a difficulty {beats} task."
|
||
|
||
if success is not None:
|
||
# show the adjusted difficulty
|
||
detail_str = f"14(d20={result} vs. diff. {difficulty}{mods})"
|
||
else:
|
||
detail_str = f"14(d20={result} with {mods} levels)"
|
||
|
||
if comment:
|
||
return self.bot.reply(event, f"{nick}: {comment} {result_str} {detail_str}")
|
||
else:
|
||
return self.bot.reply(event, f"{nick}: your check {result_str} {detail_str}")
|
||
|
||
def handle_random(self, connection, event, match):
|
||
"""Handle the !random command which picks an item from a list."""
|
||
nick = NickMask(event.source).nick
|
||
choices = match.group(1)
|
||
|
||
choices_list = choices.split(' ')
|
||
choice = random.SystemRandom().choice(choices_list)
|
||
|
||
logger.debug(event.recursing)
|
||
if event.recursing:
|
||
reply = "{0:s}".format(choice)
|
||
elif settings.DICE_PREFIX_ROLLER:
|
||
reply = "{0:s}: {1:s}".format(nick, choice)
|
||
else:
|
||
reply = "{0:s}".format(choice)
|
||
return self.bot.reply(event, reply)
|
||
|
||
def handle_roll(self, connection, event, match):
|
||
"""Handle the !roll command which covers most common dice stuff."""
|
||
nick = NickMask(event.source).nick
|
||
dicestr = match.group(1)
|
||
|
||
logger.debug(event.recursing)
|
||
try:
|
||
reply_str = self.roller.do_roll(dicestr)
|
||
except AssertionError as aex:
|
||
reply_str = f"Could not roll dice: {aex}"
|
||
except ValueError:
|
||
reply_str = "Unable to parse roll"
|
||
|
||
if event.recursing:
|
||
reply = "{0:s}".format(reply_str)
|
||
elif settings.DICE_PREFIX_ROLLER:
|
||
reply = "{0:s}: {1:s}".format(nick, reply_str)
|
||
else:
|
||
reply = "{0:s}".format(reply_str)
|
||
return self.bot.reply(event, re.sub(r'(\d+)(.*?\s+)(\(.*?\))', r'\1\214\3', reply))
|
||
|
||
|
||
plugin = Dice
|