#!/bin/env python
import botlib
from time import sleep
from random import randint, choice, shuffle
import re
from copy import copy
NAME = "dee"
MAN = 'https://aleteoryx.me/deeman.md'
### "AI" ###
def send(msg):
global NAME
botlib.send(f'{NAME}: {msg}')
def act(what):
global NAME
botlib.send(f'{NAME} {msg}')
def help(nick):
global MAN
send(f'{nick}, my help is at {MAN}')
last_cmd = ('dee, roll d6', ['dee,', 'roll', 'd6'], ['dee', 'roll', 'd6'])
def handle_msg(nick, line, words, pwords):
global NAME, MAN, last_cmd
print(nick, line, words, pwords)
og_data = copy(line), copy(words), copy(pwords)
if not botlib.strip_direct_address(NAME, [], words, pwords):
return
cmd = pwords[0]
if cmd == 'again':
return handle_msg(nick, *map(copy, last_cmd))
else:
last_cmd = og_data
pwords.pop(0)
words.pop(0)
if cmd == 'help':
help(nick)
elif cmd not in ('roll', 'pick', 'shuf', 'shuffle'):
send(f'{nick}, I don\'t know how to do that! My help is at {MAN}')
elif len(pwords) < 1:
send(f'{nick}, {cmd} what?')
elif cmd == 'roll':
dice(nick, words, pwords)
elif cmd == 'pick':
pick(nick, words, pwords)
elif cmd in ('shuf', 'shuffle'):
shuf(nick, words, pwords)
def handle_action(line, words, pwords):
pass
### CHOICES, CHOICES ###
def pick(nick, words, pwords):
terms = botlib.split_list(words, pwords)
picked = choice(terms)
send(f'{nick}, how about {" ".join(picked)}?')
def shuf(nick, words, pwords):
terms = botlib.split_list(words, pwords)
shuffle(terms)
send(f'{nick}: {", ".join(map(" ".join, terms))}')
### DICE ###
class DiceParseException(Exception):
pass
def parse_number(word):
return int(word)
'''
dice = 'then'? spec offset?
spec = 'another' num? 'more'?
spec = 'another'? num? 'more'? size
spec = 'another'? num 'more'
size = 'd' num
offset = op num
op = 'plus' | 'minus' | '+' | '-'
num = int() or human-readable number
'''
last_dice = 6
last_line = ['1', 'd6']
def parse_dice(nick, words):
global last_dice, last_line
if words[0] == 'then':
words.pop(0)
if len(words) == 0:
return 0, 0, 0
if words[0] == 'again':
return parse_dice(nick, last_line)
else:
last_line = copy(words)
has_another = False
if words[0] == 'another':
has_another = True
words.pop(0)
if len(words) == 0:
return 1, last_dice, 0
can_more = True
try:
count = parse_number(words[0])
words.pop(0)
except (IndexError, ValueError):
count = 1
can_more = False
if len(words) == 0:
if has_another:
return count, last_dice, 0
else:
raise DiceParseException(f'roll {count} what?')
if d := re.match('d([0-9]+|[A-Za-z]+)', words[0]):
last_dice = parse_number(d.group(1))
words.pop(0)
if len(words) > 0 and words[0] == 'more':
words.pop(0)
if len(words) == 0:
return count, last_dice, 0
elif words[0] == 'more':
if not can_more:
raise DiceParseException(f'roll how many more d{last_dice}?')
words.pop(0)
if len(words) == 0:
return count, last_dice, 0
if words[0] in ('plus', 'add', '+', 'minus', 'sub', 'subtract', '-'):
try:
offset = parse_number(words[1])
except (IndexError, ValueError):
raise DiceParseException(f'roll {count} d{last_dice} {words[0]} what?')
if words[0] not in ('plus', 'add', '+'):
offset *= -1
return count, last_dice, offset
raise DiceParseException(f'I don\'t know how to roll that!')
def dice(nick, words, pwords):
result = nick
terms = botlib.split_list(words, pwords)
print(f'{terms=}')
for term in terms:
try:
count, size, offset = parse_dice(nick, term)
except DiceParseException as e:
send(f'{nick}, {e.args[0]}')
return
if count == 0:
continue
if count > 50:
send(f'{nick}, roll them yourself!')
return
rollsum = offset
# string formatting
if count == 1:
result += f', 1 d{size}'
else:
result += f', {count} d{size}s'
if offset > 0:
offset = f' + {offset}'
elif offset < 0:
offset = f' - {-offset}'
else:
offset = ''
result += f'{offset}:'
for i in range(count):
if size < 1:
roll = size
else:
roll = randint(1, size)
rollsum += roll
if i > 0:
result += f' + {roll}'
else:
result += f' {roll}'
if count > 1 or offset != '':
result += f'{offset} = {rollsum}'
if size == 0:
result += ', obviously'
if result == nick:
send(f'{nick}, done, i guess')
elif len(result) < 100:
send(result)
else:
send(f'{nick}, roll them yourself!')
### BOOT ###
botlib.parse_args()
while True:
sleep(5)
botlib.writeln(f"SKIP {botlib.lastmsg}")
lines = botlib.readmany()
for line in lines:
print(line)
botlib.handle_line(line, NAME, handle_msg, handle_action)