Skip to content

Commit fcb4236

Browse files
committed
commit #2
1 parent b4260ca commit fcb4236

7 files changed

+210
-73
lines changed

baseplayer.py

+25-7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def __init__(self, group_id):
4040
self.acceptedplayers = ()
4141
self.commands = dict()
4242
self.commandparsers = dict()
43+
self.gameended = False
4344

4445
def addplayer(self, sender):
4546
raise NotImplementedError
@@ -76,11 +77,21 @@ def resume(self):
7677
try:
7778
return next(self._game)
7879
except StopIteration:
79-
print("游戏结束") # TODO
80+
self.gameended = True
8081
return None
8182

8283
def addprivatemsg(self, player, msg):
83-
self.messages.append(({"user_id": player.user_id}, msg))
84+
if isinstance(player, int):
85+
user_id = player
86+
elif isinstance(player, BasePlayer):
87+
user_id = player.user_id
88+
else:
89+
raise ValueError
90+
91+
# Debug: 添加玩家QQ号在消息前
92+
# msg = f"[{user_id}] {msg}"
93+
94+
self.messages.append(({"user_id": user_id}, msg))
8495

8596
def addprivatemsgforall(self, msg):
8697
for p in self.players:
@@ -107,9 +118,9 @@ def acceptcommandfrom(self, acceptedplayers, commandparsers):
107118
# acceptedplayers = acceptedplayers
108119
pass
109120
else:
110-
raise NotImplementedError
121+
raise ValueError
111122

112-
self.acceptedplayers = (p.user_id for p in acceptedplayers) # 转换为QQ号(int)
123+
self.acceptedplayers = tuple(p.user_id for p in acceptedplayers) # 转换为QQ号(int)
113124
acceptedplayers = None # Debug: 防止下面代码误用
114125

115126
self.commands = dict.fromkeys(self.acceptedplayers, None) # 清空指令缓存
@@ -123,7 +134,7 @@ def acceptcommandfrom(self, acceptedplayers, commandparsers):
123134
raise ValueError
124135
self.commandparsers = dict(zip(self.acceptedplayers, commandparsers))
125136
else:
126-
raise NotImplementedError
137+
raise ValueError
127138

128139
def handlemessage(self, context):
129140
raise NotImplementedError
@@ -141,5 +152,12 @@ def playerstringat(self, player_ids):
141152
if isinstance(player_ids, int):
142153
return self.getplayerbyid(player_ids).string
143154

144-
player_ids = list(player_ids).sort()
145-
return "\n".join((self.getplayerbyid(player_id) for player_id in player_ids))
155+
player_ids = list(player_ids)
156+
player_ids.sort()
157+
return "\n".join(
158+
(self.getplayerbyid(player_id).string for player_id in player_ids)
159+
)
160+
161+
def __contains__(self, user_id):
162+
"""判断QQ号是否是本局游戏的玩家。"""
163+
return user_id in (p.user_id for p in self.players)

bot.py

+62-31
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,86 @@
1+
import asyncio
2+
from defaultdict import DefaultDict
3+
14
from aiocqhttp import CQHttp
25

36
from theresistance import TheResistanceCampaign
47

