Files
WPSBot/games/dice.py
2025-10-28 13:00:35 +08:00

176 lines
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 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"**最终结果**<font color='#FF6B6B'>{final_result}</font>\n\n"
else:
text += f"**最终结果**<font color='#FF6B6B'>{final_result}</font>\n\n"
else:
# 骰子太多,只显示总和
text += f"**点数和**{total}\n\n"
if modifier:
text += f"**修正**{modifier}{modifier_value}\n\n"
text += f"**最终结果**<font color='#FF6B6B'>{final_result}</font>\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
```
"""