# 狼人杀 · Werewolf 一个 **网页联机狼人杀框架**:FastAPI + WebSocket 后端,React + TypeScript + Sass 前端, 支持 **真人玩家与 AI 玩家混合对局**,人数与板子可选,多人从不同浏览器/设备加入同一房间。 ![技术栈](https://img.shields.io/badge/FastAPI-WebSocket-009688) ![前端](https://img.shields.io/badge/React-TypeScript Sass Vite-61dafb) ![环境](https://img.shields.io/badge/uv-pnpm-管理) ## 功能特性 - **人机混战**:真人玩家占座后,空位一键补满 AI;也可以全部由 AI 对战观战 - **真正的多人联机**:房间码制,局域网/公网多设备加入,断线自动重连不掉座 - **经典板子**: - 经典 12 人局(4 狼 4 民 预言家/女巫/猎人/守卫) - 标准 10 人局(3 狼 3 民 预女猎守) - 快节奏 9 人局(3 狼 3 民 预女猎) - **完整规则**:守卫守护(不可连守)→ 狼人刀人 → 预言家验人 → 女巫双药(首夜可自救、同守同救会死) → 警长竞选(警长 1.5 票、警徽流转、可撕徽)→ 白天发言 → 投票放逐 → 猎人开枪 → 屠边/屠城胜负判定 - **AI 玩家(LLM 驱动)**:接入任意 OpenAI 兼容大模型(DeepSeek / 智谱 / Kimi / OpenAI / 本地 Ollama …), AI 有人设性格、第一人称发言、夜间决策与投票;**未配置密钥时自动回退内置启发式 AI,开箱即玩** - **网页界面**:座位圈、阶段横幅与倒计时、个人私密信息面板(身份/狼队友/查验/药水)、公开+私密对局记录、 按阶段切换的行动面板、结算复盘弹窗 - **亮/暗主题**:默认清爽浅色(白底 + 靛蓝主色),右上角 🌙/☀️ 一键切换暗色(深蓝灰),选择自动记忆 ## 快速开始 ### 环境要求 - [uv](https://docs.astral.sh/uv/)(管理 Python 后端环境,会自动安装 Python 解释器) - [pnpm](https://pnpm.io/) + Node.js 18+(管理前端) ### 方式一:单进程游玩(推荐) ```bash # 1. 构建前端 cd frontend pnpm install pnpm build # 2. 启动后端(自动托管前端构建产物) cd ../backend uv sync uv run python run.py ``` 打开 **http://127.0.0.1:8000** —— 填昵称、创建房间、把房间号发给朋友, 各自浏览器打开后输入房间号加入,空位补 AI,开始游戏。 > 局域网联机:同一 WiFi 下的朋友访问 `http://<你的IP>:8000` 即可。 ### 方式二:前端开发模式(热更新) ```bash # 终端 1:后端 cd backend && uv sync && uv run uvicorn app.main:app --port 8000 # 终端 2:前端(Vite 会把 /api 与 /ws 代理到 8000 端口) cd frontend && pnpm install && pnpm dev ``` 打开 http://127.0.0.1:5173。 ## 接入大模型 AI(可选) ```bash cd backend cp config.example.json config.json # Windows: copy config.example.json config.json ``` 编辑 `config.json`,填入任意 OpenAI 兼容服务: ```json { "llm": { "base_url": "https://api.deepseek.com/v1", "api_key": "sk-xxxx", "model": "deepseek-chat", "temperature": 0.8 } } ``` 常见服务商的 `base_url`: | 服务商 | base_url | 模型示例 | |---|---|---| | DeepSeek | `https://api.deepseek.com/v1` | `deepseek-chat` | | 智谱 GLM | `https://open.bigmodel.cn/api/paas/v4` | `glm-4-flash` | | Moonshot Kimi | `https://api.moonshot.cn/v1` | `moonshot-v1-8k` | | OpenAI | `https://api.openai.com/v1` | `gpt-4o-mini` | | 本地 Ollama | `http://localhost:11434/v1` | `qwen2.5:7b` | - 也可用环境变量覆盖:`WEREWOLF_LLM_BASE_URL` / `WEREWOLF_LLM_API_KEY` / `WEREWOLF_LLM_MODEL` - **不配置或配置错误都不会影响游戏**:AI 自动回退到内置启发式逻辑(调用失败也会单次降级,不会卡局) - 大厅页底部会显示当前 AI 状态(大模型已接入 / 启发式 AI) ## 房间操作说明 | 操作 | 说明 | |---|---| | 创建房间 | 大厅点击「创建房间」生成 4 位房间码,创建者成为房主 | | 加入房间 | 输入房间号加入,自动分配空座位;对局中进入则为观战 | | 补 AI | 房主可「+ 添加 AI」逐个加,或「⚡ 一键补满 AI」 | | 开始游戏 | 座位满员后房主点击「开始游戏」,私发身份 | | 断线重连 | 刷新/断网后重新进入同一房间自动回到原座位(对局中为观战) | | 再来一局 | 结算后房主点击「回到房间」,全员身份重置回大厅 | ## 游戏规则细节 - **夜晚顺序**:守卫 → 狼人(狼队互相可见,先选的刀口生效)→ 预言家 → 女巫 - **女巫**:解药/毒药各一瓶,每夜限用一瓶;首夜可自救;同守同救会死 - **警长**:首日竞选,警长票计 1.5 票;警长死亡可移交警徽或撕徽 - **猎人**:被刀或被放逐时可开枪,被毒杀不能开枪 - **放逐**:平票无人出局,不翻牌 - **胜负**:默认屠边(狼人杀光全部神职或全部村民即获胜),房主可切换屠城(狼数 ≥ 好人数) ## 项目结构 ``` ├── backend/ # uv 管理的 FastAPI 后端 │ ├── pyproject.toml │ ├── config.example.json # 复制为 config.json 接入大模型 │ ├── run.py # 启动入口 │ ├── smoke_test.py # 纯 AI 完整对局冒烟测试 │ ├── ws_test.py # 双真人 + AI 无头联机测试 │ ├── side_player.py # 加入指定房间自动玩的随从客户端 │ └── app/ │ ├── main.py # REST + WebSocket + 静态托管 │ ├── config.py # 配置加载 │ └── game/ │ ├── roles.py # 角色定义 │ ├── board.py # 板子预设 │ ├── player.py # 玩家实体 │ ├── room.py # 房间/连接管理/快照广播 │ ├── engine.py # 昼夜状态机引擎 │ └── ai/ # LLM 客户端、提示词、Agent、启发式兜底 └── frontend/ # pnpm + Vite + React + TS + Sass 前端 ├── vite.config.ts # dev 代理 /api /ws └── src/ ├── pages/ # Lobby 大厅 / Room 房间 ├── components/ # 座位圈/阶段横幅/行动面板/信息面板/日志/结算 ├── api/ws.ts # WebSocket 封装(自动重连) ├── types.ts # 与后端对齐的消息协议类型 └── styles/ # Sass 主题变量与全局样式 ``` ## 开发测试 ```bash cd backend uv run python smoke_test.py # 12 个内置 AI 完整对局 uv run python ws_test.py # 2 个程序化真人 + AI,覆盖建房/重连/重置 uv run python side_player.py 房间号 # 让一个自动玩家加入你的房间 ```