1+ import datetime
2+ import json
3+ import os
4+ import random
5+ import re
6+ import sqlite3
7+ from collections import Counter
8+ from typing import Any , Dict , Literal , Callable , List
9+
10+ import nonebot
11+ import requests
12+ import toml
13+ from nonebot import on_command
14+ from nonebot .adapters import Message
15+ from nonebot .adapters .onebot .v11 import (Bot , GroupMessageEvent ,
16+ PrivateMessageEvent )
17+ from nonebot .exception import ActionFailed
18+ from nonebot .params import CommandArg
19+ from nonebot .permission import SUPERUSER
20+
21+ from toolsbot .configs import DATA_PATH
22+ from toolsbot .services import _error , _info
23+ import plugins .userInfoController as uic
24+
25+ """
26+ RE: ToolsBot
27+ Tools Bot 的第二版。
28+
29+ @author: Latingtude
30+
31+ undefiendControllers.killers
32+ DEVIL ROUNDS
33+ """
34+
35+ TITLE = "RE: ToolsBot"
36+
37+ devil_rounds = on_command ("devilrounds" , aliases = {"恶魔轮盘" , "轮盘赌" }, priority = 5 , block = True )
38+
39+ # 游戏状态管理
40+ games : Dict [str , Dict ] = {} # 存储所有游戏实例
41+
42+ class DevilRoundsGame :
43+ def __init__ (self , group_id : str , players : List [uic .User ]):
44+ self .group_id = group_id
45+ self .players = players # 4个玩家
46+ self .current_player_index = 0
47+ self .shells = [] # 子弹列表,1为实弹,0为空包弹
48+ self .current_shell_index = 0
49+ self .items = {} # 玩家道具
50+ self .turn_count = 0
51+ self .game_over = False
52+ self .round = 1
53+ self .max_rounds = 5 # 最大回合数
54+
55+ # 初始化每个玩家的道具
56+ for player in self .players :
57+ self .items [player .id ] = []
58+
59+ def load_shells (self , live_count : int , blank_count : int ):
60+ """装填子弹"""
61+ self .shells = [1 ] * live_count + [0 ] * blank_count
62+ random .shuffle (self .shells )
63+ self .current_shell_index = 0
64+ _info (f"装填子弹: { live_count } 实弹, { blank_count } 空包弹" )
65+
66+ def get_current_player (self ) -> uic .User :
67+ """获取当前玩家"""
68+ return self .players [self .current_player_index ]
69+
70+ def next_player (self ):
71+ """切换到下一个玩家"""
72+ self .current_player_index = (self .current_player_index + 1 ) % len (self .players )
73+ if self .current_player_index == 0 :
74+ self .round += 1
75+
76+ def use_item (self , player : uic .User , item : str ) -> str :
77+ """使用道具"""
78+ if item not in self .items [player .id ]:
79+ return "你没有这个道具!"
80+
81+ self .items [player .id ].remove (item )
82+
83+ if item == "啤酒" :
84+ if self .current_shell_index >= len (self .shells ):
85+ return "枪膛里已经没有子弹了!"
86+ shell = self .shells .pop (self .current_shell_index )
87+ if shell == 1 :
88+ return "你用啤酒退出了一发实弹!"
89+ else :
90+ return "你用啤酒退出了一发空包弹!"
91+
92+ elif item == "手铐" :
93+ next_player = self .players [(self .current_player_index + 1 ) % len (self .players )]
94+ self .items [next_player .id ].append ("被手铐" )
95+ return f"你用手铐铐住了 { next_player .name } !"
96+
97+ elif item == "手锯" :
98+ self .items [player .id ].append ("手锯激活" )
99+ return "你使用了手锯,下次射击伤害翻倍!"
100+
101+ elif item == "香烟" :
102+ player .addScore (100 ) # 恢复生命值
103+ return "你使用了香烟,恢复了100点生命值!"
104+
105+ elif item == "放大镜" :
106+ if self .current_shell_index >= len (self .shells ):
107+ return "枪膛里已经没有子弹了!"
108+ shell_type = "实弹" if self .shells [self .current_shell_index ] == 1 else "空包弹"
109+ return f"你用放大镜看到了下一发是{ shell_type } !"
110+
111+ return "未知道具!"
112+
113+ def shoot (self , target : uic .User , self_shoot : bool = False ) -> str :
114+ """射击"""
115+ if self .current_shell_index >= len (self .shells ):
116+ return "枪膛里已经没有子弹了!"
117+
118+ shell = self .shells [self .current_shell_index ]
119+ self .current_shell_index += 1
120+
121+ damage = 2 if "手锯激活" in self .items [target .id ] else 1
122+
123+ # 检查是否被手铐
124+ if "被手铐" in self .items [target .id ]:
125+ self .items [target .id ].remove ("被手铐" )
126+ return f"{ target .name } 被手铐铐住了,无法行动!"
127+
128+ if self_shoot :
129+ # 向自己开枪
130+ if shell == 0 :
131+ # 空包弹
132+ self .next_player ()
133+ return f"{ target .name } 向自己开枪,是空包弹!获得额外回合!"
134+ else :
135+ # 实弹
136+ target .subtScore (damage * 100 ) # 扣除生命值
137+ if target .getScore () <= 0 :
138+ self .game_over = True
139+ return f"{ target .name } 向自己开枪,是实弹!受到{ damage * 100 } 点伤害,被淘汰了!"
140+ self .next_player ()
141+ return f"{ target .name } 向自己开枪,是实弹!受到{ damage * 100 } 点伤害!"
142+ else :
143+ # 向目标开枪
144+ if shell == 0 :
145+ # 空包弹
146+ self .next_player ()
147+ return f"{ target .name } 向 { self .get_current_player ().name } 开枪,是空包弹!"
148+ else :
149+ # 实弹
150+ target .subtScore (damage * 100 ) # 扣除生命值
151+ if target .getScore () <= 0 :
152+ self .game_over = True
153+ return f"{ target .name } 向 { self .get_current_player ().name } 开枪,是实弹!受到{ damage * 100 } 点伤害,被淘汰了!"
154+ self .next_player ()
155+ return f"{ target .name } 向 { self .get_current_player ().name } 开枪,是实弹!受到{ damage * 100 } 点伤害!"
156+
157+ def check_game_over (self ) -> bool :
158+ """检查游戏是否结束"""
159+ alive_players = [p for p in self .players if p .getScore () > 0 ]
160+ if len (alive_players ) <= 1 :
161+ self .game_over = True
162+ return True
163+ if self .round > self .max_rounds :
164+ self .game_over = True
165+ return True
166+ return False
167+
168+ def get_alive_players (self ) -> List [uic .User ]:
169+ """获取存活玩家"""
170+ return [p for p in self .players if p .getScore () > 0 ]
171+
172+ def get_game_status (self ) -> str :
173+ """获取游戏状态"""
174+ status = f"=== devilrounds (第{ self .round } 回合) ===\n "
175+ status += f"当前玩家: { self .get_current_player ().name } \n "
176+ status += f"剩余子弹: { len (self .shells ) - self .current_shell_index } 发\n "
177+ status += "存活玩家:\n "
178+ for player in self .get_alive_players ():
179+ status += f"- { player .name } : { player .getScore ()} 分\n "
180+ return status
181+
182+ @devil_rounds .handle ()
183+ async def handle_devil_rounds (bot : Bot , event : GroupMessageEvent , args : Message = CommandArg ()):
184+ group_id = str (event .group_id )
185+ user_id = str (event .user_id )
186+
187+ # 检查是否已有游戏
188+ if group_id in games :
189+ game = games [group_id ]
190+ if not game .game_over :
191+ await devil_rounds .finish ("RE: ToolsBot - DEVILROUNDS\n - 当前已有进行中的游戏!" )
192+
193+ # 解析命令参数
194+ msg = args .extract_plain_text ().strip ()
195+ if msg == "开始" :
196+ # 开始新游戏
197+ if len (uic .At (event .json ())) < 4 :
198+ await devil_rounds .finish ("RE: ToolsBot - DEVILROUNDS\n - 至少需要4个玩家参与游戏!" )
199+
200+ player_ids = uic .At (event .json ())
201+ players = []
202+ for pid in player_ids :
203+ user = uic .User (pid )
204+ if user .isBanned ():
205+ await devil_rounds .finish (f"RE: ToolsBot - DEVILROUNDS\n - 玩家 { user .name } 已被封禁,无法参与游戏!" )
206+ players .append (user )
207+
208+ # 创建新游戏
209+ game = DevilRoundsGame (group_id , players )
210+ games [group_id ] = game
211+
212+ # 随机装填第一轮子弹
213+ game .load_shells (random .randint (2 , 4 ), random .randint (2 , 4 ))
214+
215+ await devil_rounds .send (f"RE: ToolsBot - DEVILROUNDS\n - DEVILROUNDS 开始!\n { game .get_game_status ()} \n 请 { game .get_current_player ().name } 选择行动:\n 1. 向自己开枪\n 2. 向其他人开枪\n 3. 使用道具" )
216+
217+ elif msg .startswith ("射击" ):
218+ # 射击命令
219+ if group_id not in games :
220+ await devil_rounds .finish ("当前没有进行中的游戏!" )
221+
222+ game = games [group_id ]
223+ current_player = game .get_current_player ()
224+
225+ if user_id != current_player .id :
226+ await devil_rounds .finish (f"RE: ToolsBot - DEVILROUNDS\n - 现在不是你的回合!当前是 { current_player .name } 的回合。" )
227+
228+ # 解析射击目标
229+ parts = msg .split ()
230+ if len (parts ) < 2 :
231+ await devil_rounds .finish ("RE: ToolsBot - DEVILROUNDS\n - 请指定射击目标!例如:射击 自己 或 射击 玩家名" )
232+
233+ target_name = parts [1 ]
234+ if target_name == "自己" :
235+ result = game .shoot (current_player , self_shoot = True )
236+ else :
237+ # 查找目标玩家
238+ target = None
239+ for player in game .players :
240+ if player .name == target_name :
241+ target = player
242+ break
243+
244+ if not target :
245+ await devil_rounds .finish (f"RE: ToolsBot - DEVILROUNDS\n - 找不到玩家 { target_name } !" )
246+
247+ result = game .shoot (target , self_shoot = False )
248+
249+ await devil_rounds .send (f"{ result } \n { game .get_game_status ()} " )
250+
251+ # 检查游戏是否结束
252+ if game .check_game_over ():
253+ alive_players = game .get_alive_players ()
254+ if len (alive_players ) == 1 :
255+ winner = alive_players [0 ]
256+ winner .addScore (1000 ) # 胜利奖励
257+ await devil_rounds .send (f"RE: ToolsBot - DEVILROUNDS\n - 游戏结束!{ winner .name } 获胜!获得1000分奖励!" )
258+ else :
259+ await devil_rounds .send ("RE: ToolsBot - DEVILROUNDS\n - 游戏结束!没有玩家存活!" )
260+
261+ # 保存玩家数据
262+ for player in game .players :
263+ player .save ()
264+
265+ # 移除游戏
266+ del games [group_id ]
267+
268+ elif msg .startswith ("道具" ):
269+ # 使用道具命令
270+ if group_id not in games :
271+ await devil_rounds .finish ("RE: ToolsBot - DEVILROUNDS\n - 当前没有进行中的游戏!" )
272+
273+ game = games [group_id ]
274+ current_player = game .get_current_player ()
275+
276+ if user_id != current_player .id :
277+ await devil_rounds .finish (f"RE: ToolsBot - DEVILROUNDS\n - 现在不是你的回合!当前是 { current_player .name } 的回合。" )
278+
279+ parts = msg .split ()
280+ if len (parts ) < 2 :
281+ await devil_rounds .finish ("RE: ToolsBot - DEVILROUNDS\n - 请指定要使用的道具!例如:道具 啤酒" )
282+
283+ item_name = parts [1 ]
284+ result = game .use_item (current_player , item_name )
285+ await devil_rounds .send (f"{ result } \n { game .get_game_status ()} " )
286+
287+ elif msg == "状态" :
288+ # 查看游戏状态
289+ if group_id not in games :
290+ await devil_rounds .finish ("RE: ToolsBot - DEVILROUNDS\n - 当前没有进行中的游戏!" )
291+
292+ game = games [group_id ]
293+ await devil_rounds .send (game .get_game_status ())
294+
295+ elif msg == "退出" :
296+ # 退出游戏
297+ if group_id not in games :
298+ await devil_rounds .finish ("RE: ToolsBot - DEVILROUNDS\n - 当前没有进行中的游戏!" )
299+
300+ game = games [group_id ]
301+ current_player = game .get_current_player ()
302+
303+ if user_id != current_player .id :
304+ await devil_rounds .finish (f"RE: ToolsBot - DEVILROUNDS\n - 现在不是你的回合!当前是 { current_player .name } 的回合。" )
305+
306+ # 保存玩家数据
307+ for player in game .players :
308+ player .save ()
309+
310+ # 移除游戏
311+ del games [group_id ]
312+ await devil_rounds .send ("RE: ToolsBot - DEVILROUNDS\n - 退出游戏" )
313+
314+ else :
315+ # 显示帮助信息
316+ await devil_rounds .send (
317+ "RE: ToolsBot - DEVILROUNDS 游戏帮助\n "
318+ " - devilrounds 开始 <玩家1> <玩家2> <玩家3> <玩家4> - 开始新游戏\n "
319+ " - devilrounds 射击 <目标> - 向目标开枪(目标可以是'自己'或其他玩家名)\n "
320+ " - devilrounds 道具 <道具名> - 使用道具(啤酒、手铐、手锯、香烟、放大镜)\n "
321+ " - devilrounds 状态 - 查看游戏状态\n "
322+ " - devilrounds 退出 - 退出当前游戏"
323+ )
0 commit comments