58
bot = CQHttp(enable_http_post=False)
9+
group_message_handler = DefaultDict(default_group_message_handler)
10+
private_message_handler = DefaultDict(default_private_message_handler)
11+
campaigns = dict()
12+
13+
14+
def default_group_message_handler(context):
15+
at_me = f"[CQ:at,qq={context['self_id']}]"
16+
message = context["message"]
17+
group_id = context["group_id"]
18+
user_id = context["user_id"]
19+
20+
# 忽略没有at机器人的消息
21+
if at_me not in message:
22+
return
23+
24+
# 忽略已经在其他群进行游戏的QQ号消息,防止无法确定私聊消息应该交给哪个游戏处理
25+
if user_id in private_message_handler:
26+
return {"reply": "你已经在其它群的游戏中了……"} # TODO:文字移到外部json文件中
27+
28+
# 预先防止群内已有游戏进行,但此代码应该不会被执行,因为后续群消息应该都交给其它message_handler处理了
29+
if group_id in group_message_handler:
30+
print("This line of code should not be excecuted. Please check.")
31+
return
32+
33+
# 抵抗组织
34+
if "抵抗组织" in message: # TODO:文字移到外部json文件中
35+
campaign = TheResistanceCampaign(group_id)
36+
campaigns[group_id] = campaign
37+
campaign.addplayer(context["sender"])
38+
name = campaign.players[0].name
39+
group_message_handler[group_id] = campaign.handlemessage
40+
private_message_handler[user_id] = campaign.handlemessage
41+
return {"reply": f"{name}发起了抵抗组织游戏,发送“加入游戏”来参与吧!"} # TODO:文字移到外部json文件中
42+
43+
44+
def default_private_message_handler(context):
45+
pass
646

747

848
@bot.on_message()
949
async def handle_msg(context):
10-
pass
11-
# print(context)
12-
# if context["user_id"] == 498533576:
13-
# await bot.send({"user_id": 498533576}, "Hello!")
14-
50+
print(context) # Debug
1551

16-
def test_setup():
17-
from time import sleep
52+
# TODO: 添加游戏结束后移除message_handler的代码
1853

19-
campaign = TheResistanceCampaign(719231968)
20-
campaign.addplayer({"nickname": "一号玩家", "user_id": 498533576})
21-
campaign.addplayer({"nickname": "二号玩家", "user_id": 498533576})
22-
campaign.addplayer({"nickname": "三号玩家", "user_id": 498533576})
23-
campaign.addplayer({"nickname": "四号玩家", "user_id": 498533576})
24-
campaign.addplayer({"nickname": "五号玩家", "user_id": 498533576})
25-
campaign.addplayer({"nickname": "六号玩家", "user_id": 498533576})
26-
sendmessages(campaign.resume())
54+
if context["message_type"] == "private":
55+
ret = private_message_handler[context["user_id"]](context)
56+
elif context["message_type"] == "group":
57+
ret = group_message_handler[context["group_id"]](context)
58+
else:
59+
print("Unknown message type. Please check.")
60+
return
2761

28-
sleep(5)
62+
if isinstance(ret, dict) and "reply" in ret:
63+
return ret
64+
elif ret is None:
65+
return
66+
elif isinstance(ret, list):
67+
await sendmessages(ret)
2968

3069

31-
def sendmessages(messages):
32-
import threading
33-
34-
print(messages)
70+
async def sendmessages(messages):
71+
coros = []
3572
for context, message in messages:
36-
threading.Thread(target=sendmessage, args=(context, message)).start()
37-
73+
# Debug: 去除QQ号后面添加的id
74+
# if "user_id" in context:
75+
# context["user_id"] = context["user_id"] // 10
3876

39-
def sendmessage(context, message):
40-
import asyncio
77+
coros.append(bot.send(context, message))
4178

42-
print()
43-
print(context)
44-
print(message)
45-
asyncio.run(bot.send(context, message))
79+
await asyncio.gather(*coros)
4680

4781

4882
if __name__ == "__main__":
49-
import threading
50-
5183
try:
52-
threading.Timer(5, test_setup).start()
5384
bot.run(host="127.0.0.1", port=8090)
5485
except KeyboardInterrupt:
5586
print("Exit.")

