Python 3.x 从随机生成的数字中加减一个数字

Python 3.x 从随机生成的数字中加减一个数字,python-3.x,bots,discord.py,dice,Python 3.x,Bots,Discord.py,Dice,我正在尝试在我的程序中实现一个功能,用户可以使用一个特定的边模来添加或减去随机生成的数字。我的代码的基础放在这里: import discord import random DND_1d20 = range(1, 21) # Roll d20 if message.content == ";roll 1d20": response = random.choice(DND_1d20) response_str = "You rolled {0}".for

我正在尝试在我的程序中实现一个功能,用户可以使用一个特定的边模来添加或减去随机生成的数字。我的代码的基础放在这里:

import discord
import random

DND_1d20 = range(1, 21)

# Roll d20
    if message.content == ";roll 1d20":
        response = random.choice(DND_1d20)
        response_str = "You rolled {0}".format(response)
        if response_str == "You rolled 20":
            await message.channel.send("**Critical Hit!**\n You rolled 20")
        if response_str == "You rolled 1":
            await message.channel.send("**Critical Fail!**\n You rolled 1")
我希望用户能够指定骰子卷“1d20”,但也能够从生成的骰子卷中添加“1d20+(x)”或减去“1d20-(x)”任何数字(x)。逻辑应该是这样的

-用户“1d20+2”假设生成的随机数为6。由于用户希望在我们生成的随机数上加2,结果将是8

-机器人“你滚了8”

我该怎么做呢?我真的不知道从哪里开始。我不认为上面的代码是正确的,因为消息必须是一个“-”。 另外,我如何合并值(x),因为它可能是一个庞大的数字数组,或者是用户输入的+/-符号


感谢您的帮助

这里有一个更高级的解决方案,使用一个名为的库为这些骰子表达式定义语法(抄袭自),将这些表达式解析为语法树,然后对这些树求值。使用以下字符串创建一个名为
dice\u 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 " "
"""
如果你不熟悉这样的语法,不要惊慌。这表明我们可以掷骰子,加和减。然后,我们可以使用
dice\u 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

根据Erez在评论中的建议,我将答案改为使用
lark.Transformer
。您应该能够在这个答案的编辑历史中看到我的原始代码

我遵循了每一步,但当我键入“roll 2d6+7+d%-3d4”时,机器人没有响应。但是,它确实响应命令,例如:;掷1d20,我已发出命令。控制台中没有错误,代码中也没有语法错误。我必须通过PyCharm同时运行这两个独立的文件才能工作吗?——划掉这个注释——在将最后一块代码放入它自己的独立脚本中之后,代码似乎工作了。我可能不得不用我自己的脚本来处理它,非常感谢!如果您有一个
on_message
事件,请确保它包含一个
bot.process_命令(message)
行您应该为
bot.command
命令和您在
on_message
中定义的命令使用不同的前缀。每次您的机器人看到命令前缀(我们定义为
)时,它都假定有人试图调用命令。您还可以在消息的
末尾添加
process\u命令
,这样即使其他代码先执行失败,如果您使用Lark的transformers来评估树,您的代码也会更干净<代码>来自lark进口变压器
。有关文档,请参见此处:
;roll 2d6 +7 + d% - 3d4