diff --git a/.tasks/2025-11-03_2_werewolf-game.md b/.tasks/2025-11-03_2_werewolf-game.md index 9545a2c..1bdd4dc 100644 --- a/.tasks/2025-11-03_2_werewolf-game.md +++ b/.tasks/2025-11-03_2_werewolf-game.md @@ -319,6 +319,28 @@ if game_type == 'werewolf': - 状态:成功 +[2025-11-07_11:40:44] +- 已修改: + 1. games/werewolf.py - 新增空刀机制 + +- 更改: + 1. 允许狼人投票给0号(表示空刀,不杀人) + 2. 修改 _wolf_kill() 方法,对target_id=0不验证目标存在性 + 3. 修改投票确认消息,区分空刀和正常投票 + 4. 修改票数统计逻辑,投票0不计入击杀目标统计 + 5. 新增全部空刀处理:如果所有狼人都空刀,kill_target设为0(平安夜) + 6. 修改 _advance_phase() 为async,进入女巫阶段时私聊通知女巫刀人情况 + 7. 女巫有解药时可知道今晚是否有人被刀(0号为平安夜) + +- 原因: + 符合狼人杀游戏规则,狼人可以选择空刀(不杀人)。 + 女巫在有解药时需要知道今晚是否有人被刀以决定是否使用解药。 + +- 阻碍因素: + 无 + +- 状态:成功 + # 最终审查 待审查阶段完成... diff --git a/games/werewolf.py b/games/werewolf.py index e223be8..f89503e 100644 --- a/games/werewolf.py +++ b/games/werewolf.py @@ -258,7 +258,7 @@ class WerewolfGame(BaseGame): pass return None - def _advance_phase(self, chat_id: int, state_data: Dict) -> str: + async def _advance_phase(self, chat_id: int, state_data: Dict) -> str: """推进到下一阶段 Args: @@ -280,6 +280,22 @@ class WerewolfGame(BaseGame): state_data['phase'] = next_phase self._save_game_state(chat_id, state_data) + # 如果进入女巫阶段,且女巫有解药,通知女巫刀人情况 + if next_phase == 'night_witch': + # 检查女巫是否还有解药 + if not state_data.get('witch_save', False): + kill_target = state_data.get('kill_target') + + # 找到女巫并私聊通知 + for p in state_data['players']: + if p['role'] == 'witch' and p['alive']: + if kill_target == 0: + witch_info = f"## 🧪 女巫提示\n\n✨ 今晚是平安夜,没有人被刀" + else: + witch_info = f"## 🧪 女巫提示\n\n⚠️ 今晚 **{kill_target}号玩家** 被刀\n\n你可以选择救人、毒人或跳过" + await self._send_to_player(p['user_id'], witch_info, sender="系统") + break + # 获取下一阶段描述 next_phase_desc = self._get_phase_description(next_phase) @@ -707,18 +723,20 @@ class WerewolfGame(BaseGame): if not current_phase or not current_phase.startswith('night'): return "❌ 只能在夜晚使用技能!" - # 查找目标 - target = None - for p in state_data['players']: - if p['id'] == target_id: - target = p - break - - if not target: - return f"❌ 找不到{target_id}号玩家!" - - if not target['alive']: - return f"❌ {target_id}号玩家已死亡!" + # 0表示空刀,不验证目标 + if target_id != 0: + # 查找目标 + target = None + for p in state_data['players']: + if p['id'] == target_id: + target = p + break + + if not target: + return f"❌ 找不到{target_id}号玩家!" + + if not target['alive']: + return f"❌ {target_id}号玩家已死亡!" # 检查当前阶段 if current_phase != 'night_kill': @@ -743,17 +761,41 @@ class WerewolfGame(BaseGame): if not all_wolves.issubset(voted_wolves): # 还有狼人未投票,私聊通知投票者 not_voted_count = len(all_wolves - voted_wolves) - vote_confirm_msg = f"## 🐺 投票确认\n\n✅ 你投票给 **{target_id}号玩家**\n\n⏳ 等待其他狼人投票(还有{not_voted_count}个狼人未投票)" + if target_id == 0: + vote_confirm_msg = f"## 🐺 投票确认\n\n✅ 你选择 **空刀**(不杀人)\n\n⏳ 等待其他狼人投票(还有{not_voted_count}个狼人未投票)" + else: + vote_confirm_msg = f"## 🐺 投票确认\n\n✅ 你投票给 **{target_id}号玩家**\n\n⏳ 等待其他狼人投票(还有{not_voted_count}个狼人未投票)" await self._send_to_player(player['user_id'], vote_confirm_msg, sender="系统") # 群消息不透露目标 return f"✅ 投票已记录,等待其他狼人(还有{not_voted_count}个未投票)" - # 所有狼人都已投票,统计票数 + # 所有狼人都已投票,统计票数(忽略空刀) vote_count = {} + 空刀_count = 0 for wolf_id, target in wolf_votes.items(): if wolf_id in alive_wolves: # 只统计存活狼人的投票 - vote_count[target] = vote_count.get(target, 0) + 1 + if target == 0: + 空刀_count += 1 + else: + vote_count[target] = vote_count.get(target, 0) + 1 + + # 如果所有狼人都空刀,本晚无人被杀 + if not vote_count: # 没有有效投票 + state_data['kill_target'] = 0 # 0表示空刀 + state_data['wolf_votes'] = {} + self._save_game_state(chat_id, state_data) + + # 私聊通知所有狼人 + for p in state_data['players']: + if p['role'] == 'wolf' and p['alive']: + 空刀_msg = f"## 🐺 狼人投票结果\n\n✅ 所有狼人都选择空刀,今晚平安夜" + await self._send_to_player(p['user_id'], 空刀_msg, sender="系统") + + # 自动推进到下一阶段 + next_phase_msg = self._advance_phase(chat_id, state_data) + + return f"✅ 狼人投票完成{next_phase_msg}" # 找出票数最多的目标 max_votes = max(vote_count.values())