不知道大家知不知道 TTRPG 呢?
比较有名的大概就是龙与地下城(D&D)吧
之前看 hololive EN 在玩就萌生了来写个 Bot 玩看看好了的想法
指令格式
!roll 5D10>8
这代表:掷 5 个 10 面骰,成功判定是点数大於等於 8
# 导入 Discord.py 套件
import discord
# 导入随机数套件
import random
# 取得 Discord client 物件才能操作
client = discord.Client()
# 调用 event 函式库
@client.event
# 当机器人完成启动时在终端机显示提示讯息
async def on_ready():
print(f'目前登入身份:{client.user}')
# 调用 event 函式库
@client.event
# 当有讯息时
async def on_message(message):
# 排除机器人本身发出的讯息,避免机器人自问自答的无限回圈
if message.author == client.user:
return
# 预设错误讯息
error = []
# 处理输入文字
content = message.content.replace(' ', '').lower()
# 如果是「!roll」开头的讯息
if message.content.startswith('!roll'):
content = content.replace('!roll', '')
# 骰子数量计算
dice_cont = content.split('d')[0]
try:
dice_cont = int(dice_cont)
except ValueError:
error.append('How many dice you roll must be an interger!')
# 骰子类型判断
content = content.split('d')[1]
dice_type = content.split('>')[0]
try:
dice_type = int(dice_type)
except ValueError:
error.append('Dice type must be an interger!')
# 成功判断
if '>' in content:
success = content.split('>')[1]
try:
success = int(success)
except ValueError:
error.append('Success condition must be an interger!')
else:
success = 0
if len(error) == 0:
success_count = 0
result_msg = ''
# 掷骰子
results = [random.randint(1, dice_type) for _ in range(dice_cont)]
for result in results:
if success > 0 and result >= success:
success_count += 1
result_msg += f'`{result}`, '
await message.channel.send(result_msg)
if success > 0:
await message.channel.send(f'Success: `{success_count}`')
else:
await message.channel.send(error)
# TOKEN 在 Discord Developer 的「BOT」页取得
client.run('')
基本的discord.py
使用方法之前写过就不写了
针对逻辑的部份做说明
首先透过 message.content.startswith('!roll')
只对!roll
开头的讯息做反应
为了让使用者不管输入大小写或是有没有空格都可使用
所以透过message.content.replace(' ', '').lower()
去除空白和全部转小写
如此一来,使用者不论输入
後续程序都是以!roll5d10
做处理
根据输入讯息的格式,在!roll
後面、d
前面的「数字」代表骰子数量
使用content.replace('!roll', '')
去除字串中的!roll
因为这只是用来触发机器人,不会影响掷骰子结果
使用content.split('d')[0]
将字串从d
切分,取得列表第一个值,这就是骰子数量
使用强制转型判断取得的值是不是数字?如果不是则转型出错会被try except
捕获
若是被捕获了,就新增错误讯息字串
和刚刚的数量计算很像,只是这次我们抓取的逻辑是介於d後,>符号前
如果没有对应的>
符号,则不会分切回传整个内容
再藉由跟数量计算一样的强制转型判断取得的类型是否是数字
若是错误,一样新增错误讯息
因为我们允许使用者在使用指令的时候不输入成功判断条件
所以透过'>' in content:
来判断使用者是否有输入判断条件
如果有输入的话条件会在>
後面,一样取得值之後判断是否是数字
我们需要的参数都已经取得了,接下来就是根据条件掷骰并回传
首先先检查前面的错误讯息是不是有被建立,如果有代表不该掷骰!
这时候就直接输出错误讯息到 Discord
如果错误讯息为空,就透过
results = [random.randint(1, dice_type) for _ in range(dice_cont)]
取得指定数量的随机乱数执行结果,用这种方法写和写回圈是一样的!
接着遍历所有结果,整理成输出到 Discord 想要的格式
并且如果使用者有输入掷骰成功的条件,也在这边计算成功次数
最後就是输出掷骰结果和成功次数到 Discord,结果如下
如此就完成了一开始设定的掷骰机器人需求
尽管机器人的需求是完成了,但是还有很多可以优化的部分
现在太多逻辑全部写在一起,应该拆成独立函数来呼叫
这样不论是写测试或是未来要调整都会比较容易
切分逻辑过於简单,万一使用者输入了我们没想到的内容
例如!roll6D10d5
,虽然程序执行起来会跟!roll6D10
一样
但是使用者不应该多最後那个d5
,这部分该如何处理也是一个可以改进的目标
event 查目前网页的 event,开启 Chrome 的开发者工具,点选 Elements,之後...
当我们拿到一个现有的 Web Component 时 , 如何在 React 专案中引用呢 ? 利用...
如果你正在为水电或3C故障而苦恼,也许照着影片操作,是可以完成修复,但网路影片并非每一样技术都可以直...
简介厨房:Shioaji Shioaji是永丰证开发出来的Python API,用来给客户自行开发自...
天亮了 昨晚是平安夜 关於迷雾森林故事 香水 在场本来许多animal们牵着喜鹊儿的翅膀小手跳舞 都...