From 8f64c429d24c05b4ca3fd42c9d9c1c1070cf6177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=9A=E7=BE=85=E7=8B=BC?= Date: Sun, 24 Mar 2024 22:46:13 +0800 Subject: [PATCH] Update BPdice --- modules/dice/__init__.py | 12 +- modules/dice/dice.py | 253 ++++---------------------- modules/dice/locales/en_us.json | 2 +- modules/dice/locales/zh_cn.json | 2 +- modules/dice/locales/zh_tw.json | 2 +- modules/dice/type.py | 305 ++++++++++++++++++++++++++++++++ 6 files changed, 341 insertions(+), 235 deletions(-) create mode 100644 modules/dice/type.py diff --git a/modules/dice/__init__.py b/modules/dice/__init__.py index 1fe70f0550..f33aa77be8 100644 --- a/modules/dice/__init__.py +++ b/modules/dice/__init__.py @@ -7,15 +7,7 @@ @dice.command(' [] {{dice.help}}') async def _(msg: Bot.MessageSession, dices: str, dc = None): - - if '#' in dices: - times = dices.partition('#')[0] - dices = dices.partition('#')[2] - else: - times = '1' - if not times.isdigit(): - await msg.finish(msg.locale.t('dice.message.N.invalid') + times) - await msg.finish(await process_expression(msg, dices, int(times), dc)) + await msg.finish(await process_expression(msg, dices, dc)) @dice.regex(r"[扔投掷擲丢]([0-9]*)?[个個]([0-9]*面)?骰子?([0-9]*次)?", desc="{dice.help.regex.desc}") @@ -24,7 +16,7 @@ async def _(msg: Bot.MessageSession): default_type = msg.data.options.get('dice_default_face') if msg.data.options.get('dice_default_face') else '6' dice_type = groups[1][:-1] if groups[1] else default_type roll_time = groups[2][:-1] if groups[2] else '1' - await msg.finish(await process_expression(msg, f'{groups[0]}D{dice_type}', int(roll_time), None)) + await msg.finish(await process_expression(msg, f'{roll_time}#{groups[0]}D{dice_type}', None)) @dice.command('set {{dice.help.set}}', required_admin=True) diff --git a/modules/dice/dice.py b/modules/dice/dice.py index d2d3390345..f0b4600072 100644 --- a/modules/dice/dice.py +++ b/modules/dice/dice.py @@ -1,13 +1,12 @@ import math import re -import secrets -import numpy as np from simpleeval import SimpleEval, FunctionNotDefined, NameNotDefined from config import Config from core.exceptions import ConfigValueError from core.logger import Logger +from .type import Dice, FudgeDice, DiceSyntaxError, DiceValueError # 配置常量 MAX_DICE_COUNT = Config('dice_limit', 100) # 一次摇动最多的骰子数量 @@ -40,205 +39,7 @@ se.functions.update(math_funcs) -# 异常类定义 -class DiceSyntaxError(Exception): - """骰子语法错误""" - - def __init__(self, msg, message): - self.message = message - - -class DiceValueError(Exception): - """骰子参数值错误""" - - def __init__(self, msg, message, value=None): - if value: - self.message = msg.locale.t("dice.message.error.value", value=value) + message - else: - self.message = message - - -# 类定义 -class DiceItemBase(object): - """骰子项的基类""" - - def __init__(self, dice_code: str): - self.code = dice_code - self.result = None - self.detail = '' - - def GetResult(self): - return self.result - - def GetDetail(self): - return self.detail - - def Roll(self, msg, use_markdown: bool = False): - pass - - -class Dice(DiceItemBase): - """骰子项""" - - def __init__(self, msg, dice_code: str): - - dice_code = dice_code.replace(' ', '') - super().__init__(dice_code) - args = self.GetArgs(msg) - self.count = args[0] - self.type = args[1] - self.adv = args[2] - if self.count <= 0 or self.count > MAX_DICE_COUNT: - raise DiceValueError(msg, - msg.locale.t("dice.message.error.value.n.out_of_range", max=MAX_DICE_COUNT), - self.count) - if self.type <= 0: - raise DiceValueError(msg, - msg.locale.t("dice.message.error.value.n.less_2"), - self.type) - if self.type == 1: - raise DiceValueError(msg, msg.locale.t("dice.message.error.value.n.d1")) - if abs(self.adv) > self.count: - raise DiceValueError(msg, - msg.locale.t("dice.message.error.value.k.out_of_range"), - self.adv) - - def GetArgs(self, msg): - dice_code = self.code.upper() # 便于识别 - dice_code = dice_code.replace("D%", "D100") # 百分骰别名 - dice_count = '1' # 骰子数量 - advantage = '0' # 保留的骰子量 - if re.search(r'[^0-9DKQ\%]', dice_code): - raise DiceSyntaxError(msg, msg.locale.t("dice.message.error.invalid")) - temp = dice_code.split('D') - if len(temp[0]): - dice_count = temp[0] - else: - dice_count = '1' - dice_type = temp[1] - if 'K' in temp[1]: - midstrs = temp[1].partition('K') - dice_type = midstrs[0] - advantage = midstrs[2] - elif 'Q' in temp[1]: - midstrs = temp[1].partition('Q') - dice_type = midstrs[0] - advantage = f'-{midstrs[2]}' - if not len(advantage.removeprefix('-')): - advantage += '1' # K/Q后没有值默认为1 - # 语法合法检定 - if not dice_count.isdigit(): - raise DiceValueError(msg, - msg.locale.t("dice.message.error.value.m.invalid"), - dice_count) - if not dice_type.isdigit(): - raise DiceValueError(msg, - msg.locale.t("dice.message.error.value.n.invalid"), - dice_type) - if not (advantage.isdigit() or (advantage[0] == '-' and advantage[1:].isdigit())): - raise DiceValueError(msg, - msg.locale.t("dice.message.error.value.k.invalid"), - advantage) - return (int(dice_count), int(dice_type), int(advantage)) - - def Roll(self, msg, use_markdown=False): - output = '' - result = 0 - dice_results = [] - adv = self.adv - output += self.code + '=' - # 生成随机序列 - for i in range(self.count): - dice_results.append(secrets.randbelow(int(self.type)) + 1) - if adv != 0: - new_results = [] - indexes = np.array(dice_results).argsort() - indexes = indexes[-adv:] if adv > 0 else indexes[:-adv] - output += '[' - output_buffer = '' - for i in range(self.count): - if use_markdown: - if i in indexes: - new_results.append(dice_results[i]) - output_buffer += f"*{str(dice_results[i])}*" - else: - output_buffer += f"{str(dice_results[i])}" - else: - output_buffer += str(dice_results[i]) - if i in indexes: - new_results.append(dice_results[i]) - output_buffer += '*' - if i < self.count - 1: - output_buffer += ', ' - if self.count >= MAX_OUTPUT_CNT: - output_buffer = msg.locale.t("dice.message.output.too_long", length=self.count) - output += output_buffer + ']=' - dice_results = new_results - # 公用加法 - length = len(dice_results) - if length > 1: - output += '[' - if length > MAX_OUTPUT_CNT: # 显示数据含100 - output += msg.locale.t("dice.message.output.too_long", length=length) - for i in range(length): - result += dice_results[i] - if length <= MAX_OUTPUT_CNT: # 显示数据含100 - output += str(dice_results[i]) - if i < length - 1: - output += '+' - output += ']=' - else: - result = dice_results[0] - if len(output) > MAX_OUTPUT_LEN: - output = msg.locale.t("dice.message.too_long") - self.detail = output + f"{result}" - self.result = result - - -class FudgeDice(DiceItemBase): - """命运骰子项""" - - def __init__(self, msg, dice_code: str): - super().__init__(dice_code) - self.count = 4 # 默认投掷次数为4 - - # 兼容旧格式 - if dice_code.upper().endswith('DF'): - dice_code = dice_code[:-2] + 'F' - - if len(dice_code) > 1: - try: - self.count = int(dice_code[:-1]) - except ValueError: - raise DiceSyntaxError(msg, msg.locale.t("dice.message.error.invalid")) - if self.count <= 0 or self.count > MAX_DICE_COUNT: - raise DiceValueError(msg, - msg.locale.t("dice.message.error.value.n.out_of_range", max=MAX_DICE_COUNT), - self.count) - - def Roll(self, msg, use_markdown=False): - output = '' - result = 0 - output += self.code + '=' - - dice_results = ['-', '-', '0', '0', '+', '+'] - selected_results = [secrets.choice(dice_results) for _ in range(self.count)] - output += '[' + ', '.join(selected_results) + ']' - - for res in selected_results: - if res == '-': - result -= 1 - elif res == '+': - result += 1 - - self.detail = output + f"={result}" - self.result = result - - def GetArgs(self, msg): - return self.count, 6, 0 - - -async def process_expression(msg, expr: str, times: int, dc, use_markdown = False): +async def process_expression(msg, expr: str, dc, use_markdown = False): if not all([MAX_DICE_COUNT > 0, MAX_ROLL_TIMES > 0, MAX_OUTPUT_CNT > 0, MAX_OUTPUT_LEN > 0, MAX_DETAIL_CNT > 0, MAX_ITEM_COUNT > 0]): raise ConfigValueError(msg.locale.t("error.config.invalid")) @@ -248,7 +49,7 @@ async def process_expression(msg, expr: str, times: int, dc, use_markdown = Fals expr = expr.replace('*', '\*') expr = expr.replace('\\*', '\*') - dice_list, count, err = parse_dice_expression(msg, expr) + dice_list, count, times, err = parse_dice_expression(msg, expr) if err: return err output = generate_dice_message(msg, expr, dice_list, count, times, dc, use_markdown) @@ -265,6 +66,14 @@ def parse_dice_expression(msg, dices): errmsg = None # 切分骰子表达式 + if '#' in dices: + times = dices.partition('#')[0] + dices = dices.partition('#')[2] + else: + times = '1' + if not times.isdigit(): + return None, None, None, DiceValueError(msg, msg.locale.t('dice.message.N.invalid'), times).message + dice_expr_list = re.split('|'.join(patterns), dices, flags=re.I) dice_expr_list = [item for item in dice_expr_list if item] # 清除空白元素 for item in range(len(dice_expr_list)): @@ -272,27 +81,26 @@ def parse_dice_expression(msg, dices): dice_expr_list[item] += str(msg.data.options.get('dice_default_face')) Logger.debug(dice_expr_list) - for item in dice_expr_list: + for i, item in enumerate(dice_expr_list): for pattern in patterns: match = re.match(pattern, item, flags=re.I) if match: + dice_expr_list[i] = item.upper() dice_item_list.append(item) break if len(dice_item_list) > MAX_ITEM_COUNT: - return None, None, DiceValueError(msg, msg.locale.t('dice.message.error.value.too_long')).message + return None, None, None, DiceValueError(msg, msg.locale.t('dice.message.error.value.too_long')).message dice_count = 0 - i = 0 # 初始化骰子序列 - for item in dice_expr_list: + for j, item in enumerate(dice_expr_list): try: - i += 1 if 'F' in item or 'f' in item: dice_count += 1 - dice_expr_list[i-1] = FudgeDice(msg, item) + dice_expr_list[j] = FudgeDice(msg, item) elif 'D' in item or 'd' in item: dice_count += 1 - dice_expr_list[i-1] = Dice(msg, item) + dice_expr_list[j] = Dice(msg, item) elif item.isdigit(): dice_count += 1 else: @@ -300,8 +108,8 @@ def parse_dice_expression(msg, dices): except (DiceSyntaxError, DiceValueError) as ex: errmsg = msg.locale.t('dice.message.error.prompt', i=dice_count) + ex.message if errmsg: - return None, None, DiceValueError(msg, msg.locale.t('dice.message.error') + '\n' + errmsg).message - return dice_expr_list, dice_count, None + return None, None, None, DiceValueError(msg, msg.locale.t('dice.message.error') + '\n' + errmsg).message + return dice_expr_list, dice_count, int(times), None # 在数字与数字之间加上乘号 @@ -333,21 +141,19 @@ def generate_dice_message(msg, expr, dice_expr_list, dice_count, times, dc, use_ msg.locale.t("dice.message.error.value.N.out_of_range", max=MAX_ROLL_TIMES), times).message # 开始投掷并生成消息 - for i in range(times): - j = 0 + for _ in range(times): dice_detail_list = dice_expr_list.copy() dice_res_list = dice_expr_list.copy() output_line = '' - for item in dice_detail_list: - j += 1 + for i, item in enumerate(dice_detail_list): if isinstance(item, (Dice, FudgeDice)): item.Roll(msg, use_markdown) res = item.GetResult() if times * dice_count < MAX_DETAIL_CNT: - dice_detail_list[j-1] = f'({item.GetDetail()})' + dice_detail_list[i] = f'({item.GetDetail()})' else: - dice_detail_list[j-1] = f'({str(res)})' if res < 0 else str(res) # 负数加括号 - dice_res_list[j-1] = f'({str(res)})' if res < 0 else str(res) + dice_detail_list[i] = f'({str(res)})' if res < 0 else str(res) # 负数加括号 + dice_res_list[i] = f'({str(res)})' if res < 0 else str(res) else: continue dice_detail_list = insert_multiply(dice_detail_list, use_markdown) @@ -356,10 +162,13 @@ def generate_dice_message(msg, expr, dice_expr_list, dice_count, times, dc, use_ Logger.debug(dice_detail_list) Logger.debug(dice_res_list) try: - dice_res = ''.join(dice_res_list) - dice_res = dice_res.replace('\*', '*') - Logger.debug(dice_res) - result = int(se.eval(dice_res)) + if dice_res_list: + dice_res = ''.join(dice_res_list) + dice_res = dice_res.replace('\*', '*') + Logger.debug(dice_res) + result = int(se.eval(dice_res)) + else: + raise SyntaxError except (FunctionNotDefined, NameNotDefined, SyntaxError): return DiceSyntaxError(msg, msg.locale.t('dice.message.error.syntax')).message except Exception as e: diff --git a/modules/dice/locales/en_us.json b/modules/dice/locales/en_us.json index 1ad5f10de5..8e04e59725 100644 --- a/modules/dice/locales/en_us.json +++ b/modules/dice/locales/en_us.json @@ -22,7 +22,7 @@ "dice.message.error.value.n.invalid": "Invalid sides number of dice.", "dice.message.error.value.n.less_2": "The sides number of dice cannot be less than 2.", "dice.message.error.value.N.out_of_range": "The number of dice roll cannot be less than 1 or greater than ${max}.", - "dice.message.error.value.n.out_of_range": "The number of dice cannot be less than 1 or greater than ${max}.", + "dice.message.error.value.m.out_of_range": "The number of dice cannot be less than 1 or greater than ${max}.", "dice.message.error.value.too_long": "The number of items in the dice expression exceeds the limit.", "dice.message.error.value.y.invalid": "Invalid adjustment value.", "dice.message.error.value.y.out_of_range": "The adjustment value cannot be less than ${min} or greater than ${max}.", diff --git a/modules/dice/locales/zh_cn.json b/modules/dice/locales/zh_cn.json index b7a48c2395..e8fbdc8c9f 100644 --- a/modules/dice/locales/zh_cn.json +++ b/modules/dice/locales/zh_cn.json @@ -22,7 +22,7 @@ "dice.message.error.value.n.invalid": "无效的骰子面数。", "dice.message.error.value.n.less_2": "骰子面数不得小于 2。", "dice.message.error.value.N.out_of_range": "投骰次数不得小于 1 或大于 ${max}。", - "dice.message.error.value.n.out_of_range": "骰子数量不得小于 1 或大于 ${max}。", + "dice.message.error.value.m.out_of_range": "骰子数量不得小于 1 或大于 ${max}。", "dice.message.error.value.too_long": "骰子表达式项数超过限制。", "dice.message.error.value.y.invalid": "无效的调节值项。", "dice.message.error.value.y.out_of_range": "调节值不得小于 ${min} 或大于 ${max}。", diff --git a/modules/dice/locales/zh_tw.json b/modules/dice/locales/zh_tw.json index 42b46739c2..0e400b8d82 100644 --- a/modules/dice/locales/zh_tw.json +++ b/modules/dice/locales/zh_tw.json @@ -21,7 +21,7 @@ "dice.message.error.value.n.d1": "1 面的骰子?", "dice.message.error.value.n.invalid": "無效的骰子面數。", "dice.message.error.value.n.less_2": "骰子面數不得小於 2。", - "dice.message.error.value.n.out_of_range": "骰子數量不得小於 1 或大於 ${max}。", + "dice.message.error.value.m.out_of_range": "骰子數量不得小於 1 或大於 ${max}。", "dice.message.error.value.N.out_of_range": "投骰次數不得小於 1 或大於 ${max}。", "dice.message.error.value.too_long": "骰子運算式項數超過限制。", "dice.message.error.value.y.invalid": "無效的調整值項。", diff --git a/modules/dice/type.py b/modules/dice/type.py new file mode 100644 index 0000000000..da3a0c14ef --- /dev/null +++ b/modules/dice/type.py @@ -0,0 +1,305 @@ +import re +import secrets + +import numpy as np + +from config import Config + +MAX_DICE_COUNT = Config('dice_limit', 100) # 一次摇动最多的骰子数量 +MAX_OUTPUT_CNT = Config('dice_output_count', 50) # 输出的最多数据量 +MAX_OUTPUT_LEN = Config('dice_output_len', 200) # 输出的最大长度 + + +# 异常类定义 +class DiceSyntaxError(Exception): + """骰子语法错误""" + + def __init__(self, msg, message): + self.message = message + + +class DiceValueError(Exception): + """骰子参数值错误""" + + def __init__(self, msg, message, value=None): + if value: + self.message = msg.locale.t("dice.message.error.value", value=value) + message + else: + self.message = message + + +# 类定义 +class DiceItemBase(object): + """骰子项的基类""" + + def __init__(self, dice_code: str): + self.code = dice_code + self.result = None + self.detail = '' + + def GetResult(self): + return self.result + + def GetDetail(self): + return self.detail + + def Roll(self, msg, use_markdown: bool = False): + pass + + +class Dice(DiceItemBase): + """骰子项""" + + def __init__(self, msg, dice_code: str): + + dice_code = dice_code.replace(' ', '') + super().__init__(dice_code) + args = self.GetArgs(msg) + self.count = args[0] + self.type = args[1] + self.adv = args[2] + if self.count <= 0 or self.count > MAX_DICE_COUNT: + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.m.out_of_range", max=MAX_DICE_COUNT), + self.count) + if self.type <= 0: + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.n.less_2"), + self.type) + if self.type == 1: + raise DiceValueError(msg, msg.locale.t("dice.message.error.value.n.d1")) + if abs(self.adv) > self.count: + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.k.out_of_range"), + self.adv) + + def GetArgs(self, msg): + dice_code = self.code.upper() # 便于识别 + dice_code = dice_code.replace("D%", "D100") # 百分骰别名 + dice_count = '1' # 骰子数量 + advantage = '0' # 保留的骰子量 + if re.search(r'[^0-9DKQ\%]', dice_code): + raise DiceSyntaxError(msg, msg.locale.t("dice.message.error.invalid")) + temp = dice_code.split('D') + if len(temp[0]): + dice_count = temp[0] + dice_type = temp[1] + if 'K' in temp[1]: + midstrs = temp[1].partition('K') + dice_type = midstrs[0] + advantage = midstrs[2] + elif 'Q' in temp[1]: + midstrs = temp[1].partition('Q') + dice_type = midstrs[0] + advantage = f'-{midstrs[2]}' + if not len(advantage.removeprefix('-')): + advantage += '1' # K/Q后没有值默认为1 + # 语法合法检定 + if not dice_count.isdigit(): + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.m.invalid"), + dice_count) + if not dice_type.isdigit(): + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.n.invalid"), + dice_type) + if not (advantage.isdigit() or (advantage[0] == '-' and advantage[1:].isdigit())): + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.k.invalid"), + advantage) + return (int(dice_count), int(dice_type), int(advantage)) + + def Roll(self, msg, use_markdown=False): + output = self.code + result = 0 + dice_results = [] + adv = self.adv + # 生成随机序列 + for i in range(self.count): + dice_results.append(secrets.randbelow(int(self.type)) + 1) + if adv != 0: + new_results = [] + indexes = np.array(dice_results).argsort() + indexes = indexes[-adv:] if adv > 0 else indexes[:-adv] + output += '=[' + output_buffer = '' + for i in range(self.count): + if use_markdown: + if i in indexes: + new_results.append(dice_results[i]) + output_buffer += f"*{str(dice_results[i])}*" + else: + output_buffer += f"{str(dice_results[i])}" + else: + output_buffer += str(dice_results[i]) + if i in indexes: + new_results.append(dice_results[i]) + output_buffer += '*' + if i < self.count - 1: + output_buffer += ', ' + if self.count >= MAX_OUTPUT_CNT: + output_buffer = msg.locale.t("dice.message.output.too_long", length=self.count) + output += output_buffer + ']' + dice_results = new_results + # 公用加法 + length = len(dice_results) + if length > 1: + output += '=[' + if length > MAX_OUTPUT_CNT: # 显示数据含100 + output += msg.locale.t("dice.message.output.too_long", length=length) + for i in range(length): + result += dice_results[i] + if length <= MAX_OUTPUT_CNT: # 显示数据含100 + output += str(dice_results[i]) + if i < length - 1: + output += '+' + output += ']' + else: + result = dice_results[0] + if len(output) > MAX_OUTPUT_LEN: + output = msg.locale.t("dice.message.too_long") + self.detail = output + f"={result}" + self.result = result + + +class FudgeDice(DiceItemBase): + """命运骰子项""" + + def __init__(self, msg, dice_code: str): + + dice_code = dice_code.replace(' ', '') + super().__init__(dice_code) + args = self.GetArgs(msg) + self.count = args[0] + if self.count <= 0 or self.count > MAX_DICE_COUNT: + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.m.out_of_range", max=MAX_DICE_COUNT), + self.count) + + + def GetArgs(self, msg): + dice_code = self.code.upper() # 便于识别 + if dice_code.upper().endswith('DF'): # 兼容旧格式 + dice_code = dice_code[:-2] + 'F' + dice_count = '4' # 骰子数量 + if re.search(r'[^0-9F]', dice_code): + raise DiceSyntaxError(msg, msg.locale.t("dice.message.error.invalid")) + temp = dice_code.split('F') + if len(temp[0]): + dice_count = temp[0] + + # 语法合法检定 + if not dice_count.isdigit(): + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.m.invalid"), + dice_count) + return (int(dice_count), 0) + + def Roll(self, msg, use_markdown=False): + output = self.code + result = 0 + + dice_results = ['-', '-', '0', '0', '+', '+'] + selected_results = [secrets.choice(dice_results) for _ in range(self.count)] + + length = len(selected_results) + output += '=[' + if length > MAX_OUTPUT_CNT: # 显示数据含100 + output += msg.locale.t("dice.message.output.too_long", length=length) + else: + output += ', '.join(selected_results) + output += ']' + + for res in selected_results: + if res == '-': + result -= 1 + elif res == '+': + result += 1 + + if len(output) > MAX_OUTPUT_LEN: + output = msg.locale.t("dice.message.too_long") + self.detail = output + f"={result}" + self.result = result + + +class BounsPunishDice(DiceItemBase): + """奖惩骰子项""" + + def __init__(self, msg, dice_code: str): + + dice_code = dice_code.replace(' ', '') + super().__init__(dice_code) + args = self.GetArgs(msg) + self.count = args[0] + self.type = args[1] + if self.count <= 0 or self.count > MAX_DICE_COUNT: + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.m.out_of_range", max=MAX_DICE_COUNT), + self.count) + + def GetArgs(self, msg): + dice_code = self.code.upper() # 便于识别 + if re.search(r'[^0-9BP]', dice_code): + raise DiceSyntaxError(msg, msg.locale.t("dice.message.error.invalid")) + if 'B' in dice_code: + dice_type = 'B' + temp = dice_code.split('B') + dice_count = temp[1] if len(temp[1]) else '1' # 骰子数量 + elif 'P' in dice_code: + dice_type = 'P' + temp = dice_code.split('P') + dice_count = temp[1] if len(temp[1]) else '1' # 骰子数量 + + # 语法合法检定 + if not dice_count.isdigit(): + raise DiceValueError(msg, + msg.locale.t("dice.message.error.value.m.invalid"), + dice_count) + + return (int(dice_count), dice_type) + + def Roll(self, msg, use_markdown=False): + output = '' + dice_results = [] + dice_type = self.type + result = 0 + # 生成随机序列 + + d100_result = secrets.randbelow(100) + 1 + d100_digit = d100_result % 10 + output += f'D100={d100_result}, D10{self.code}' + + for i in range(self.count): + dice_results.append(secrets.randbelow(10) + 1) + dice_results = [0 if x == 10 else x for x in dice_results] + new_results = [] + indexes = np.array(dice_results).argsort() + if dice_type == 'P': + indexes = indexes[-1:] + elif dice_type == 'B': + indexes = indexes[:1] + output += '=[' + output_buffer = '' + for i in range(self.count): + if use_markdown: + if i in indexes: + new_results.append(dice_results[i]) + output_buffer += f"*{str(dice_results[i])}*" + else: + output_buffer += f"{str(dice_results[i])}" + else: + output_buffer += str(dice_results[i]) + if i in indexes: + new_results.append(dice_results[i]) + output_buffer += '*' + if i < self.count - 1: + output_buffer += ', ' + if self.count >= MAX_OUTPUT_CNT: + output_buffer = msg.locale.t("dice.message.output.too_long", length=self.count) + output += output_buffer + ']' + dice_digit = new_results[0] + result = int(str(dice_digit) + str(d100_digit)) + if len(output) > MAX_OUTPUT_LEN: + output = msg.locale.t("dice.message.too_long") + self.detail = output + f"={dice_digit}" + self.result = result \ No newline at end of file