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-02-23 21:52:34 +08:00

151 lines
5.8 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)
if mod[0] == '+':
mod = mod[1:]
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.isdigit() or (mod[0] == '-' and mod[1:].isdigit())):
return '发生错误:无效的调节值:' + mod
if not (advantage.isdigit() or (advantage[0] == '-' and advantage[1:].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']} = "
result += 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 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 '发生错误:骰子面数不得小于 2'
if diceArgs['type'] == 1:
return '发生错误1...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)