Files
WPSBot/.tasks/2025-10-28_1_add-idiom-chain-game.md

239 lines
8.3 KiB
Markdown
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.

# 背景
文件名2025-10-28_1_add-idiom-chain-game.md
创建于2025-10-28_15:43:00
创建者admin
主分支main
任务分支task/add-idiom-chain-game_2025-10-28_1
Yolo模式Off
# 任务描述
在WPS Bot Game项目中新增一个成语接龙游戏功能。
## 核心需求
1. 群内多人游戏,机器人作为裁判和出题者
2. 允许按拼音接龙(包括谐音接龙)
3. 没有时间限制
4. 不需要提示功能
5. 游戏记录保存到.stats统计中
6. 不允许重复使用成语
7. 不需要难度分级(非人机对战)
8. 需要裁判指令用于接受/拒绝玩家回答
## 游戏玩法
- 机器人出题(给出起始成语)
- 群内玩家轮流接龙
- 机器人判断接龙是否有效(拼音/谐音匹配、未重复使用)
- 裁判可以手动接受或拒绝某个回答
- 记录每个玩家的成功接龙次数
# 项目概览
## 项目结构
```
WPSBotGame/
├── app.py # FastAPI主应用
├── config.py # 配置管理
├── core/
│ ├── database.py # SQLite数据库操作
│ ├── middleware.py # 中间件
│ └── models.py # 数据模型
├── games/ # 游戏模块
│ ├── base.py # 游戏基类
│ ├── dice.py # 骰娘游戏
│ ├── rps.py # 石头剪刀布
│ ├── fortune.py # 运势占卜
│ ├── guess.py # 猜数字
│ └── quiz.py # 问答游戏
├── data/ # 数据文件
│ ├── bot.db # SQLite数据库
│ ├── quiz.json # 问答题库
│ └── fortunes.json # 运势数据
├── routers/ # 路由处理
│ ├── callback.py # WPS回调处理
│ └── health.py # 健康检查
└── utils/ # 工具模块
├── message.py # 消息发送
├── parser.py # 指令解析
└── rate_limit.py # 限流控制
```
## 技术栈
- FastAPIWeb框架
- SQLite数据存储
- WPS协作机器人API消息接收与发送
## 现有游戏架构
1. 所有游戏继承`BaseGame`基类
2. 必须实现`handle(command, chat_id, user_id)`方法处理指令
3. 必须实现`get_help()`方法返回帮助信息
4. 游戏状态存储在数据库`game_states`表:`(chat_id, user_id, game_type)`作为联合主键
5. 游戏统计存储在`game_stats`表:记录`wins`, `losses`, `draws`, `total_plays`
6. 指令通过`CommandParser`解析,在`callback.py`中分发到对应游戏处理器
## 数据库设计
### game_states表
- chat_id: 会话ID
- user_id: 用户ID
- game_type: 游戏类型
- state_data: JSON格式的游戏状态数据
- created_at/updated_at: 时间戳
### game_stats表
- user_id: 用户ID
- game_type: 游戏类型
- wins/losses/draws/total_plays: 统计数据
# 分析
## 关键技术挑战
### 1. 群级别vs个人级别状态管理
现有游戏(猜数字、问答)都是个人独立状态,使用`(chat_id, user_id, game_type)`作为主键。
成语接龙是群内共享游戏,需要:
- 群级别的游戏状态:当前成语、已用成语列表、接龙长度、当前轮到谁
- 个人级别的统计:每个玩家的成功接龙次数
**可能方案:**
- 使用特殊user_id如0或-1存储群级别游戏状态
- 或者在state_data中存储所有玩家信息
### 2. 成语词库准备
需要准备:
- 成语列表至少500-1000个常用成语
- 每个成语的拼音信息(用于判断接龙是否匹配)
- 数据格式JSON文件类似quiz.json
### 3. 拼音匹配逻辑
- 需要拼音库支持pypinyin
- 支持谐音匹配(声母韵母匹配)
- 处理多音字情况
### 4. 裁判指令设计
需要额外指令:
- `.idiom accept` - 接受上一个回答
- `.idiom reject` - 拒绝上一个回答
- 需要权限控制(谁可以当裁判?)
### 5. 游戏流程设计
```
1. 开始游戏:.idiom start
- 机器人随机给出起始成语
- 创建群级别游戏状态
2. 玩家接龙:.idiom [成语]
- 检查是否在词库中
- 检查拼音是否匹配(首字拼音 == 上一个成语尾字拼音)
- 检查是否已使用过
- 自动判断或等待裁判确认
3. 裁判操作:.idiom accept/reject
- 手动接受或拒绝最近的回答
4. 查看状态:.idiom status
- 显示当前成语、已用成语数量、参与人数
5. 结束游戏:.idiom stop
- 显示统计信息
- 更新每个玩家的game_stats
```
## 现有代码分析
### CommandParser (utils/parser.py)
需要添加成语接龙指令映射:
```python
'.idiom': 'idiom',
'.成语接龙': 'idiom',
```
### callback.py (routers/callback.py)
需要在`handle_command`函数中添加idiom游戏分支
```python
if game_type == 'idiom':
from games.idiom import IdiomGame
game = IdiomGame()
return await game.handle(command, chat_id, user_id)
```
### base.py (games/base.py)
需要更新`get_help_message()``get_stats_message()`,添加成语接龙信息。
### config.py
可能需要添加成语接龙相关配置:
```python
"idiom": {
"auto_judge": True, # 是否自动判断
"require_approval": False, # 是否需要裁判确认
}
```
# 提议的解决方案
待INNOVATE模式填写
# 当前执行步骤:"1. 创建任务文件"
# 任务进度
## [2025-10-28 15:45:00]
- 已修改requirements.txt, config.py, utils/parser.py, routers/callback.py, games/base.py
- 已创建games/idiom.py
- 更改:
1. 在requirements.txt中添加pypinyin==0.51.0依赖
2. 在config.py的GAME_CONFIG中添加idiom配置起始成语池、历史显示数量
3. 在utils/parser.py的COMMAND_MAP中添加.idiom、.成语接龙、.成语指令映射
4. 创建games/idiom.py实现完整的成语接龙游戏逻辑
- IdiomGame类继承BaseGame
- 实现handle()主指令分发方法
- 实现_start_game()开始游戏
- 实现_make_chain()玩家接龙
- 实现_set_next_user()指定下一位
- 实现_reject_idiom()裁判拒绝
- 实现_show_status()显示状态
- 实现_show_blacklist()显示黑名单
- 实现_stop_game()结束游戏
- 实现_get_pinyin()获取拼音(支持多音字)
- 实现_check_pinyin_match()检查拼音匹配(忽略声调)
- 实现_parse_mentioned_user()解析@用户
- 实现_can_answer()权限检查(防连续、指定轮次)
- 实现_validate_idiom()词语验证4字、拼音匹配、未使用、未黑名单
- 实现get_help()帮助信息
5. 在routers/callback.py的handle_command()中添加idiom游戏分支
6. 在games/base.py的get_help_message()中添加成语接龙帮助信息
7. 在games/base.py的get_stats_message()的game_names字典中添加idiom映射
- 原因:实现成语接龙游戏功能的所有核心代码
- 阻碍因素:无
- 状态:未确认
## [2025-10-28 15:50:00]
- 已修改games/base.py
- 更改在get_help_message()的成语接龙部分添加黑名单相关指令说明
- 添加 `.idiom reject [词语]` - 拒绝词语加入黑名单(仅发起人)
- 添加 `.idiom blacklist` - 查看黑名单
- 原因:用户反馈.help帮助信息中看不到黑名单机制的使用说明
- 阻碍因素:无
- 状态:未确认
## [2025-10-28 15:55:00]
- 已修改games/idiom.py
- 已创建data/idiom_blacklist.json
- 更改:将黑名单机制从游戏状态改为全局永久存储
1. 创建data/idiom_blacklist.json作为全局黑名单数据文件
2. 在IdiomGame.__init__()中添加黑名单文件路径和懒加载变量
3. 添加_load_blacklist()方法从文件懒加载全局黑名单
4. 添加_save_blacklist()方法保存黑名单到文件
5. 修改_validate_idiom()方法检查全局黑名单而非游戏状态中的黑名单
6. 修改_start_game()方法移除state_data中的blacklist字段初始化
7. 修改_reject_idiom()方法将词语添加到全局黑名单并保存到文件
8. 修改_show_blacklist()方法显示全局黑名单,不再依赖游戏状态
9. 更新所有提示信息,明确说明是"永久禁用"
- 原因:用户要求被拒绝的词语应该永久不可用,而不是仅本局游戏不可用
- 阻碍因素:无
- 状态:未确认
# 最终审查
待REVIEW模式完成后填写