Discord.py D&D 掷骰子命令有太多问题

Posted

技术标签:

【中文标题】Discord.py D&D 掷骰子命令有太多问题【英文标题】:Discord.py D&D dice roll command has far too many issues 【发布时间】:2020-12-16 13:52:55 【问题描述】:

所以我所有的 D&D 党员都确信当前的骰子机器人是“被诅咒的”,所以我决定自己动手做我自己的机器人。这很酷,但我的掷骰子命令有多个问题。

我目前的命令是

async def d(ctx, die:int):
    for x in range(1):
        await ctx.send("<:d20:748302353375166614> "+str(random.randint(1,die)))

第一个问题是它使用格式“|d 20”而不是“|d20”,因此第一个请求将删除“d”和表示边数的 int 之间的空格die 会有(“die”变量,在本例中为“20”)。

除此之外,我想添加一个功能,如果输入“|[骰子数]d[边数]”,它'd 将请求的骰子滚动请求的次数。如果未指定骰子数量(例如:“|d20”),则应自动假定骰子数量为 1。机器人消息应包括所有掷出的数字及其总和。

例如“|2d20”可能返回“<:d20:748302353375166614>11 + 15 = 26”,而“|10d2”可能返回“<:d20:748302353375166614>1 + 1 + 2 + 1 + 2 + 2 + 2 + 1 + 1 + 2 = 15"

除此之外,我还希望能够为掷骰添加奖励(“|[骰子数]d[边数] em>+[bonus]") 并在机器人的消息中返回掷骰子、奖金和最终值。

例如“|d20+4”可能返回“<:d20:748302353375166614>11 + 4 = 15”,而“|2d10+2+3”可能返回“<:d20>9 + 4 + 2 + 3 = 18"

(可选地,如果痛苦地写下这个问题的答案的人觉得从这个请求的庞大规模来看他们还没有足够的痛苦,那么像“|1d4+2d6”这样的事情可以成为可能)

【问题讨论】:

您为实现目标做了哪些努力?如果你想删除一个空格,你传递的字符串中有一个空格文字 - 你试过删除它吗? SO 不是我们为您的问题提供即时代码解决方案的地方 就在这里这么说吧:D&D gooooo!和;您应该为骰子的所有 20 个面创建贴纸,并在滚动时让机器人张贴它们。会很棒.. @TheodorPeifer 目前我有 3 个表情,一个用于 nat 1,一个用于 nat 20,一个用于介于两者之间的所有表情,但我决定不使用它们,因为使用当前代码。我也有这个想法,首先,它只会发送一个 d20 滚动的动画表情,它只会在 2-3 秒后显示数字以产生悬念,但我也放弃了,因为此时我已经受够了我很高兴它能按预期工作。 【参考方案1】:

!roll 3d20+6d8+1 这样的格式呢?如果这是可以接受的,你可以这样做:

async def d(ctx, *args):
    dicestring = "".join(args)
    # Process dicestring here

这里,*args 是一个可变长度的参数说明符。解析命令的方式,!roll 5d6 + 6d12 会给你参数("5d6", "+", "6d12")!roll 5d6+6d12 会给你参数("5d6+6d12")

"".join(args) 将简单地将所有这些参数混合在一起,为您留下一个您可以随意解析的字符串。

如果唯一的前缀是 | 对您很重要,那么您尝试做的事情就不能很好地适应命令结构。我会考虑将其设为on_message 事件,例如https://discordpy.readthedocs.io/en/latest/api.html#discord-api-events。

【讨论】:

【参考方案2】:

使用commands 扩展,您无法摆脱命令和die 变量之间的空格。为了摆脱它,您必须使用 on_message 事件来解析您的命令内容:

from random import sample

@client.event
async def on_message(message):
    content = message.content
    if content.startswith('|') and (content[1].isdigit() or content[1]=='d'):
        content = content.split('+')
        rolls = [int(content.pop(i)) for i in range(len(content)) if content[i].isdigit()]
        for elem in content:
            n, faces = elem.split('d') if elem.split('d')[0] != '' else (1, elem[1:])
            rolls += [randint(1, int(faces)) for _ in range(int(n))]
        rolls_str = ' + '.join([str(n) for n in rolls]) 
        await message.channel.send(f"rolls_str = sum(rolls)")
    else:
        pass

    await client.process_commands(message)

【讨论】:

我非常感谢这条评论,但似乎出了点问题,日志如下:``` 2020-08-27T20:38:08.254349+00:00 app[worker.1]:文件“namegen.py”,第 21 行,在 2020-08-27T20:38:08.254521+00:00 app[worker.1]:@bot.event 2020-08-27T20:38:08.254546+00: 00 app[worker.1]: NameError: name 'bot' is not defined 2020-08-27T20:38:08.335175+00:00 heroku[worker.1]: Process exited with status 1 2020-08-27T20:38: 08.368578+00:00 heroku[worker.1]: 状态从 up to crashed ``` 我写了client = commands.Bot(command_prefix = "|") 所以你只需要用客户端替换 bot :) 好的,它工作得几乎完美,虽然它偶尔会滚动一个 0,所以当我有更多空闲时间时,我将不得不努力解决这个问题。谢谢。 它有效,对于那些在这里寻找答案的人来说,机器人现在只在请求 d20 时生成 1-19 的数字,但可以通过 @987654328 轻松修复@ 它也只允许骰子的数量是一个小于骰子边数的单位数,出于某种奇怪的原因,但这很好,我认为无论如何都不会有人滚动 21d20s。

以上是关于Discord.py D&D 掷骰子命令有太多问题的主要内容,如果未能解决你的问题,请参考以下文章

[leetcode 周赛 149] 1155 掷骰子的N种方法

我试图在 discord.py 中创建一个楼梯命令

模拟算法_掷骰子游戏&&猜数游戏

python 由用户输入掷多少次骰子,然后统计每个面出现的次数

我如何在不和谐中 ping 某人

如何在Unity 3D中掷骰子