-
Notifications
You must be signed in to change notification settings - Fork 1
/
baseplayer.py
163 lines (129 loc) · 5.14 KB
/
baseplayer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import random
class BasePlayer:
ROLE = {"unassigned": "未分配身份"}
def __init__(self, sender):
self.user_id = sender["user_id"]
self.name = sender.get("card") or sender["nickname"]
self.role = "unassigned"
self.player_id = None
# def __hash__(self):
# return hash(self.user_id)
def assignrole(self, role):
self.role = role
@property
def rolename(self):
return self.ROLE[self.role]
@property
def string(self):
return f"[{self.player_id}] {self.name}"
@classmethod
def updaterolenames(cls, roles: dict):
cls.ROLE.update(roles)
class BaseCampaign:
PlayerConfig = dict()
def __init__(self, group_id):
self.group_id = group_id
self.players = []
self._game = self._start()
self.messages = []
self.acceptedplayers = ()
self.commands = dict()
self.commandparsers = dict()
self.gameended = False
def addplayer(self, sender):
raise NotImplementedError
@property
def playernum(self):
"""返回玩家数量"""
return len(self.players)
@property
def allplayerset(self):
"""返回是否已收到所有玩家的指令"""
return all((cmd is not None for cmd in self.commands.values()))
def assignroles(self):
"""给玩家分配角色,并打乱座次"""
if self.playernum not in self.PlayerConfig:
print("玩家数量不够或超出。") # TODO
return
roles = self.PlayerConfig[self.playernum].copy()
player_ids = list(range(1, self.playernum + 1))
random.shuffle(roles)
random.shuffle(player_ids)
for i, p in enumerate(self.players):
p.assignrole(roles[i])
p.player_id = player_ids[i]
self.players.sort(key=lambda p: p.player_id)
def _start(self):
yield NotImplemented
raise NotImplementedError
def resume(self):
try:
return next(self._game)
except StopIteration:
self.gameended = True
return None
def addprivatemsg(self, player, msg):
if isinstance(player, int):
user_id = player
elif isinstance(player, BasePlayer):
user_id = player.user_id
else:
raise ValueError
# Debug: 添加玩家QQ号在消息前
# msg = f"[{user_id}] {msg}"
self.messages.append(({"user_id": user_id}, msg))
def addprivatemsgforall(self, msg):
for p in self.players:
self.addprivatemsg(p, msg)
def addgroupmsg(self, msg):
self.messages.append(({"group_id": self.group_id}, msg))
def yieldmessages(self):
messages = self.messages
self.messages = []
return messages
def acceptcommandfrom(self, acceptedplayers, commandparsers):
"""设置允许接收指令的玩家。
Arguments:
acceptedplayers {str, iterable[Player]} -- 允许发送指令的玩家,'all'代表所有玩家
commandparsers {callable, iterable[callable]} -- 设置玩家指令的解析器,单个代表解析器设置给所有玩家
"""
if isinstance(acceptedplayers, str) and acceptedplayers == "all": # 所有玩家
acceptedplayers = self.players
elif isinstance(acceptedplayers, (set, tuple, list)): # 部分玩家
# acceptedplayers = acceptedplayers
pass
else:
raise ValueError
self.acceptedplayers = tuple(p.user_id for p in acceptedplayers) # 转换为QQ号(int)
acceptedplayers = None # Debug: 防止下面代码误用
self.commands = dict.fromkeys(self.acceptedplayers, None) # 清空指令缓存
if callable(commandparsers): # 单个解析器分配给所有acceptedplayers
self.commandparsers = dict.fromkeys(self.acceptedplayers, commandparsers)
elif isinstance(commandparsers, (tuple, list)): # 解析器列表按顺序分配给acceptedplayers
if len(self.acceptedplayers) != len(commandparsers): # 长度不匹配,抛出ValueError异常
raise ValueError
if isinstance(self.acceptedplayers, set): # 集合无顺序,抛出ValueError异常
raise ValueError
self.commandparsers = dict(zip(self.acceptedplayers, commandparsers))
else:
raise ValueError
def handlemessage(self, context):
raise NotImplementedError
@property
def allplayerstring(self):
return "\n".join((p.string for p in self.players))
def getplayerbyid(self, id):
for p in self.players:
if p.player_id == id:
return p
def playerstringat(self, player_ids):
if isinstance(player_ids, int):
return self.getplayerbyid(player_ids).string
player_ids = list(player_ids)
player_ids.sort()
return "\n".join(
(self.getplayerbyid(player_id).string for player_id in player_ids)
)
def __contains__(self, user_id):
"""判断QQ号是否是本局游戏的玩家。"""
return user_id in (p.user_id for p in self.players)