Archived
1
0
Fork 0
This repository has been archived on 2024-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
akari-bot/modules/dice/dice.py
2023-01-26 15:16:11 +08:00

144 lines
No EOL
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import secrets
import numpy as np
import re
MAX_DICE_COUNT = 100 # 一次摇动最多的骰子数量
MAX_ROLL_TIMES = 10 # 一次命令最多的摇动次数
MAX_MOD_NUMBER = 10000 # 骰子最大加权值
MIN_MOD_NUMBER = -10000 # 骰子最小加权值
MAX_OUTPUT_NUM = 50 # 输出的最多数据量
MAX_OUTPUT_LEN = 200 # 输出的最大长度
def GetDiceArgs(dice: str):
dice.replace(' ', '')
dice = dice.upper() # 便于识别
diceCount = '1' # 骰子数量
rollTimes = '1' # 摇取次数
advantage = '0' # 保留的骰子量
mod = '0' # Modifier
if 'D' not in dice:
return '语法错误'
temp = dice.split('D')
if len(temp):
if '*' in temp[0]:
rollTimes = temp[0].split('*')[0] # 摇动次数
diceCount = temp[0].split('*')[1] # 骰子数量
dice = dice[len(rollTimes):]
else:
diceCount = temp[0]
if not len(diceCount):
diceCount = '1'
back = re.match(r'^(.*)([+-].*)$',temp[1])
if back:
midstr = back.group(1)
mod = back.group(2).removeprefix('+')
else:
midstr = temp[1]
midstrs = midstr.partition('K')
diceType = midstrs[0]
if 'K' in midstrs[1]:
advantage = midstrs[2].replace('L','-')
# 语法合法检定
if not diceCount.isdigit():
return '错误:骰子数量非法:' + diceCount
if not diceType.isdigit():
return '错误:骰子面数非法:' + diceType
if not rollTimes.isdigit():
return '错误:投骰次数非法:' + rollTimes
if not mod.removeprefix('-').isdigit():
return '错误:调整值非法:' + mod
if not advantage.removeprefix('-').isdigit():
return '错误:优劣势非法:' + advantage
return {'times': int(rollTimes), 'cnt': int(diceCount), 'type': int(diceType), 'adv': int(advantage), 'mod': int(mod), 'str': dice}
def RollDice(args, dc):
output = '你摇出来的结果是:\n'
successNum = 0
failNum = 0
for times in range(args['times']):
result = 0
diceResults = []
output += args['str'] + ' = '
# 生成随机序列
for i in range(args['cnt']):
diceResults.append(secrets.randbelow(int(args['type']) - 1) + 1)
if args['adv'] != 0:
newResults = []
indexs = np.array(diceResults).argsort()
indexs = indexs[-args['adv']:] if args['adv'] > 0 else indexs[:-args['adv']]
output += '( '
outputBuffer = ''
for i in range(args['cnt']):
outputBuffer += str(diceResults[i])
if i in indexs:
newResults.append(diceResults[i])
outputBuffer += '*'
if i < args['cnt'] - 1:
outputBuffer += ','
if args['cnt'] >= MAX_OUTPUT_NUM:
outputBuffer = f"数量过大省略 {args['cnt']} 个数据"
output += outputBuffer + ' ) = '
diceResults = newResults
# 公用加法
length = len(diceResults)
if (length > 1):
output += '[ '
if length > MAX_OUTPUT_NUM: # 显示数据含100
output += f'数量过大省略{length}个数据'
for i in range(length):
result += diceResults[i]
if length <= MAX_OUTPUT_NUM: # 显示数据含100
output += str(diceResults[i])
if i < length-1:
output += '+'
output += ' ] = '
else:
result = diceResults[0]
# Modifier
if args['mod'] != 0:
output += f"N{result}"
if args['mod'] > 0:
output += '+'
output += f"{args['mod']} = "
output += str(result)
if dc != 0:
if result > dc:
output += ',判定成功!'
successNum += 1
else:
output += ',判定失败!'
failNum += 1
if (args['cnt'] == 1 or (args['cnt'] == 2 and (args['adv'] != 0))) and (args['type'] == 20 or args['type'] == 100) and args['mod'] >= 0:
temp = result - args['mod']
if temp >= args['type']:
output += ' 大成功!'
if temp == 1:
output += ' 大失败!'
if times != args['times']-1:
output += '\n'
if len(output) > MAX_OUTPUT_LEN:
output = '输出过长...'
if dc != 0 and args['times'] > 1:
output += '\n▷ 判定成功数量:' + str(successNum) + ' 判定失败数量:' + str(failNum)
return output
async def roll(dice: str, dc: int):
diceArgs = GetDiceArgs(dice) # 语法识别
if type(diceArgs) is str:
return diceArgs # 报错输出
# 数值合法与防熊检定
if not dc.isdigit():
return '错误DC非法:' + dc
dc = int(dc)
if (diceArgs['times'] <= 0 or diceArgs['times'] > MAX_ROLL_TIMES):
return f'错误:投骰次数不得小于 1 或 大于 {MAX_ROLL_TIMES}'
if (diceArgs['cnt'] <= 0 or diceArgs['cnt'] > MAX_DICE_COUNT):
return f'错误骰子数量不得小于1或大于{MAX_DICE_COUNT}'
if (diceArgs['type'] <= 0):
return '错误骰子面数不得小于1'
if (abs(diceArgs['adv']) > diceArgs['cnt']):
return '错误:优劣势骰数大于总骰子数'
if (diceArgs['mod'] > MAX_MOD_NUMBER or diceArgs['mod'] < MIN_MOD_NUMBER):
return f'错误:调整值不得小于 {MIN_MOD_NUMBER} 或大于 {MIN_MOD_NUMBER} '
# 开始随机生成
return RollDice(diceArgs, dc)