nonebot-plugin-werewolf 1.1.7__py3-none-any.whl → 1.1.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nonebot_plugin_werewolf/__init__.py +1 -1
- nonebot_plugin_werewolf/config.py +73 -15
- nonebot_plugin_werewolf/constant.py +54 -46
- nonebot_plugin_werewolf/exception.py +2 -4
- nonebot_plugin_werewolf/game.py +154 -136
- nonebot_plugin_werewolf/matchers/__init__.py +1 -0
- nonebot_plugin_werewolf/matchers/depends.py +4 -4
- nonebot_plugin_werewolf/matchers/edit_behavior.py +205 -0
- nonebot_plugin_werewolf/matchers/edit_preset.py +11 -11
- nonebot_plugin_werewolf/matchers/message_in_game.py +3 -1
- nonebot_plugin_werewolf/matchers/poke/chronocat_poke.py +8 -5
- nonebot_plugin_werewolf/matchers/poke/ob11_poke.py +3 -3
- nonebot_plugin_werewolf/matchers/start_game.py +213 -175
- nonebot_plugin_werewolf/matchers/superuser_ops.py +3 -3
- nonebot_plugin_werewolf/models.py +31 -19
- nonebot_plugin_werewolf/player_set.py +10 -8
- nonebot_plugin_werewolf/players/__init__.py +1 -1
- nonebot_plugin_werewolf/players/can_shoot.py +15 -15
- nonebot_plugin_werewolf/players/civilian.py +1 -1
- nonebot_plugin_werewolf/players/guard.py +16 -14
- nonebot_plugin_werewolf/players/hunter.py +1 -1
- nonebot_plugin_werewolf/players/idiot.py +3 -3
- nonebot_plugin_werewolf/players/{joker.py → jester.py} +4 -5
- nonebot_plugin_werewolf/players/player.py +90 -28
- nonebot_plugin_werewolf/players/prophet.py +11 -10
- nonebot_plugin_werewolf/players/werewolf.py +46 -11
- nonebot_plugin_werewolf/players/witch.py +29 -12
- nonebot_plugin_werewolf/players/wolfking.py +1 -1
- nonebot_plugin_werewolf/utils.py +105 -6
- {nonebot_plugin_werewolf-1.1.7.dist-info → nonebot_plugin_werewolf-1.1.8.dist-info}/METADATA +23 -20
- nonebot_plugin_werewolf-1.1.8.dist-info/RECORD +35 -0
- {nonebot_plugin_werewolf-1.1.7.dist-info → nonebot_plugin_werewolf-1.1.8.dist-info}/WHEEL +1 -1
- nonebot_plugin_werewolf-1.1.7.dist-info/RECORD +0 -34
- {nonebot_plugin_werewolf-1.1.7.dist-info → nonebot_plugin_werewolf-1.1.8.dist-info}/LICENSE +0 -0
- {nonebot_plugin_werewolf-1.1.7.dist-info → nonebot_plugin_werewolf-1.1.8.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,205 @@
|
|
1
|
+
# ruff: noqa: FBT001
|
2
|
+
|
3
|
+
from typing import Annotated, NoReturn
|
4
|
+
|
5
|
+
from nonebot.internal.matcher import current_matcher
|
6
|
+
from nonebot.params import Depends
|
7
|
+
from nonebot.permission import SUPERUSER
|
8
|
+
from nonebot.typing import T_State
|
9
|
+
from nonebot_plugin_alconna import (
|
10
|
+
Alconna,
|
11
|
+
Args,
|
12
|
+
CommandMeta,
|
13
|
+
Subcommand,
|
14
|
+
UniMessage,
|
15
|
+
on_alconna,
|
16
|
+
)
|
17
|
+
|
18
|
+
from ..config import GameBehavior
|
19
|
+
|
20
|
+
GAME_BEHAVIOR_CACHE_KEY = "GAME_BEHAVIOR_CACHE_KEY"
|
21
|
+
|
22
|
+
|
23
|
+
def _behavior(state: T_State) -> GameBehavior:
|
24
|
+
if GAME_BEHAVIOR_CACHE_KEY not in state:
|
25
|
+
state[GAME_BEHAVIOR_CACHE_KEY] = GameBehavior.get()
|
26
|
+
return state[GAME_BEHAVIOR_CACHE_KEY]
|
27
|
+
|
28
|
+
|
29
|
+
Behavior = Annotated[GameBehavior, Depends(_behavior)]
|
30
|
+
|
31
|
+
|
32
|
+
async def finish(text: str) -> NoReturn:
|
33
|
+
behavior: GameBehavior = current_matcher.get().state[GAME_BEHAVIOR_CACHE_KEY]
|
34
|
+
behavior.save()
|
35
|
+
await UniMessage.text(text).finish(reply_to=True)
|
36
|
+
|
37
|
+
|
38
|
+
alc = Alconna(
|
39
|
+
"狼人杀配置",
|
40
|
+
Subcommand(
|
41
|
+
"show_roles",
|
42
|
+
Args["enabled#是否启用", bool],
|
43
|
+
alias={"显示职业"},
|
44
|
+
help_text="设置游戏开始时是否显示职业列表",
|
45
|
+
),
|
46
|
+
Subcommand(
|
47
|
+
"speak_order",
|
48
|
+
Args["enabled#是否启用", bool],
|
49
|
+
alias={"发言顺序"},
|
50
|
+
help_text="设置是否按顺序发言",
|
51
|
+
),
|
52
|
+
Subcommand(
|
53
|
+
"dead_chat",
|
54
|
+
Args["limit#每分钟限制次数", int],
|
55
|
+
alias={"死亡聊天"},
|
56
|
+
help_text="设置死亡玩家发言频率限制",
|
57
|
+
),
|
58
|
+
Subcommand(
|
59
|
+
"timeout",
|
60
|
+
Subcommand(
|
61
|
+
"prepare",
|
62
|
+
Args["time#时间", int],
|
63
|
+
alias={"准备阶段"},
|
64
|
+
help_text="准备阶段超时时间(秒)",
|
65
|
+
),
|
66
|
+
Subcommand(
|
67
|
+
"speak",
|
68
|
+
Args["time#时间", int],
|
69
|
+
alias={"个人发言"},
|
70
|
+
help_text="个人发言超时时间(秒)",
|
71
|
+
),
|
72
|
+
Subcommand(
|
73
|
+
"group_speak",
|
74
|
+
Args["time#时间", int],
|
75
|
+
alias={"集体发言"},
|
76
|
+
help_text="集体发言超时时间(秒)",
|
77
|
+
),
|
78
|
+
Subcommand(
|
79
|
+
"interact",
|
80
|
+
Args["time#时间", int],
|
81
|
+
alias={"交互阶段"},
|
82
|
+
help_text="交互阶段超时时间(秒)",
|
83
|
+
),
|
84
|
+
Subcommand(
|
85
|
+
"vote",
|
86
|
+
Args["time#时间", int],
|
87
|
+
alias={"投票阶段"},
|
88
|
+
help_text="投票阶段超时时间(秒)",
|
89
|
+
),
|
90
|
+
Subcommand(
|
91
|
+
"werewolf",
|
92
|
+
Args["time#时间", int],
|
93
|
+
alias={"狼人交互"},
|
94
|
+
help_text="狼人交互超时时间(秒)",
|
95
|
+
),
|
96
|
+
alias={"超时"},
|
97
|
+
help_text="设置各阶段超时时间",
|
98
|
+
),
|
99
|
+
meta=CommandMeta(
|
100
|
+
description="修改狼人杀游戏配置",
|
101
|
+
usage="狼人杀配置 --help",
|
102
|
+
example=(
|
103
|
+
"狼人杀配置\n"
|
104
|
+
"狼人杀配置 显示职业 true\n"
|
105
|
+
"狼人杀配置 发言顺序 false\n"
|
106
|
+
"狼人杀配置 死亡聊天 30\n"
|
107
|
+
"狼人杀配置 超时 准备 300"
|
108
|
+
),
|
109
|
+
),
|
110
|
+
)
|
111
|
+
|
112
|
+
edit_behavior = on_alconna(
|
113
|
+
alc,
|
114
|
+
permission=SUPERUSER,
|
115
|
+
use_cmd_start=True,
|
116
|
+
)
|
117
|
+
|
118
|
+
|
119
|
+
@edit_behavior.assign("show_roles")
|
120
|
+
async def set_show_roles(behavior: Behavior, enabled: bool) -> None:
|
121
|
+
behavior.show_roles_list_on_start = enabled
|
122
|
+
await finish(f"已{'启用' if enabled else '禁用'}游戏开始时显示职业列表")
|
123
|
+
|
124
|
+
|
125
|
+
@edit_behavior.assign("speak_order")
|
126
|
+
async def set_speak_order(behavior: Behavior, enabled: bool) -> None:
|
127
|
+
behavior.speak_in_turn = enabled
|
128
|
+
await finish(f"已{'启用' if enabled else '禁用'}按顺序发言")
|
129
|
+
|
130
|
+
|
131
|
+
@edit_behavior.assign("dead_chat")
|
132
|
+
async def set_dead_chat(behavior: Behavior, limit: int) -> None:
|
133
|
+
if limit < 0:
|
134
|
+
await finish("限制次数必须大于零")
|
135
|
+
behavior.dead_channel_rate_limit = limit
|
136
|
+
await finish(f"已设置死亡玩家发言限制为 {limit} 次/分钟")
|
137
|
+
|
138
|
+
|
139
|
+
@edit_behavior.assign("timeout.prepare")
|
140
|
+
async def set_prepare_timeout(behavior: Behavior, time: int) -> None:
|
141
|
+
if time < 300:
|
142
|
+
await finish("准备时间必须大于 300 秒")
|
143
|
+
behavior.timeout.prepare = time
|
144
|
+
await finish(f"已设置准备阶段超时时间为 {time} 秒")
|
145
|
+
|
146
|
+
|
147
|
+
@edit_behavior.assign("timeout.speak")
|
148
|
+
async def set_speak_timeout(behavior: Behavior, time: int) -> None:
|
149
|
+
if time < 60:
|
150
|
+
await finish("发言时间必须大于 60 秒")
|
151
|
+
behavior.timeout.speak = time
|
152
|
+
await finish(f"已设置发言阶段超时时间为 {time} 秒")
|
153
|
+
|
154
|
+
|
155
|
+
@edit_behavior.assign("timeout.group_speak")
|
156
|
+
async def set_group_speak_timeout(behavior: Behavior, time: int) -> None:
|
157
|
+
if time < 120:
|
158
|
+
await finish("集体发言时间必须大于 120 秒")
|
159
|
+
behavior.timeout.group_speak = time
|
160
|
+
await finish(f"已设置集体发言超时时间为 {time} 秒")
|
161
|
+
|
162
|
+
|
163
|
+
@edit_behavior.assign("timeout.interact")
|
164
|
+
async def set_interact_timeout(behavior: Behavior, time: int) -> None:
|
165
|
+
if time < 60:
|
166
|
+
await finish("交互时间必须大于 60 秒")
|
167
|
+
behavior.timeout.interact = time
|
168
|
+
await finish(f"已设置交互阶段超时时间为 {time} 秒")
|
169
|
+
|
170
|
+
|
171
|
+
@edit_behavior.assign("timeout.vote")
|
172
|
+
async def set_vote_timeout(behavior: Behavior, time: int) -> None:
|
173
|
+
if time < 60:
|
174
|
+
await finish("投票时间必须大于 60 秒")
|
175
|
+
behavior.timeout.vote = time
|
176
|
+
await finish(f"已设置投票阶段超时时间为 {time} 秒")
|
177
|
+
|
178
|
+
|
179
|
+
@edit_behavior.assign("timeout.werewolf")
|
180
|
+
async def set_werewolf_timeout(behavior: Behavior, time: int) -> None:
|
181
|
+
if time < 120:
|
182
|
+
await finish("狼人交互时间必须大于 120 秒")
|
183
|
+
behavior.timeout.werewolf = time
|
184
|
+
await finish(f"已设置狼人交互阶段超时时间为 {time} 秒")
|
185
|
+
|
186
|
+
|
187
|
+
@edit_behavior.handle()
|
188
|
+
async def handle_default(behavior: Behavior) -> None:
|
189
|
+
timeout = behavior.timeout
|
190
|
+
lines = [
|
191
|
+
"当前游戏配置:",
|
192
|
+
"",
|
193
|
+
f"游戏开始发送职业列表: {'是' if behavior.show_roles_list_on_start else '否'}",
|
194
|
+
f"白天讨论按顺序发言: {'是' if behavior.speak_in_turn else '否'}",
|
195
|
+
f"死亡玩家发言转发限制: {behavior.dead_channel_rate_limit} 次/分钟",
|
196
|
+
"",
|
197
|
+
"超时时间设置:",
|
198
|
+
f"准备阶段: {timeout.prepare} 秒",
|
199
|
+
f"个人发言: {timeout.speak} 秒",
|
200
|
+
f"集体发言: {timeout.group_speak} 秒",
|
201
|
+
f"交互阶段: {timeout.interact} 秒",
|
202
|
+
f"投票阶段: {timeout.vote} 秒",
|
203
|
+
f"狼人交互: {timeout.werewolf} 秒",
|
204
|
+
]
|
205
|
+
await finish("\n".join(lines))
|
@@ -15,7 +15,7 @@ from nonebot_plugin_alconna import (
|
|
15
15
|
)
|
16
16
|
|
17
17
|
from ..config import PresetData
|
18
|
-
from ..constant import
|
18
|
+
from ..constant import ROLE_NAME_CONV
|
19
19
|
from ..models import Role
|
20
20
|
|
21
21
|
alc = Alconna(
|
@@ -82,7 +82,7 @@ async def finish(text: str) -> NoReturn:
|
|
82
82
|
|
83
83
|
|
84
84
|
def display_roles(roles: list[Role]) -> str:
|
85
|
-
role_name =
|
85
|
+
role_name = ROLE_NAME_CONV.__getitem__
|
86
86
|
return ", ".join(map(role_name, roles))
|
87
87
|
|
88
88
|
|
@@ -152,9 +152,9 @@ async def assign_werewolf(state: T_State) -> None:
|
|
152
152
|
for role in roles:
|
153
153
|
match role:
|
154
154
|
case "狼人" | "狼":
|
155
|
-
result.append(Role.
|
155
|
+
result.append(Role.WEREWOLF)
|
156
156
|
case "狼王":
|
157
|
-
result.append(Role.
|
157
|
+
result.append(Role.WOLFKING)
|
158
158
|
case x:
|
159
159
|
await finish(f"未知职业: {x}")
|
160
160
|
|
@@ -195,15 +195,15 @@ async def assign_priesthood(state: T_State) -> None:
|
|
195
195
|
for role in roles:
|
196
196
|
match role:
|
197
197
|
case "预言家" | "预言" | "预":
|
198
|
-
result.append(Role.
|
198
|
+
result.append(Role.PROPHET)
|
199
199
|
case "女巫" | "巫":
|
200
|
-
result.append(Role.
|
200
|
+
result.append(Role.WITCH)
|
201
201
|
case "猎人" | "猎":
|
202
|
-
result.append(Role.
|
202
|
+
result.append(Role.HUNTER)
|
203
203
|
case "守卫":
|
204
|
-
result.append(Role.
|
204
|
+
result.append(Role.GUARD)
|
205
205
|
case "白痴":
|
206
|
-
result.append(Role.
|
206
|
+
result.append(Role.IDIOT)
|
207
207
|
case x:
|
208
208
|
await finish(f"未知职业: {x}")
|
209
209
|
|
@@ -236,7 +236,7 @@ async def assign_joker(probability: Match[float]) -> None:
|
|
236
236
|
await finish("输入错误,概率应在 0 到 100 之间")
|
237
237
|
|
238
238
|
data = PresetData.load()
|
239
|
-
data.
|
239
|
+
data.jester_probability = probability.result / 100
|
240
240
|
data.save()
|
241
241
|
await finish(f"设置成功: 小丑概率 {probability.result:.1f}%")
|
242
242
|
|
@@ -258,6 +258,6 @@ async def handle_default() -> None:
|
|
258
258
|
|
259
259
|
lines.append("狼人优先级: " + display_roles(data.werewolf_priority))
|
260
260
|
lines.append("神职优先级: " + display_roles(data.priesthood_proirity))
|
261
|
-
lines.append(f"小丑概率: {data.
|
261
|
+
lines.append(f"小丑概率: {data.jester_probability:.0%}")
|
262
262
|
|
263
263
|
await finish("\n".join(lines))
|
@@ -2,6 +2,7 @@ from nonebot import on_message
|
|
2
2
|
from nonebot.adapters import Event
|
3
3
|
from nonebot_plugin_alconna import Alconna, MsgTarget, UniMessage, UniMsg, on_alconna
|
4
4
|
|
5
|
+
from ..config import config
|
5
6
|
from ..constant import STOP_COMMAND
|
6
7
|
from ..utils import InputStore
|
7
8
|
from .depends import rule_in_game
|
@@ -18,10 +19,11 @@ async def handle_input(event: Event, target: MsgTarget, msg: UniMsg) -> None:
|
|
18
19
|
|
19
20
|
|
20
21
|
stopcmd = on_alconna(
|
21
|
-
Alconna(
|
22
|
+
Alconna(config.get_stop_command()[0]),
|
22
23
|
rule=rule_in_game,
|
23
24
|
block=True,
|
24
25
|
use_cmd_start=True,
|
26
|
+
aliases=set(aliases) if (aliases := config.get_stop_command()[1:]) else None,
|
25
27
|
)
|
26
28
|
|
27
29
|
|
@@ -6,7 +6,7 @@ from nonebot_plugin_alconna import MsgTarget, UniMessage
|
|
6
6
|
|
7
7
|
from ...config import config
|
8
8
|
from ...constant import STOP_COMMAND
|
9
|
-
from ...game import
|
9
|
+
from ...game import get_starting_games
|
10
10
|
from ...utils import InputStore
|
11
11
|
from ..depends import user_in_game
|
12
12
|
|
@@ -33,7 +33,7 @@ with contextlib.suppress(ImportError):
|
|
33
33
|
gen = (
|
34
34
|
seg.data["operatorId"]
|
35
35
|
for seg in poke
|
36
|
-
if seg.data["userId"] == event.
|
36
|
+
if seg.data["userId"] == event.login.sn
|
37
37
|
)
|
38
38
|
return next(gen, None)
|
39
39
|
|
@@ -76,7 +76,7 @@ with contextlib.suppress(ImportError):
|
|
76
76
|
user_id=user_id,
|
77
77
|
group_id=(event.guild and event.guild.id) or event.channel.id,
|
78
78
|
)
|
79
|
-
and any(target.verify(group) for group in
|
79
|
+
and any(target.verify(group) for group in get_starting_games())
|
80
80
|
)
|
81
81
|
|
82
82
|
@on_message(rule=_rule_poke_join).handle()
|
@@ -86,7 +86,7 @@ with contextlib.suppress(ImportError):
|
|
86
86
|
target: MsgTarget,
|
87
87
|
) -> None:
|
88
88
|
user_id = extract_poke_tome(event) or event.get_user_id()
|
89
|
-
players = next(p for g, p in
|
89
|
+
players = next(p for g, p in get_starting_games().items() if target.verify(g))
|
90
90
|
|
91
91
|
if user_id not in players:
|
92
92
|
# XXX:
|
@@ -114,4 +114,7 @@ with contextlib.suppress(ImportError):
|
|
114
114
|
return False
|
115
115
|
|
116
116
|
event = current_event.get()
|
117
|
-
return
|
117
|
+
return (
|
118
|
+
isinstance(event, MessageCreatedEvent)
|
119
|
+
and event.login.platform == "chronocat"
|
120
|
+
)
|
@@ -6,7 +6,7 @@ from nonebot_plugin_alconna import MsgTarget, UniMessage
|
|
6
6
|
|
7
7
|
from ...config import config
|
8
8
|
from ...constant import STOP_COMMAND
|
9
|
-
from ...game import
|
9
|
+
from ...game import get_starting_games
|
10
10
|
from ...utils import InputStore
|
11
11
|
from ..depends import user_in_game
|
12
12
|
|
@@ -50,7 +50,7 @@ with contextlib.suppress(ImportError):
|
|
50
50
|
return (
|
51
51
|
(event.target_id == event.self_id)
|
52
52
|
and not user_in_game(bot.self_id, user_id, group_id)
|
53
|
-
and any(target.verify(group) for group in
|
53
|
+
and any(target.verify(group) for group in get_starting_games())
|
54
54
|
)
|
55
55
|
|
56
56
|
@on_notice(rule=_rule_poke_join).handle()
|
@@ -60,7 +60,7 @@ with contextlib.suppress(ImportError):
|
|
60
60
|
target: MsgTarget,
|
61
61
|
) -> None:
|
62
62
|
user_id = event.get_user_id()
|
63
|
-
players = next(p for g, p in
|
63
|
+
players = next(p for g, p in get_starting_games().items() if target.verify(g))
|
64
64
|
|
65
65
|
if event.group_id is None or user_id in players:
|
66
66
|
return
|