commandparser.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ def getnumberparser(include=None, exclude=None, commandnumber=1, maxnum=None):
1616
"""
1717
if include is None:
1818
include = set(range(1, maxnum + 1))
19+
if exclude is None:
20+
exclude = set()
1921
# if exclude is not None:
2022
# include -= set(exclude)
2123

2224
def commandparser(message: str):
23-
message = message.strip(" ,")
2425
pattern = (
2526
r"^[^\d]*"
2627
+ r"[,.\s\u3000\u3001\u3002\uFF0C\uFF1B\u548C]".join(

defaultdict.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class DefaultDict(dict):
2+
def __init__(self, defaultvalue=None, *args, **kwargs):
3+
dict.__init__(self, *args, **kwargs)
4+
self.defaultvalue = defaultvalue
5+
6+
def __getitem__(self, key):
7+
return self.get(key, self.defaultvalue)

test.py

+5-12
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,17 @@
33

44
class Test:
55
counter = count()
6+
allinstance = []
67

78
def __init__(self):
89
self.id = next(self.counter)
10+
self.allinstance.append(self.id)
911

10-
def __repr__(self):
11-
return f"Test({self.id})"
12-
13-
def __hash__(self):
14-
return hash(self.id)
12+
def __contains__(self, other):
13+
return other in self.allinstance
1514

1615

1716
if __name__ == "__main__":
1817
t1 = Test()
1918
t2 = Test()
20-
di = {t1: "t1", t2: "t2"}
21-
print(t1)
22-
print(t2)
23-
print(di)
24-
print(di[t1])
25-
print(t1 in di)
26-
print(0 in di)
19+
print(0 in t1)

theresistance.json

+20-5
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
"GAME_START": "游戏开始!",
99
"THIS_ROUND_STARTUP": "这一轮的任务首领是{player.name}。\n请在讨论后选择{missionplayernum}名玩家执行第{gameround}次任务。",
1010
"LEADER_CHOOSE_PLAYER": "请回复玩家前的数字选择执行任务的玩家:\n{}",
11-
"VOTE_LEADER_CHOOSE_PLAYER": "首领选择指派以下玩家执行任务,请投票选择是否通过:\n{}",
11+
"VOTE_LEADER_CHOOSE_PLAYER": "首领选择指派以下玩家执行任务,请投票选择是否通过:\n{missionplayers}\n这是此项任务的第{votecount}次投票。",
1212
"INVALID_MESSAGE": "没看懂你在说啥……",
1313
"DUPLICATED_NUMBERS": "请不要选择重复的玩家。",
14+
"COMMAND_RECEIVED": "收到!",
1415
"VOTE_AGREE": [
1516
".y",
1617
"同意",
@@ -19,12 +20,26 @@
1920
],
2021
"VOTE_DISAGREE": [
2122
".n",
22-
"不同意",
23-
"不通过",
24-
"不是",
23+
"",
2524
""
2625
],
2726
"VOTE_BEGIN": "请回复是否通过这一轮的投票。",
2827
"VOTE_NOT_PASSED": "这一轮投票未被通过,请继续讨论并由下一位首领选择执行任务的玩家。",
29-
"VOTE_PASSED": "投票通过!"
28+
"VOTE_PASSED": "投票通过!请以上玩家准备执行任务……",
29+
"MISSION_VOTE_1": "准备执行第{gameround}次任务,请回复是否配合此次任务执行,注意只要有一位玩家不配合,此次任务就失败。",
30+
"MISSION_VOTE_2": "准备执行第{gameround}次任务,请回复是否配合此次任务执行,注意本任务两位玩家不配合才视为失败。",
31+
"MISSION_COOP": [
32+
".y",
33+
"配合",
34+
""
35+
],
36+
"MISSION_NOT_COOP": [
37+
".n",
38+
"",
39+
""
40+
],
41+
"MISSION_SUCCESS": "任务成功完成!",
42+
"MISSION_SUCCESS_WITH_1_NOTCOOP": "虽然有一票不配合,但是任务仍然成功完成!",
43+
"MISSION_FAIL": "任务失败,有{notcoop}位玩家选择了不配合。",
44+
"GAME_END": "游戏结束,{winners}阵营胜利!"
3045
}

0 commit comments

Comments
 (0)