feat: complete roll command
This commit is contained in:
parent
74f991af40
commit
3ab4e424a1
2 changed files with 120 additions and 10 deletions
102
dice.py
102
dice.py
|
|
@ -1,18 +1,40 @@
|
|||
from random import randint
|
||||
|
||||
from pyparsing import Combine, OpAssoc, Word, infix_notation, nums, one_of
|
||||
from pyparsing import Combine, OpAssoc, ParseResults, Word, infix_notation, nums, one_of
|
||||
|
||||
SEPARATOR = "|"
|
||||
|
||||
|
||||
class Dice:
|
||||
class Realizable:
|
||||
pass
|
||||
|
||||
|
||||
class Integer(Realizable):
|
||||
def __init__(self, tokens):
|
||||
self.value = int(tokens[0])
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
||||
def realize(self):
|
||||
return [self.value]
|
||||
|
||||
|
||||
class Dice(Realizable):
|
||||
def __init__(self, tokens):
|
||||
split_tokens = tokens[0].split(SEPARATOR)
|
||||
self.dice, self.faces = split_tokens[0], split_tokens[2]
|
||||
self.dice, self.faces = int(split_tokens[0]), int(split_tokens[2])
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.dice}d{self.faces}"
|
||||
|
||||
def realize(self):
|
||||
rolls = [randint(1, self.faces) for _ in range(self.dice)]
|
||||
return rolls
|
||||
|
||||
|
||||
def roll_parse(roll):
|
||||
integer = Word(nums)
|
||||
integer = Word(nums).set_parse_action(Integer)
|
||||
dice = Combine(integer + "d" + integer, join_string="|")
|
||||
dice.set_parse_action(Dice)
|
||||
|
||||
|
|
@ -28,7 +50,75 @@ def roll_parse(roll):
|
|||
return expr.parse_string(roll, parse_all=True)
|
||||
|
||||
|
||||
def realize(expr):
|
||||
if isinstance(expr, ParseResults):
|
||||
return list(map(realize, expr))
|
||||
elif isinstance(expr, Realizable):
|
||||
return expr.realize()
|
||||
elif isinstance(expr, str):
|
||||
return expr
|
||||
else:
|
||||
raise ValueError(f"{expr} has an unexpected type in realization")
|
||||
|
||||
|
||||
def pstr_expr(expr):
|
||||
if isinstance(expr, Realizable):
|
||||
return str(expr)
|
||||
elif isinstance(expr, list) and all(map(lambda e: isinstance(e, int), expr)):
|
||||
return "/".join(map(str, expr))
|
||||
elif isinstance(expr, str):
|
||||
return expr
|
||||
elif isinstance(expr, list) and len(expr) == 1:
|
||||
return pstr_expr(expr[0])
|
||||
elif isinstance(expr, ParseResults) or isinstance(expr, list):
|
||||
return " ".join(map(pstr_expr, expr))
|
||||
else:
|
||||
raise ValueError(f"{expr} has an unexpected type in pstr_expr")
|
||||
|
||||
|
||||
def eval_op(op):
|
||||
if op == "+":
|
||||
return int.__add__
|
||||
elif op == "*":
|
||||
return int.__mul__
|
||||
elif op == "-":
|
||||
return int.__sub__
|
||||
elif op == "/":
|
||||
return int.__floordiv__
|
||||
elif op == "%":
|
||||
return int.__mod__
|
||||
raise ValueError(f"Unknown {op} operator in eval_op")
|
||||
|
||||
|
||||
def compute(rexpr):
|
||||
if isinstance(rexpr, Realizable):
|
||||
raise ValueError(f"{rexpr} should already be realized")
|
||||
elif isinstance(rexpr, int):
|
||||
return rexpr
|
||||
elif isinstance(rexpr, list) and all(map(lambda e: isinstance(e, int), rexpr)):
|
||||
return sum(rexpr)
|
||||
elif isinstance(rexpr, list) and len(rexpr) == 1:
|
||||
return compute(rexpr[0])
|
||||
elif isinstance(rexpr, list):
|
||||
if len(rexpr) % 2 == 0:
|
||||
raise ValueError(
|
||||
f"{rexpr} should be an infix expression with an odd number of elements"
|
||||
)
|
||||
total = compute(rexpr[0])
|
||||
for i in range(1, len(rexpr), 2):
|
||||
op = eval_op(rexpr[i])
|
||||
total = op(total, compute(rexpr[i + 1]))
|
||||
return total
|
||||
else:
|
||||
raise ValueError(f"{rexpr} has an unexpected type in compute")
|
||||
|
||||
|
||||
async def roll(bot, mtch, room, message):
|
||||
await bot.api.send_text_message(
|
||||
room.room_id, str(roll_parse(" ".join(mtch.args())))
|
||||
expr = roll_parse(" ".join(mtch.args()))
|
||||
rexpr = realize(expr)
|
||||
value = compute(rexpr)
|
||||
await bot.api.send_markdown_message(
|
||||
room.room_id,
|
||||
"> " + pstr_expr(rexpr) + "\n\n" + str(value),
|
||||
reply_to=message.event_id,
|
||||
)
|
||||
|
|
|
|||
28
main.py
28
main.py
|
|
@ -26,21 +26,36 @@ bot.start_time = datetime.now()
|
|||
async def ping(room, message):
|
||||
mtch = matrix.match.MessageMatch(room, message, bot, PREFIX)
|
||||
if mtch.is_not_from_this_bot and mtch.prefix and mtch.command("ping"):
|
||||
await misc.ping(bot, mtch, room, message)
|
||||
try:
|
||||
await misc.ping(bot, mtch, room, message)
|
||||
except Exception as e:
|
||||
await bot.api.send_text_message(
|
||||
room.room_id, f"Unexpected error: {e}", reply_to=message.event_id
|
||||
)
|
||||
|
||||
|
||||
@bot.listener.on_message_event
|
||||
async def echo(room, message):
|
||||
mtch = matrix.match.MessageMatch(room, message, bot, PREFIX)
|
||||
if mtch.is_not_from_this_bot and mtch.prefix and mtch.command("echo"):
|
||||
await misc.echo(bot, mtch, room, message)
|
||||
try:
|
||||
await misc.echo(bot, mtch, room, message)
|
||||
except Exception as e:
|
||||
await bot.api.send_text_message(
|
||||
room.room_id, f"Unexpected error: {e}", reply_to=message.event_id
|
||||
)
|
||||
|
||||
|
||||
@bot.listener.on_message_event
|
||||
async def uptime(room, message):
|
||||
mtch = matrix.match.MessageMatch(room, message, bot, PREFIX)
|
||||
if mtch.is_not_from_this_bot and mtch.prefix and mtch.command("uptime"):
|
||||
await misc.uptime(bot, mtch, room, message)
|
||||
try:
|
||||
await misc.uptime(bot, mtch, room, message)
|
||||
except Exception as e:
|
||||
await bot.api.send_text_message(
|
||||
room.room_id, f"Unexpected error: {e}", reply_to=message.event_id
|
||||
)
|
||||
|
||||
|
||||
@bot.listener.on_message_event
|
||||
|
|
@ -51,7 +66,12 @@ async def roll(room, message):
|
|||
and mtch.prefix
|
||||
and (mtch.command("roll") or mtch.command("r"))
|
||||
):
|
||||
await dice.roll(bot, mtch, room, message)
|
||||
try:
|
||||
await dice.roll(bot, mtch, room, message)
|
||||
except Exception as e:
|
||||
await bot.api.send_text_message(
|
||||
room.room_id, f"Unexpected error: {e}", reply_to=message.event_id
|
||||
)
|
||||
|
||||
|
||||
bot.run()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue