Compare commits
5 Commits
d0cbc815d1
...
6d8ba18380
Author | SHA1 | Date | |
---|---|---|---|
6d8ba18380 | |||
3b7c871a94 | |||
fa4815153a | |||
cc9b110531 | |||
af4746fb90 |
@ -13,7 +13,7 @@ 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_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 + ')'
|
||||
|
||||
|
||||
@ -49,11 +49,12 @@ class Dice(Plugin):
|
||||
nick = NickMask(event.source).nick
|
||||
task = match.group(1)
|
||||
|
||||
task_group = re.search(CYPHER_ROLL_REGEX, task)
|
||||
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)
|
||||
result, beats, success, effect = cypher_roll(difficulty=difficulty, mods=mods, is_attack=is_attack)
|
||||
|
||||
if success is not None:
|
||||
if success:
|
||||
@ -76,12 +77,13 @@ class Dice(Plugin):
|
||||
# show the adjusted difficulty
|
||||
detail_str = f"14(d20={result} vs. diff. {difficulty}{mods})"
|
||||
else:
|
||||
detail_str = f"14(d20={result} with {mods} levels)"
|
||||
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:
|
||||
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):
|
||||
"""Handle the !random command which picks an item from a list."""
|
||||
|
@ -6,12 +6,13 @@ import numexpr
|
||||
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.
|
||||
|
||||
Args:
|
||||
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')
|
||||
is_attack: if the roll is an attack (in which case the damage-only effects are included)
|
||||
Returns:
|
||||
tuple of:
|
||||
- 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')
|
||||
|
||||
effect = None
|
||||
if roll == 17:
|
||||
if roll == 17 and is_attack:
|
||||
effect = '+1 damage'
|
||||
elif roll == 18:
|
||||
elif roll == 18 and is_attack:
|
||||
effect = '+2 damage'
|
||||
elif roll == 19:
|
||||
effect = 'a minor effect'
|
||||
|
@ -1,14 +1,13 @@
|
||||
"""Karma logging models."""
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
import pytz
|
||||
|
||||
from irc.client import NickMask
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from irc.client import NickMask
|
||||
|
||||
log = logging.getLogger('karma.models')
|
||||
|
||||
@ -44,12 +43,13 @@ class KarmaKey(models.Model):
|
||||
objects = KarmaKeyManager()
|
||||
|
||||
def __str__(self):
|
||||
"""String representation."""
|
||||
"""Display the karma key and score."""
|
||||
return "{0:s} ({1:d})".format(self.key, self.score())
|
||||
|
||||
def score(self):
|
||||
"""Determine the score for this karma entry."""
|
||||
return KarmaLogEntry.objects.filter(key=self).aggregate(models.Sum('delta'))['delta__sum']
|
||||
score = KarmaLogEntry.objects.filter(key=self).aggregate(models.Sum('delta'))['delta__sum']
|
||||
return score if score else 0
|
||||
|
||||
def rank(self):
|
||||
"""Determine the rank of this karma entry relative to the others."""
|
||||
|
18
markov/migrations/0010_markovcontext_web_enabled.py
Normal file
18
markov/migrations/0010_markovcontext_web_enabled.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.9 on 2024-11-14 15:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('markov', '0009_alter_markovcontext_id_alter_markovstate_id_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='markovcontext',
|
||||
name='web_enabled',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
@ -12,6 +12,7 @@ class MarkovContext(models.Model):
|
||||
"""Define contexts for Markov chains."""
|
||||
|
||||
name = models.CharField(max_length=200, unique=True)
|
||||
web_enabled = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
"""Provide string representation."""
|
||||
|
@ -3,6 +3,7 @@ import json
|
||||
import logging
|
||||
import time
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from rest_framework.authentication import BasicAuthentication
|
||||
@ -27,6 +28,8 @@ def context_index(request, context_id):
|
||||
|
||||
start_t = time.time()
|
||||
context = get_object_or_404(MarkovContext, pk=context_id)
|
||||
if not context.web_enabled:
|
||||
raise PermissionDenied()
|
||||
chain = " ".join(markovlib.generate_line(context))
|
||||
end_t = time.time()
|
||||
|
||||
|
@ -26,23 +26,57 @@ class MarkovTestCase(TestCase):
|
||||
def test_cypher_roll_strings(self):
|
||||
"""Simulate incoming Cypher System requests."""
|
||||
mock_event = mock.MagicMock()
|
||||
mock_event.arguments = ['!cypher T3']
|
||||
mock_event.source = 'test!test@test'
|
||||
mock_event.target = '#test'
|
||||
mock_event.recursing = False
|
||||
|
||||
match = re.search(dice.ircplugin.CYPHER_COMMAND_REGEX, '!cypher T3')
|
||||
# general task roll (no damage output on a 17)
|
||||
mock_event.arguments = ['!cypher T3']
|
||||
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 check 9succeeded, with +1 damage! 14(d20=17 vs. diff. 3)'
|
||||
'test: your check 9succeeded! 14(d20=17 vs. diff. 3)'
|
||||
)
|
||||
|
||||
match = re.search(dice.ircplugin.CYPHER_COMMAND_REGEX, '!cypher +1')
|
||||
# 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 check beats a difficulty 4 task, with +1 damage! 14(d20=17 with +1 levels)'
|
||||
'test: your attack 9succeeded, with +1 damage! 14(d20=17 vs. diff. 3)'
|
||||
)
|
||||
|
||||
# general task roll, case insensitive
|
||||
mock_event.arguments = ['!cypher t3']
|
||||
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 check 9succeeded! 14(d20=17 vs. diff. 3)'
|
||||
)
|
||||
|
||||
# unknown target roll
|
||||
mock_event.arguments = ['!cypher +1']
|
||||
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 check beats a difficulty 4 task. 14(d20=17 with +1 levels)'
|
||||
)
|
||||
|
||||
# no mod or known difficulty
|
||||
mock_event.arguments = ['!cypher unmodded attempt']
|
||||
match = re.search(dice.ircplugin.CYPHER_COMMAND_REGEX, mock_event.arguments[0])
|
||||
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
||||
with mock.patch('random.SystemRandom.randint', return_value=9):
|
||||
self.plugin.handle_cypher_roll(self.mock_connection, mock_event, match)
|
||||
self.mock_bot.reply.assert_called_with(
|
||||
mock_event,
|
||||
'test: unmodded attempt beats a difficulty 3 task. 14(d20=9)'
|
||||
)
|
||||
|
@ -26,15 +26,25 @@ class DiceLibTestCase(TestCase):
|
||||
result = dice.lib.cypher_roll(difficulty=1)
|
||||
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
|
||||
with mock.patch('random.SystemRandom.randint', return_value=17):
|
||||
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
|
||||
with mock.patch('random.SystemRandom.randint', return_value=18):
|
||||
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
|
||||
with mock.patch('random.SystemRandom.randint', return_value=19):
|
||||
|
Loading…
x
Reference in New Issue
Block a user