Вот более продвинутое решение, использующее библиотеку с именем lark
для определения грамматики для этих выражений кубиков (взято из this question ), проанализируйте эти выражения в синтаксических деревьях, затем оценить эти деревья. Создайте файл с именем dice_grammar.py
с этой строкой:
grammar="""
start: _expr
_expr: add
| subtract
| roll
| NUMBER
add: _expr "+" _expr
subtract: _expr "-" _expr
roll: [NUMBER] ("d"|"D") (NUMBER|PERCENT)
NUMBER: ("0".."9")+
PERCENT: "%"
%ignore " "
"""
Если вы не знакомы с такими грамматиками, не панируйте c. Все это показывает, что мы можем бросать кости, складывать и вычитать. Тогда у нас может быть dice_transformer.py
для использования деревьев, которые будет генерировать синтаксический анализатор:
from lark import Transformer, v_args
from random import randint
class DiceTransformer(Transformer):
PERCENT = lambda self, percent: 100
NUMBER = int
def __init__(self):
super().__init__(visit_tokens=True)
@v_args(inline=True)
def start(self, expr):
return expr
@v_args(inline=True)
def add(self, left, right):
return left + right
@v_args(inline=True)
def subtract(self, left, right):
return left - right
@v_args(inline=True)
def roll(self, qty, size):
qty = qty or 1
return sum(randint(1, size) for _ in range(qty))
и dice_bot.py
, который использует их для оценки выражений кости от пользователя:
from discord.ext import commands
from lark import Lark
from lark.exceptions import LarkError
from dice_grammar import grammar
from dice_transformer import DiceTransformer
bot = commands.Bot(";")
parser = Lark(grammar, maybe_placeholders=True)
transformer = DiceTransformer()
@bot.command()
async def roll(ctx, *, expression):
try:
tree = parser.parse(expression)
except LarkError:
await ctx.send("Bad Expression")
return
print(tree.pretty()) # Log the roll
result = transformer.transform(tree)
await ctx.send(f"You rolled: {result}")
bot.run("token")
Это позволяет нам запрашивать вычисление более сложных бросков, таких как
;roll 2d6 +7 + d% - 3d4
. По совету Эреза в комментариях я изменил свой ответ на использование lark.Transformer
. Вы должны увидеть мой оригинальный код в истории редактирования этого ответа.