cypher: distinguish between a task roll and an attack roll
attack = A, otherwise the same options as with a generic task (= T) Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
This commit is contained in:
parent
3b7c871a94
commit
6d8ba18380
@ -13,7 +13,7 @@ from ircbot.lib import Plugin
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
CYPHER_ROLL_REGEX = r'(T(?P<difficulty>\d+))?(?P<mods>(?:\s*(-|\+)\d+)*)\s*(?P<comment>.*)?'
|
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 + ')'
|
CYPHER_COMMAND_REGEX = r'^!cypher\s+(' + CYPHER_ROLL_REGEX + ')'
|
||||||
|
|
||||||
|
|
||||||
@ -52,8 +52,9 @@ class Dice(Plugin):
|
|||||||
task_group = re.search(CYPHER_ROLL_REGEX, task, re.IGNORECASE)
|
task_group = re.search(CYPHER_ROLL_REGEX, task, re.IGNORECASE)
|
||||||
difficulty = int(task_group.group('difficulty')) if task_group.group('difficulty') else None
|
difficulty = int(task_group.group('difficulty')) if task_group.group('difficulty') else None
|
||||||
mods = task_group.group('mods')
|
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')
|
comment = task_group.group('comment')
|
||||||
result, beats, success, effect = cypher_roll(difficulty=difficulty, mods=mods)
|
result, beats, success, effect = cypher_roll(difficulty=difficulty, mods=mods, is_attack=is_attack)
|
||||||
|
|
||||||
if success is not None:
|
if success is not None:
|
||||||
if success:
|
if success:
|
||||||
@ -81,7 +82,8 @@ class Dice(Plugin):
|
|||||||
if comment:
|
if comment:
|
||||||
return self.bot.reply(event, f"{nick}: {comment} {result_str} {detail_str}")
|
return self.bot.reply(event, f"{nick}: {comment} {result_str} {detail_str}")
|
||||||
else:
|
else:
|
||||||
return self.bot.reply(event, f"{nick}: your check {result_str} {detail_str}")
|
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):
|
def handle_random(self, connection, event, match):
|
||||||
"""Handle the !random command which picks an item from a list."""
|
"""Handle the !random command which picks an item from a list."""
|
||||||
|
@ -6,12 +6,13 @@ import numexpr
|
|||||||
rand = random.SystemRandom()
|
rand = random.SystemRandom()
|
||||||
|
|
||||||
|
|
||||||
def cypher_roll(difficulty=None, mods=0):
|
def cypher_roll(difficulty=None, mods=0, is_attack=False):
|
||||||
"""Make a Cypher System roll.
|
"""Make a Cypher System roll.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
difficulty: the original difficulty to beat; if provided, success or failure is indicated in the results
|
difficulty: the original difficulty to beat; if provided, success or failure is indicated in the results
|
||||||
mods: eases(-) and hindrances(+) to apply to the check, as a string (e.g. '-3+1')
|
mods: eases(-) and hindrances(+) to apply to the check, as a string (e.g. '-3+1')
|
||||||
|
is_attack: if the roll is an attack (in which case the damage-only effects are included)
|
||||||
Returns:
|
Returns:
|
||||||
tuple of:
|
tuple of:
|
||||||
- the result on the d20
|
- the result on the d20
|
||||||
@ -24,9 +25,9 @@ def cypher_roll(difficulty=None, mods=0):
|
|||||||
return (roll, None, False if difficulty else None, 'a GM intrusion')
|
return (roll, None, False if difficulty else None, 'a GM intrusion')
|
||||||
|
|
||||||
effect = None
|
effect = None
|
||||||
if roll == 17:
|
if roll == 17 and is_attack:
|
||||||
effect = '+1 damage'
|
effect = '+1 damage'
|
||||||
elif roll == 18:
|
elif roll == 18 and is_attack:
|
||||||
effect = '+2 damage'
|
effect = '+2 damage'
|
||||||
elif roll == 19:
|
elif roll == 19:
|
||||||
effect = 'a minor effect'
|
effect = 'a minor effect'
|
||||||
|
@ -30,14 +30,24 @@ class MarkovTestCase(TestCase):
|
|||||||
mock_event.target = '#test'
|
mock_event.target = '#test'
|
||||||
mock_event.recursing = False
|
mock_event.recursing = False
|
||||||
|
|
||||||
# general task roll
|
# general task roll (no damage output on a 17)
|
||||||
mock_event.arguments = ['!cypher T3']
|
mock_event.arguments = ['!cypher T3']
|
||||||
match = re.search(dice.ircplugin.CYPHER_COMMAND_REGEX, mock_event.arguments[0])
|
match = re.search(dice.ircplugin.CYPHER_COMMAND_REGEX, mock_event.arguments[0])
|
||||||
with mock.patch('random.SystemRandom.randint', return_value=17):
|
with mock.patch('random.SystemRandom.randint', return_value=17):
|
||||||
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
||||||
self.mock_bot.reply.assert_called_with(
|
self.mock_bot.reply.assert_called_with(
|
||||||
mock_event,
|
mock_event,
|
||||||
'test: your check 9succeeded, with +1 damage! 14(d20=17 vs. diff. 3)'
|
'test: your check 9succeeded! 14(d20=17 vs. diff. 3)'
|
||||||
|
)
|
||||||
|
|
||||||
|
# general attack roll (incl. damage output on a 17)
|
||||||
|
mock_event.arguments = ['!cypher A3']
|
||||||
|
match = re.search(dice.ircplugin.CYPHER_COMMAND_REGEX, mock_event.arguments[0])
|
||||||
|
with mock.patch('random.SystemRandom.randint', return_value=17):
|
||||||
|
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
||||||
|
self.mock_bot.reply.assert_called_with(
|
||||||
|
mock_event,
|
||||||
|
'test: your attack 9succeeded, with +1 damage! 14(d20=17 vs. diff. 3)'
|
||||||
)
|
)
|
||||||
|
|
||||||
# general task roll, case insensitive
|
# general task roll, case insensitive
|
||||||
@ -47,7 +57,7 @@ class MarkovTestCase(TestCase):
|
|||||||
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
||||||
self.mock_bot.reply.assert_called_with(
|
self.mock_bot.reply.assert_called_with(
|
||||||
mock_event,
|
mock_event,
|
||||||
'test: your check 9succeeded, with +1 damage! 14(d20=17 vs. diff. 3)'
|
'test: your check 9succeeded! 14(d20=17 vs. diff. 3)'
|
||||||
)
|
)
|
||||||
|
|
||||||
# unknown target roll
|
# unknown target roll
|
||||||
@ -57,7 +67,7 @@ class MarkovTestCase(TestCase):
|
|||||||
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
||||||
self.mock_bot.reply.assert_called_with(
|
self.mock_bot.reply.assert_called_with(
|
||||||
mock_event,
|
mock_event,
|
||||||
'test: your check beats a difficulty 4 task, with +1 damage! 14(d20=17 with +1 levels)'
|
'test: your check beats a difficulty 4 task. 14(d20=17 with +1 levels)'
|
||||||
)
|
)
|
||||||
|
|
||||||
# no mod or known difficulty
|
# no mod or known difficulty
|
||||||
|
@ -26,15 +26,25 @@ class DiceLibTestCase(TestCase):
|
|||||||
result = dice.lib.cypher_roll(difficulty=1)
|
result = dice.lib.cypher_roll(difficulty=1)
|
||||||
self.assertEqual(result, (1, None, False, 'a GM intrusion'))
|
self.assertEqual(result, (1, None, False, 'a GM intrusion'))
|
||||||
|
|
||||||
|
# rolled a 17 on an attack
|
||||||
|
with mock.patch('random.SystemRandom.randint', return_value=17):
|
||||||
|
result = dice.lib.cypher_roll(difficulty=1, is_attack=True)
|
||||||
|
self.assertEqual(result, (17, 5, True, '+1 damage'))
|
||||||
|
|
||||||
|
# rolled a 18 on an attack
|
||||||
|
with mock.patch('random.SystemRandom.randint', return_value=18):
|
||||||
|
result = dice.lib.cypher_roll(difficulty=1, is_attack=True)
|
||||||
|
self.assertEqual(result, (18, 6, True, '+2 damage'))
|
||||||
|
|
||||||
# rolled a 17
|
# rolled a 17
|
||||||
with mock.patch('random.SystemRandom.randint', return_value=17):
|
with mock.patch('random.SystemRandom.randint', return_value=17):
|
||||||
result = dice.lib.cypher_roll(difficulty=1)
|
result = dice.lib.cypher_roll(difficulty=1)
|
||||||
self.assertEqual(result, (17, 5, True, '+1 damage'))
|
self.assertEqual(result, (17, 5, True, None))
|
||||||
|
|
||||||
# rolled a 18
|
# rolled a 18
|
||||||
with mock.patch('random.SystemRandom.randint', return_value=18):
|
with mock.patch('random.SystemRandom.randint', return_value=18):
|
||||||
result = dice.lib.cypher_roll(difficulty=1)
|
result = dice.lib.cypher_roll(difficulty=1)
|
||||||
self.assertEqual(result, (18, 6, True, '+2 damage'))
|
self.assertEqual(result, (18, 6, True, None))
|
||||||
|
|
||||||
# rolled a 19
|
# rolled a 19
|
||||||
with mock.patch('random.SystemRandom.randint', return_value=19):
|
with mock.patch('random.SystemRandom.randint', return_value=19):
|
||||||
|
Loading…
Reference in New Issue
Block a user