"""骰娘系统""" import re import random import logging from typing import Tuple, Optional, List from games.base import BaseGame logger = logging.getLogger(__name__) class DiceGame(BaseGame): """骰娘游戏""" # 骰子指令正则模式 # 匹配:.r 3d6, .r 1d20+5, .r 2d10-3等 DICE_PATTERN = re.compile( r'^\.r(?:oll)?\s+(\d+)d(\d+)(?:([+-])(\d+))?', re.IGNORECASE ) # 最大限制 MAX_DICE_COUNT = 100 MAX_DICE_SIDES = 1000 async def handle(self, command: str, chat_id: int, user_id: int) -> str: """处理骰子指令 Args: command: 指令,如 ".r 1d20" 或 ".r 3d6+5" chat_id: 会话ID user_id: 用户ID Returns: 回复消息 """ try: # 解析指令 result = self._parse_command(command) if not result: return self.get_help() dice_count, dice_sides, modifier, modifier_value = result # 验证参数 if dice_count > self.MAX_DICE_COUNT: return f"❌ 骰子数量不能超过 {self.MAX_DICE_COUNT}" if dice_sides > self.MAX_DICE_SIDES: return f"❌ 骰子面数不能超过 {self.MAX_DICE_SIDES}" if dice_count <= 0 or dice_sides <= 0: return "❌ 骰子数量和面数必须大于0" # 掷骰子 rolls = [random.randint(1, dice_sides) for _ in range(dice_count)] total = sum(rolls) # 应用修正值 final_result = total if modifier: if modifier == '+': final_result = total + modifier_value elif modifier == '-': final_result = total - modifier_value # 格式化输出 return self._format_result( dice_count, dice_sides, rolls, total, modifier, modifier_value, final_result ) except Exception as e: logger.error(f"处理骰子指令错误: {e}", exc_info=True) return f"❌ 处理指令出错: {str(e)}" def _parse_command(self, command: str) -> Optional[Tuple[int, int, Optional[str], int]]: """解析骰子指令 Args: command: 指令字符串 Returns: (骰子数量, 骰子面数, 修正符号, 修正值) 或 None """ match = self.DICE_PATTERN.match(command.strip()) if not match: return None dice_count = int(match.group(1)) dice_sides = int(match.group(2)) modifier = match.group(3) # '+' 或 '-' 或 None modifier_value = int(match.group(4)) if match.group(4) else 0 return dice_count, dice_sides, modifier, modifier_value def _format_result(self, dice_count: int, dice_sides: int, rolls: List[int], total: int, modifier: Optional[str], modifier_value: int, final_result: int) -> str: """格式化骰子结果 Args: dice_count: 骰子数量 dice_sides: 骰子面数 rolls: 各个骰子结果 total: 骰子总和 modifier: 修正符号 modifier_value: 修正值 final_result: 最终结果 Returns: 格式化的Markdown消息 """ # 构建表达式 expression = f"{dice_count}d{dice_sides}" if modifier: expression += f"{modifier}{modifier_value}" # Markdown格式输出 text = f"## 🎲 掷骰结果\n\n" text += f"**表达式**:{expression}\n\n" # 显示每个骰子的结果 if dice_count <= 20: # 骰子数量不多时,显示详细结果 rolls_str = ", ".join([f"**{r}**" for r in rolls]) text += f"**骰子**:[{rolls_str}]\n\n" text += f"**点数和**:{total}\n\n" if modifier: text += f"**修正**:{modifier}{modifier_value}\n\n" text += f"**最终结果**:{final_result}\n\n" else: text += f"**最终结果**:{final_result}\n\n" else: # 骰子太多,只显示总和 text += f"**点数和**:{total}\n\n" if modifier: text += f"**修正**:{modifier}{modifier_value}\n\n" text += f"**最终结果**:{final_result}\n\n" # 特殊提示 if dice_count == 1: if rolls[0] == dice_sides: text += "✨ **大成功!**\n" elif rolls[0] == 1: text += "💥 **大失败!**\n" return text def get_help(self) -> str: """获取帮助信息""" return """## 🎲 骰娘系统帮助 ### 基础用法 - `.r 1d20` - 掷一个20面骰 - `.r 3d6` - 掷三个6面骰 - `.r 2d10+5` - 掷两个10面骰,结果加5 - `.r 1d20-3` - 掷一个20面骰,结果减3 ### 说明 - 格式:`.r XdY+Z` - X = 骰子数量(最多100个) - Y = 骰子面数(最多1000面) - Z = 修正值(可选) - 支持 + 和 - 修正 - 单个d20骰出20为大成功,骰出1为大失败 ### 示例 ``` .r 1d6 → 掷一个6面骰 .r 4d6 → 掷四个6面骰 .r 1d20+5 → 1d20并加5 .r 3d6-2 → 3d6并减2 ``` """