nonebot-plugin-werewolf 1.1.0__py3-none-any.whl → 1.1.1__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 +1 -2
- nonebot_plugin_werewolf/constant.py +5 -5
- nonebot_plugin_werewolf/game.py +26 -32
- nonebot_plugin_werewolf/player.py +7 -26
- {nonebot_plugin_werewolf-1.1.0.dist-info → nonebot_plugin_werewolf-1.1.1.dist-info}/METADATA +19 -5
- nonebot_plugin_werewolf-1.1.1.dist-info/RECORD +15 -0
- nonebot_plugin_werewolf-1.1.0.dist-info/RECORD +0 -15
- {nonebot_plugin_werewolf-1.1.0.dist-info → nonebot_plugin_werewolf-1.1.1.dist-info}/LICENSE +0 -0
- {nonebot_plugin_werewolf-1.1.0.dist-info → nonebot_plugin_werewolf-1.1.1.dist-info}/WHEEL +0 -0
- {nonebot_plugin_werewolf-1.1.0.dist-info → nonebot_plugin_werewolf-1.1.1.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,8 @@
|
|
1
|
-
from typing import Literal, overload
|
1
|
+
from typing import Literal, Self, overload
|
2
2
|
|
3
3
|
from nonebot import get_plugin_config, logger
|
4
4
|
from nonebot.compat import PYDANTIC_V2
|
5
5
|
from pydantic import BaseModel, Field
|
6
|
-
from typing_extensions import Self
|
7
6
|
|
8
7
|
from .constant import (
|
9
8
|
Role,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
|
3
|
+
import dataclasses
|
4
4
|
from enum import Enum, auto
|
5
5
|
from typing import TYPE_CHECKING
|
6
6
|
|
@@ -43,17 +43,17 @@ class KillReason(Enum):
|
|
43
43
|
class GameStatus(Enum):
|
44
44
|
GoodGuy = auto()
|
45
45
|
Werewolf = auto()
|
46
|
-
Unset = auto()
|
47
46
|
Joker = auto()
|
48
47
|
|
49
48
|
|
50
|
-
@dataclass
|
49
|
+
@dataclasses.dataclass
|
51
50
|
class GameState:
|
52
51
|
day: int
|
53
52
|
killed: Player | None = None
|
54
53
|
shoot: tuple[Player, Player] | tuple[None, None] = (None, None)
|
55
|
-
|
56
|
-
|
54
|
+
antidote: set[Player] = dataclasses.field(default_factory=set)
|
55
|
+
poison: set[tuple[Player, Player]] = dataclasses.field(default_factory=set)
|
56
|
+
protected: set[Player] = dataclasses.field(default_factory=set)
|
57
57
|
|
58
58
|
|
59
59
|
role_name_conv: dict[Role | RoleGroup, str] = {
|
nonebot_plugin_werewolf/game.py
CHANGED
@@ -3,8 +3,7 @@ from __future__ import annotations
|
|
3
3
|
import asyncio
|
4
4
|
import asyncio.timeouts
|
5
5
|
import contextlib
|
6
|
-
import
|
7
|
-
import time
|
6
|
+
import secrets
|
8
7
|
from typing import TYPE_CHECKING, NoReturn
|
9
8
|
|
10
9
|
from nonebot.log import logger
|
@@ -35,20 +34,19 @@ def init_players(bot: Bot, game: Game, players: dict[str, str]) -> PlayerSet:
|
|
35
34
|
f"应为 {', '.join(map(str, role_preset))} 人, 传入{len(players)}人"
|
36
35
|
)
|
37
36
|
|
37
|
+
w, p, c = preset
|
38
38
|
roles: list[Role] = []
|
39
|
-
roles.extend(config.werewolf_priority[:
|
40
|
-
roles.extend(config.priesthood_proirity[:
|
41
|
-
roles.extend([Role.Civilian] *
|
39
|
+
roles.extend(config.werewolf_priority[:w])
|
40
|
+
roles.extend(config.priesthood_proirity[:p])
|
41
|
+
roles.extend([Role.Civilian] * c)
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
if roles.count(Role.Civilian) >= 2 and r.random() <= config.joker_probability:
|
43
|
+
if c >= 2 and secrets.randbelow(100) <= config.joker_probability * 100:
|
46
44
|
roles.remove(Role.Civilian)
|
47
45
|
roles.append(Role.Joker)
|
48
46
|
|
49
47
|
shuffled: list[Role] = []
|
50
|
-
|
51
|
-
idx =
|
48
|
+
while roles:
|
49
|
+
idx = secrets.randbelow(len(roles))
|
52
50
|
shuffled.append(roles.pop(idx))
|
53
51
|
|
54
52
|
logger.debug(f"职业分配: {shuffled}")
|
@@ -107,7 +105,7 @@ class Game:
|
|
107
105
|
msg.at(p.user_id)
|
108
106
|
return msg
|
109
107
|
|
110
|
-
def check_game_status(self) ->
|
108
|
+
def check_game_status(self) -> None:
|
111
109
|
players = self.players.alive()
|
112
110
|
w = players.select(RoleGroup.Werewolf)
|
113
111
|
p = players.exclude(RoleGroup.Werewolf)
|
@@ -125,8 +123,6 @@ class Game:
|
|
125
123
|
if not w.size:
|
126
124
|
raise GameFinishedError(GameStatus.GoodGuy)
|
127
125
|
|
128
|
-
return GameStatus.Unset
|
129
|
-
|
130
126
|
def show_killed_players(self) -> str:
|
131
127
|
msg = ""
|
132
128
|
|
@@ -220,7 +216,7 @@ class Game:
|
|
220
216
|
await self.interact(Role.Witch, 60)
|
221
217
|
# 否则等待 5-20s
|
222
218
|
else:
|
223
|
-
await asyncio.sleep(
|
219
|
+
await asyncio.sleep(5 + secrets.randbelow(15))
|
224
220
|
|
225
221
|
async def handle_new_dead(self, players: Player | PlayerSet) -> None:
|
226
222
|
if isinstance(players, Player):
|
@@ -369,28 +365,28 @@ class Game:
|
|
369
365
|
self.interact(Role.Prophet, 60),
|
370
366
|
self.interact(Role.Guard, 60),
|
371
367
|
players.select(Role.Witch).broadcast("请等待狼人决定目标..."),
|
372
|
-
players.
|
373
|
-
|
374
|
-
),
|
368
|
+
players.exclude(
|
369
|
+
RoleGroup.Werewolf, Role.Prophet, Role.Witch, Role.Guard
|
370
|
+
).broadcast("请等待其他玩家结束交互..."),
|
375
371
|
)
|
376
372
|
|
377
373
|
# 狼人击杀目标
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
potioned, (antidote, poison) = self.state.potion
|
383
|
-
|
384
|
-
# 狼人未空刀,除非守卫保护或女巫使用解药,否则狼人正常击杀玩家
|
385
|
-
if killed is not None and (
|
386
|
-
not ((killed is protected) or (antidote and potioned is killed))
|
374
|
+
if (
|
375
|
+
(killed := self.state.killed) # 狼人未空刀
|
376
|
+
and killed not in self.state.protected # 守卫保护
|
377
|
+
and killed not in self.state.antidote # 女巫使用解药
|
387
378
|
):
|
379
|
+
# 狼人正常击杀玩家
|
388
380
|
await killed.kill(
|
389
|
-
KillReason.Werewolf,
|
381
|
+
KillReason.Werewolf,
|
382
|
+
*players.select(RoleGroup.Werewolf),
|
390
383
|
)
|
391
|
-
|
392
|
-
|
393
|
-
|
384
|
+
|
385
|
+
# 女巫操作目标
|
386
|
+
for witch, potioned in self.state.poison:
|
387
|
+
if potioned not in self.state.protected: # 守卫未保护
|
388
|
+
# 女巫毒杀玩家
|
389
|
+
await potioned.kill(KillReason.Poison, witch)
|
394
390
|
|
395
391
|
day_count += 1
|
396
392
|
msg = UniMessage.text(f"『第{day_count}天』天亮了...\n")
|
@@ -440,8 +436,6 @@ class Game:
|
|
440
436
|
winner = "狼人"
|
441
437
|
case GameStatus.Joker:
|
442
438
|
winner = "小丑"
|
443
|
-
case GameStatus.Unset:
|
444
|
-
raise RuntimeError(f"错误的游戏状态: {status!r}")
|
445
439
|
|
446
440
|
msg = UniMessage.text(f"🎉游戏结束,{winner}获胜\n\n")
|
447
441
|
for p in sorted(self.players, key=lambda p: (p.role.value, p.user_id)):
|
@@ -307,24 +307,6 @@ class Witch(Player):
|
|
307
307
|
antidote: int = 1
|
308
308
|
poison: int = 1
|
309
309
|
|
310
|
-
def set_state(
|
311
|
-
self,
|
312
|
-
*,
|
313
|
-
antidote: Player | None = None,
|
314
|
-
posion: Player | None = None,
|
315
|
-
) -> None:
|
316
|
-
if antidote is not None:
|
317
|
-
self.antidote = 0
|
318
|
-
self.selected = antidote
|
319
|
-
self.game.state.potion = (antidote, (True, False))
|
320
|
-
elif posion is not None:
|
321
|
-
self.poison = 0
|
322
|
-
self.selected = posion
|
323
|
-
self.game.state.potion = (posion, (False, True))
|
324
|
-
else:
|
325
|
-
self.selected = None
|
326
|
-
self.game.state.potion = (None, (False, False))
|
327
|
-
|
328
310
|
async def handle_killed(self) -> bool:
|
329
311
|
msg = UniMessage()
|
330
312
|
if (killed := self.game.state.killed) is not None:
|
@@ -343,7 +325,7 @@ class Witch(Player):
|
|
343
325
|
text = await self.receive_text()
|
344
326
|
if text == "1":
|
345
327
|
self.antidote = 0
|
346
|
-
self.
|
328
|
+
self.game.state.antidote.add(killed)
|
347
329
|
await self.send(f"你对 {killed.name} 使用了解药,回合结束")
|
348
330
|
return True
|
349
331
|
if text == "/stop":
|
@@ -357,7 +339,6 @@ class Witch(Player):
|
|
357
339
|
|
358
340
|
if not self.poison:
|
359
341
|
await self.send("你没有可以使用的药水,回合结束")
|
360
|
-
self.set_state()
|
361
342
|
return
|
362
343
|
|
363
344
|
players = self.game.players.alive()
|
@@ -377,13 +358,12 @@ class Witch(Player):
|
|
377
358
|
break
|
378
359
|
if text == "/stop":
|
379
360
|
await self.send("你选择不使用毒药,回合结束")
|
380
|
-
self.set_state()
|
381
361
|
return
|
382
362
|
await self.send("输入错误: 请发送玩家编号或 “/stop”")
|
383
363
|
|
384
364
|
self.poison = 0
|
385
|
-
|
386
|
-
self.
|
365
|
+
player = players[selected]
|
366
|
+
self.game.state.poison.add((self, player))
|
387
367
|
await self.send(f"当前回合选择对玩家 {player.name} 使用毒药\n回合结束")
|
388
368
|
|
389
369
|
|
@@ -418,7 +398,8 @@ class Guard(Player):
|
|
418
398
|
break
|
419
399
|
await self.send("输入错误,请发送编号选择玩家")
|
420
400
|
|
421
|
-
self.
|
401
|
+
self.selected = players[selected]
|
402
|
+
self.game.state.protected.add(self.selected)
|
422
403
|
await self.send(f"本回合保护的玩家: {self.selected.name}")
|
423
404
|
|
424
405
|
|
@@ -462,11 +443,11 @@ class Joker(Player):
|
|
462
443
|
|
463
444
|
@override
|
464
445
|
async def kill(self, reason: KillReason, *killers: Player) -> bool:
|
465
|
-
|
446
|
+
await super().kill(reason, *killers)
|
466
447
|
if reason == KillReason.Vote:
|
467
448
|
self.game.killed_players.append(self)
|
468
449
|
raise GameFinishedError(GameStatus.Joker)
|
469
|
-
return
|
450
|
+
return True
|
470
451
|
|
471
452
|
|
472
453
|
@register_role(Role.Civilian, RoleGroup.GoodGuy)
|
{nonebot_plugin_werewolf-1.1.0.dist-info → nonebot_plugin_werewolf-1.1.1.dist-info}/METADATA
RENAMED
@@ -1,10 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: nonebot-plugin-werewolf
|
3
|
-
Version: 1.1.
|
3
|
+
Version: 1.1.1
|
4
4
|
Summary: 适用于 Nonebot2 的狼人杀插件
|
5
5
|
Author-email: wyf7685 <wyf7685@163.com>
|
6
6
|
License: MIT
|
7
|
-
Requires-Python: >=3.
|
7
|
+
Requires-Python: >=3.11
|
8
8
|
Description-Content-Type: text/markdown
|
9
9
|
License-File: LICENSE
|
10
10
|
Requires-Dist: nonebot2 >=2.3.3
|
@@ -26,13 +26,18 @@ _✨ 简单的狼人杀插件 ✨_
|
|
26
26
|
|
27
27
|
[](./LICENSE)
|
28
28
|
[](https://pypi.python.org/pypi/nonebot-plugin-werewolf)
|
29
|
-
[](https://www.python.org/)
|
31
30
|
[](https://github.com/astral-sh/uv)
|
31
|
+
[](https://github.com/astral-sh/ruff)
|
32
32
|
[](https://pycqa.github.io/isort/)
|
33
33
|
[](https://github.com/psf/black)
|
34
34
|
[](https://github.com/Microsoft/pyright)
|
35
|
-
|
35
|
+
|
36
|
+
[](https://github.com/wyf7685/nonebot-plugin-werewolf/commits)
|
37
|
+
[](https://wakatime.com/badge/user/b097681b-c224-44ec-8e04-e1cf71744655/project/70a7f68d-5625-4989-9476-be6877408332)
|
38
|
+
[](https://results.pre-commit.ci/latest/github/wyf7685/nonebot-plugin-werewolf/master)
|
39
|
+
[](https://github.com/wyf7685/nonebot-plugin-werewolf/actions/workflows/pyright.yml)
|
40
|
+
[](https://github.com/wyf7685/nonebot-plugin-werewolf/actions/workflows/pypi-publish.yml)
|
36
41
|
|
37
42
|
[](https://registry.nonebot.dev/plugin/nonebot-plugin-werewolf:nonebot_plugin_werewolf)
|
38
43
|
[](https://registry.nonebot.dev/plugin/nonebot-plugin-werewolf:nonebot_plugin_werewolf)
|
@@ -45,6 +50,10 @@ _✨ 简单的狼人杀插件 ✨_
|
|
45
50
|
|
46
51
|
## 💿 安装
|
47
52
|
|
53
|
+
> [!note]
|
54
|
+
>
|
55
|
+
> 请确保 NoneBot2 使用的 Python 解释器版本 >=3.11
|
56
|
+
|
48
57
|
<details open>
|
49
58
|
<summary>使用 nb-cli 安装</summary>
|
50
59
|
在 nonebot2 项目的根目录下打开命令行, 输入以下指令即可安装
|
@@ -231,6 +240,11 @@ werewolf__priesthood_proirity=[11, 12, 13, 14, 15]
|
|
231
240
|
|
232
241
|
<!-- CHANGELOG -->
|
233
242
|
|
243
|
+
- 2024.09.11 v1.1.1
|
244
|
+
|
245
|
+
- 修改 Python 需求为 `>=3.11`
|
246
|
+
- 优化交互结果处理 ~~_可以在一局游戏中加入多个女巫了_~~
|
247
|
+
|
234
248
|
- 2024.09.09 v1.1.0
|
235
249
|
|
236
250
|
- 新增职业 `小丑`
|
@@ -0,0 +1,15 @@
|
|
1
|
+
nonebot_plugin_werewolf/__init__.py,sha256=I6lFyJgJ4Tz4t8gS2lrsx-7paN2h_PNoGjGR8ryvSeU,734
|
2
|
+
nonebot_plugin_werewolf/config.py,sha256=gl_ujiY-8fxQ5hN9_gjL1WpJJR5UOBIRBGofbLcQzaE,2900
|
3
|
+
nonebot_plugin_werewolf/constant.py,sha256=1XNTcTicil90WSviI2e33FX0LstWXl1aV2ugbhsDlIk,1909
|
4
|
+
nonebot_plugin_werewolf/exception.py,sha256=Ui8rB1sBg6_p8JHSvrjCpUaXJlgrM_9XsLJ09k8F1bg,391
|
5
|
+
nonebot_plugin_werewolf/game.py,sha256=Y9MQASaNdm2uuNw37IjdQEQzikWmbql_PWLHaL7lcB8,17414
|
6
|
+
nonebot_plugin_werewolf/matchers.py,sha256=5FioDfARlxTEibGL1JMKUMzmTzOwljjWKAJxBnyzaYs,2106
|
7
|
+
nonebot_plugin_werewolf/ob11_ext.py,sha256=P8uc3AdN5K5MzJaK80WDK85VKFg_CK5avDHu7ueMkho,2418
|
8
|
+
nonebot_plugin_werewolf/player.py,sha256=ifqTBfNepQY5FCY7hZoUA6DcObkcFEiNmKEeRkitJqY,14749
|
9
|
+
nonebot_plugin_werewolf/player_set.py,sha256=AI8v6KjH9ACtP4lvrd5IJfayan0qALmpTRLC3s_3DFw,2754
|
10
|
+
nonebot_plugin_werewolf/utils.py,sha256=l7oNSK471SV5CaB1eEVyZm10XSBFf_TwNotvb30U6vE,6835
|
11
|
+
nonebot_plugin_werewolf-1.1.1.dist-info/LICENSE,sha256=B_WbEqjGr6GYVNfEJPY31T1Opik7OtgOkhRs4Ig3e2M,1064
|
12
|
+
nonebot_plugin_werewolf-1.1.1.dist-info/METADATA,sha256=5ikh-mdZTIObaFs9w7qgzrgsx31lCxB5Ag--C8stl0g,10447
|
13
|
+
nonebot_plugin_werewolf-1.1.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
14
|
+
nonebot_plugin_werewolf-1.1.1.dist-info/top_level.txt,sha256=wLTfg8sTKbH9lLT9LtU118C9cTspEBJareLsrYM52YA,24
|
15
|
+
nonebot_plugin_werewolf-1.1.1.dist-info/RECORD,,
|
@@ -1,15 +0,0 @@
|
|
1
|
-
nonebot_plugin_werewolf/__init__.py,sha256=A2138SSGhd2FdZ8V9Op50k5-pdfIVSfT0xBNG6qWacM,734
|
2
|
-
nonebot_plugin_werewolf/config.py,sha256=8HnSt7sk8WIwnQlHm0tLdiSk6OTwbysDwoQf8cvFgoE,2929
|
3
|
-
nonebot_plugin_werewolf/constant.py,sha256=yrhyw67KTaZ7DoGWZl3USWheaHSsUI94kl6ChDs0phI,1829
|
4
|
-
nonebot_plugin_werewolf/exception.py,sha256=Ui8rB1sBg6_p8JHSvrjCpUaXJlgrM_9XsLJ09k8F1bg,391
|
5
|
-
nonebot_plugin_werewolf/game.py,sha256=t1Gq-adeD5xprDH4uxfGF70wV_N-YZKBXn2CrMEH5Sc,17761
|
6
|
-
nonebot_plugin_werewolf/matchers.py,sha256=5FioDfARlxTEibGL1JMKUMzmTzOwljjWKAJxBnyzaYs,2106
|
7
|
-
nonebot_plugin_werewolf/ob11_ext.py,sha256=P8uc3AdN5K5MzJaK80WDK85VKFg_CK5avDHu7ueMkho,2418
|
8
|
-
nonebot_plugin_werewolf/player.py,sha256=IdkVKt31DMw6W_0idW04c-ix6JVtg7VPl7ZaegxUN0Y,15360
|
9
|
-
nonebot_plugin_werewolf/player_set.py,sha256=AI8v6KjH9ACtP4lvrd5IJfayan0qALmpTRLC3s_3DFw,2754
|
10
|
-
nonebot_plugin_werewolf/utils.py,sha256=l7oNSK471SV5CaB1eEVyZm10XSBFf_TwNotvb30U6vE,6835
|
11
|
-
nonebot_plugin_werewolf-1.1.0.dist-info/LICENSE,sha256=B_WbEqjGr6GYVNfEJPY31T1Opik7OtgOkhRs4Ig3e2M,1064
|
12
|
-
nonebot_plugin_werewolf-1.1.0.dist-info/METADATA,sha256=6hjSQYd7yYi9UgZ4OLqDUDwHhL6imH21MMDEu9hS6AA,9234
|
13
|
-
nonebot_plugin_werewolf-1.1.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
14
|
-
nonebot_plugin_werewolf-1.1.0.dist-info/top_level.txt,sha256=wLTfg8sTKbH9lLT9LtU118C9cTspEBJareLsrYM52YA,24
|
15
|
-
nonebot_plugin_werewolf-1.1.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{nonebot_plugin_werewolf-1.1.0.dist-info → nonebot_plugin_werewolf-1.1.1.dist-info}/top_level.txt
RENAMED
File without changes
|