如何为现有Discord骰子机器人实现仿Avrae的单次指令多枚骰子投掷功能?
实现多枚骰子投掷功能的完整方案
嘿,我明白你想把现有的骰子命令改成像Avrae那样支持一次投多枚的需求,这其实不难,咱们一步步来调整代码:
第一步:调整命令参数接收方式
原来的参数拆分不太适配多骰子格式,我们改成接收一个完整的骰子表达式字符串(比如5 d20或3d6),这样灵活性更高。把命令定义改成:
@client.command(aliases=['r', 'dado', 'dice']) async def roll(ctx, *, dice_str: str = 'd20'):
这里用*表示接收所有后续输入作为单个参数,默认值设为d20,方便用户直接输-r就能投1枚d20。
第二步:解析骰子表达式
用正则表达式来提取骰子数量和面数,不管用户输入5d20还是5 d20都能精准识别。添加匹配逻辑:
import re # 匹配格式:数字+d+数字,中间允许有空格 match = re.match(r'(\d*)\s*d(\d+)', dice_str.lower()) if not match: await ctx.send(f'{ctx.author.mention} ❌ 格式不对哦!请用类似 `-r 5 d20` 或 `-r 3d6` 的格式~') return # 提取数量和面数,没写数量默认投1枚 count = int(match.group(1)) if match.group(1) else 1 sides = int(match.group(2))
第三步:执行多枚骰子投掷
循环生成每个骰子的结果,同时保留你原来的暴击/大失败加粗效果:
rolls = [] total = 0 for _ in range(count): num = random.randint(1, sides) # 对1和当前骰子的最大面数加粗(如果是d20就保留1和20的特殊标记) if (sides == 20 and (num == 1 or num == 20)) or (num == 1 or num == sides): rolls.append(f'**{num}**') else: rolls.append(str(num)) total += num
第四步:格式化输出
按照你想要的样式拼接结果,清晰展示每枚骰子的数值和总和:
# 把结果列表转成带括号的字符串 rolls_str = f'({", ".join(rolls)})' await ctx.send(f'{ctx.author.mention} 🎇 \n**{count}枚D{sides}骰子结果**: {rolls_str}\n**总和**: {total}')
完整修改后的代码
整合所有逻辑,同时修正原代码里的小bug(比如total == '1'的赋值错误):
import random import re from discord.ext import commands @client.command(aliases=['r', 'dado', 'dice']) async def roll(ctx, *, dice_str: str = 'd20'): # 解析骰子表达式 match = re.match(r'(\d*)\s*d(\d+)', dice_str.lower()) if not match: await ctx.send(f'{ctx.author.mention} ❌ 格式错误!请使用 `-r <数量> d<面数>` 或 `-r <数量>d<面数>`,例如 `-r 5 d20`、`-r 3d6`。') return count = int(match.group(1)) if match.group(1) else 1 sides = int(match.group(2)) # 处理非法数值 if count <= 0 or sides < 2: await ctx.send(f'{ctx.author.mention} ❌ 骰子数量必须大于0,面数至少为2哦!') return # 执行投掷 rolls = [] total = 0 for _ in range(count): num = random.randint(1, sides) # 对1和最大面数加粗 if (sides == 20 and (num == 1 or num == 20)) or (num == 1 or num == sides): rolls.append(f'**{num}**') else: rolls.append(str(num)) total += num # 格式化输出 rolls_str = f'({", ".join(rolls)})' await ctx.send(f'{ctx.author.mention} 🎇 \n**{count}枚D{sides}骰子结果**: {rolls_str}\n**总和**: {total}')
额外优化小建议
如果之后想扩展功能,可以考虑支持带 modifier 的格式(比如-r 2d6+3),或者同时投掷多组不同骰子(比如-r 2d6 + 3d8),这些都可以通过扩展正则匹配逻辑来实现~
内容的提问来源于stack exchange,提问作者日本Jorge




