【问题标题】:Adding or Subtracting a number from a randomly generated number从随机生成的数字中添加或减去数字
【发布时间】:2020-07-20 02:57:25
【问题描述】:

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

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)生成的骰子。逻辑看起来像这样

-user ";1d20+2" 假设生成的随机数是 6。由于用户想在我们生成的随机数上加 2,结果是 8。

-bot "你掷出 8"

# 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")
        else:
            if message.content == "-":

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

感谢任何帮助!

【问题讨论】:

    标签: python-3.x bots discord.py dice


    【解决方案1】:

    这是一个更高级的解决方案,它使用名为 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 " "
    """
    

    如果您不熟悉此类语法,请不要惊慌。所有这一切都表明我们可以掷骰子、加法和减法。然后我们可以使用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
    

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

    【讨论】:

    • 我遵循了每一步,但是当我输入“;roll 2d6 +7 + d% - 3d4”时,机器人没有响应。但是它确实响应命令,例如我所做的 ;roll 1d20 命令。控制台中没有错误,我的代码中没有任何语法错误。我是否必须通过 PyCharm 同时运行两个单独的文件才能正常工作?
    • -scratch this comment- 将最后一段代码放入自己单独的脚本后,代码似乎可以工作了。可能不得不摆弄它才能让它在我自己的脚本中工作,非常感谢!
    • 如果您有 on_message 事件,请确保它包含 bot.process_commands(message) 行
    • 您应该为您的bot.command 命令和您在on_message 中定义的命令使用不同的前缀。每次您的机器人看到命令前缀(我们定义为 ;)时,它都会假定有人正在尝试调用命令。您也可以将process_commands 放在on_message 的末尾,这样即使失败,您的其他代码也会先执行
    • 如果你使用 Lark 的转换器来评估树,你的代码会干净很多。 from lark import Transformer。有关文档,请参见此处:lark-parser.readthedocs.io/en/latest/visitors
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多