dr.botzo/dice/ircplugin.py
Brian S. Stephan 0d691ff431
tweak the green-ness of the middle !reaction result
Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
2025-02-24 16:48:30 -06:00

146 lines
5.7 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""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, reaction_roll
from dice.roller import DiceRoller
from ircbot.lib import Plugin
logger = logging.getLogger(__name__)
CYPHER_ROLL_REGEX = r'((?P<type>A|T)(?P<difficulty>\d+))?(?P<mods>(?:\s*(-|\+)\d+)*)\s*(?P<comment>.*)?'
CYPHER_COMMAND_REGEX = r'^!cypher\s+(' + CYPHER_ROLL_REGEX + ')'
REACTION_COMMAND_REGEX = r'^!reaction$'
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)
self.connection.reactor.add_global_regex_handler(['pubmsg', 'privmsg'], REACTION_COMMAND_REGEX,
self.handle_reaction_roll, -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)
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_cypher_roll)
self.connection.reactor.remove_global_regex_handler(['pubmsg', 'privmsg'], self.handle_reaction_roll)
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, re.IGNORECASE)
difficulty = int(task_group.group('difficulty')) if task_group.group('difficulty') else None
mods = task_group.group('mods')
is_attack = True if task_group.group('type') and task_group.group('type').upper() == 'A' else False
comment = task_group.group('comment')
result, beats, success, effect = cypher_roll(difficulty=difficulty, mods=mods, is_attack=is_attack)
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}{f' with {mods} levels' if mods else ''})"
if comment:
return self.bot.reply(event, f"{nick}: {comment} {result_str} {detail_str}")
else:
type_str = 'attack' if is_attack else 'check'
return self.bot.reply(event, f"{nick}: your {type_str} {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_reaction_roll(self, connection, event, match):
"""Handle the !reaction roll."""
nick = NickMask(event.source).nick
roll, label, summary = reaction_roll()
if summary in ('--', '-'):
result_str = f"4{label}"
elif summary == '~':
result_str = f"3{label}"
else:
result_str = f"9{label}"
return self.bot.reply(event, f"{nick}: the current disposition is {result_str} 14({roll})")
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