nonebot-plugin-werewolf 1.1.3__py3-none-any.whl → 1.1.6__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.
Files changed (35) hide show
  1. nonebot_plugin_werewolf/__init__.py +3 -1
  2. nonebot_plugin_werewolf/config.py +18 -55
  3. nonebot_plugin_werewolf/constant.py +20 -58
  4. nonebot_plugin_werewolf/exception.py +1 -1
  5. nonebot_plugin_werewolf/game.py +286 -245
  6. nonebot_plugin_werewolf/matchers/__init__.py +2 -0
  7. nonebot_plugin_werewolf/matchers/depends.py +50 -0
  8. nonebot_plugin_werewolf/matchers/edit_preset.py +263 -0
  9. nonebot_plugin_werewolf/matchers/message_in_game.py +18 -3
  10. nonebot_plugin_werewolf/matchers/poke/__init__.py +8 -0
  11. nonebot_plugin_werewolf/matchers/poke/chronocat_poke.py +117 -0
  12. nonebot_plugin_werewolf/matchers/{ob11_ext.py → poke/ob11_poke.py} +21 -19
  13. nonebot_plugin_werewolf/matchers/start_game.py +266 -28
  14. nonebot_plugin_werewolf/matchers/superuser_ops.py +24 -0
  15. nonebot_plugin_werewolf/models.py +73 -0
  16. nonebot_plugin_werewolf/player_set.py +33 -34
  17. nonebot_plugin_werewolf/players/can_shoot.py +15 -20
  18. nonebot_plugin_werewolf/players/civilian.py +3 -3
  19. nonebot_plugin_werewolf/players/guard.py +16 -22
  20. nonebot_plugin_werewolf/players/hunter.py +3 -3
  21. nonebot_plugin_werewolf/players/idiot.py +4 -4
  22. nonebot_plugin_werewolf/players/joker.py +8 -4
  23. nonebot_plugin_werewolf/players/player.py +133 -70
  24. nonebot_plugin_werewolf/players/prophet.py +8 -15
  25. nonebot_plugin_werewolf/players/werewolf.py +54 -30
  26. nonebot_plugin_werewolf/players/witch.py +33 -38
  27. nonebot_plugin_werewolf/players/wolfking.py +3 -3
  28. nonebot_plugin_werewolf/utils.py +109 -179
  29. {nonebot_plugin_werewolf-1.1.3.dist-info → nonebot_plugin_werewolf-1.1.6.dist-info}/METADATA +78 -66
  30. nonebot_plugin_werewolf-1.1.6.dist-info/RECORD +34 -0
  31. {nonebot_plugin_werewolf-1.1.3.dist-info → nonebot_plugin_werewolf-1.1.6.dist-info}/WHEEL +1 -1
  32. nonebot_plugin_werewolf/_timeout.py +0 -110
  33. nonebot_plugin_werewolf-1.1.3.dist-info/RECORD +0 -29
  34. {nonebot_plugin_werewolf-1.1.3.dist-info → nonebot_plugin_werewolf-1.1.6.dist-info}/LICENSE +0 -0
  35. {nonebot_plugin_werewolf-1.1.3.dist-info → nonebot_plugin_werewolf-1.1.6.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@ from nonebot import require
2
2
  from nonebot.plugin import PluginMetadata, inherit_supported_adapters
3
3
 
4
4
  require("nonebot_plugin_alconna")
5
+ require("nonebot_plugin_localstore")
5
6
  require("nonebot_plugin_uninfo")
6
7
  require("nonebot_plugin_waiter")
7
8
 
@@ -9,7 +10,7 @@ from . import matchers as matchers
9
10
  from . import players as players
10
11
  from .config import Config
11
12
 
12
- __version__ = "1.1.3"
13
+ __version__ = "1.1.6"
13
14
  __plugin_meta__ = PluginMetadata(
14
15
  name="狼人杀",
15
16
  description="适用于 Nonebot2 的狼人杀插件",
@@ -24,6 +25,7 @@ __plugin_meta__ = PluginMetadata(
24
25
  ),
25
26
  extra={
26
27
  "Author": "wyf7685",
28
+ "Version": __version__,
27
29
  "Bug Tracker": "https://github.com/wyf7685/nonebot-plugin-werewolf/issues",
28
30
  },
29
31
  )
@@ -1,82 +1,45 @@
1
- from typing import Any, Literal, overload
1
+ import json
2
2
 
3
3
  from nonebot import get_plugin_config, logger
4
- from nonebot.compat import PYDANTIC_V2
4
+ from nonebot.compat import model_dump, type_validate_json
5
+ from nonebot_plugin_localstore import get_plugin_data_file
5
6
  from pydantic import BaseModel, Field
6
7
  from typing_extensions import Self
7
8
 
8
9
  from .constant import (
9
- Role,
10
- RolePresetConfig,
11
- RolePresetDict,
12
10
  default_priesthood_proirity,
13
11
  default_role_preset,
14
12
  default_werewolf_priority,
15
13
  )
14
+ from .models import Role
16
15
 
17
- if PYDANTIC_V2:
18
- from pydantic import model_validator as model_validator
19
- else:
20
- from pydantic import root_validator
21
16
 
22
- @overload
23
- def model_validator(*, mode: Literal["before"]) -> Any: ... # noqa: ANN401
24
-
25
- @overload
26
- def model_validator(*, mode: Literal["after"]) -> Any: ... # noqa: ANN401
27
-
28
- def model_validator(*, mode: Literal["before", "after"]) -> Any:
29
- return root_validator(
30
- pre=mode == "before", # pyright: ignore[reportArgumentType]
31
- allow_reuse=True,
32
- )
33
-
34
-
35
- class PluginConfig(BaseModel):
36
- enable_poke: bool = True
37
- role_preset: RolePresetConfig = default_role_preset.copy()
17
+ class PresetData(BaseModel):
18
+ role_preset: dict[int, tuple[int, int, int]] = default_role_preset.copy()
38
19
  werewolf_priority: list[Role] = default_werewolf_priority.copy()
39
20
  priesthood_proirity: list[Role] = default_priesthood_proirity.copy()
40
21
  joker_probability: float = Field(default=0.0, ge=0.0, le=1.0)
41
22
 
42
- @model_validator(mode="after")
43
- def _validate(self) -> Self:
44
- if isinstance(self.role_preset, list):
45
- for preset in self.role_preset:
46
- if preset[0] != sum(preset[1:]):
47
- raise ValueError(
48
- "配置项 `role_preset` 错误: "
49
- f"预设总人数为 {preset[0]}, 实际总人数为 {sum(preset[1:])} "
50
- f"({', '.join(map(str, preset[1:]))})"
51
- )
52
- self.role_preset = default_role_preset | {
53
- i[0]: i[1:] for i in self.role_preset
54
- }
55
- logger.debug(f"覆写配置 role_preset: {self.role_preset}")
56
-
57
- min_length = max(i[0] for i in self.role_preset.values())
58
- if len(self.werewolf_priority) < min_length:
59
- raise ValueError(
60
- f"配置项 `werewolf_priority` 错误: 应至少为 {min_length} 项"
61
- )
23
+ @classmethod
24
+ def load(cls) -> Self:
25
+ return type_validate_json(cls, preset_data_file.read_text())
62
26
 
63
- min_length = max(i[1] for i in self.role_preset.values())
64
- if len(self.priesthood_proirity) < min_length:
65
- raise ValueError(
66
- f"配置项 `priesthood_proirity` 错误: 应至少为 {min_length} 项"
67
- )
27
+ def save(self) -> None:
28
+ preset_data_file.write_text(json.dumps(model_dump(self)))
68
29
 
69
- return self
70
30
 
71
- def get_role_preset(self) -> RolePresetDict:
72
- if isinstance(self.role_preset, list):
73
- self.role_preset = {i[0]: i[1:] for i in self.role_preset}
74
- return self.role_preset
31
+ class PluginConfig(BaseModel):
32
+ enable_poke: bool = True
33
+ enable_button: bool = False
75
34
 
76
35
 
77
36
  class Config(BaseModel):
78
37
  werewolf: PluginConfig = PluginConfig()
79
38
 
80
39
 
40
+ preset_data_file = get_plugin_data_file("preset.json")
41
+ if not preset_data_file.exists():
42
+ PresetData().save()
43
+
81
44
  config = get_plugin_config(Config).werewolf
82
45
  logger.debug(f"加载插件配置: {config}")
@@ -1,59 +1,12 @@
1
- from __future__ import annotations
1
+ import nonebot
2
2
 
3
- import dataclasses
4
- from enum import Enum, auto
5
- from typing import TYPE_CHECKING
3
+ from .models import GameStatus, KillReason, Role, RoleGroup
6
4
 
7
- if TYPE_CHECKING:
8
- from .players import Player
9
-
10
-
11
- class Role(Enum):
12
- # 狼人
13
- Werewolf = 1
14
- WolfKing = 2
15
-
16
- # 神职
17
- Prophet = 11
18
- Witch = 12
19
- Hunter = 13
20
- Guard = 14
21
- Idiot = 15
22
-
23
- # 其他
24
- Joker = 51
25
-
26
- # 平民
27
- Civilian = 0
28
-
29
-
30
- class RoleGroup(Enum):
31
- Werewolf = auto()
32
- GoodGuy = auto()
33
- Others = auto()
34
-
35
-
36
- class KillReason(Enum):
37
- Werewolf = auto()
38
- Poison = auto()
39
- Shoot = auto()
40
- Vote = auto()
41
-
42
-
43
- class GameStatus(Enum):
44
- GoodGuy = auto()
45
- Werewolf = auto()
46
- Joker = auto()
47
-
48
-
49
- @dataclasses.dataclass
50
- class GameState:
51
- day: int
52
- killed: Player | None = None
53
- shoot: tuple[Player, Player] | tuple[None, None] = (None, None)
54
- antidote: set[Player] = dataclasses.field(default_factory=set)
55
- poison: set[Player] = dataclasses.field(default_factory=set)
56
- protected: set[Player] = dataclasses.field(default_factory=set)
5
+ COMMAND_START = next(
6
+ iter(sorted(nonebot.get_driver().config.command_start, key=len)), ""
7
+ )
8
+ STOP_COMMAND_PROMPT = f"{COMMAND_START}stop"
9
+ STOP_COMMAND = "{{stop}}"
57
10
 
58
11
 
59
12
  role_name_conv: dict[Role | RoleGroup, str] = {
@@ -83,10 +36,20 @@ role_emoji: dict[Role, str] = {
83
36
  Role.Civilian: "👨🏻‍🌾",
84
37
  }
85
38
 
86
- RolePresetDict = dict[int, tuple[int, int, int]]
87
- RolePresetConfig = RolePresetDict | list[tuple[int, int, int, int]]
39
+ game_status_conv: dict[GameStatus, str] = {
40
+ GameStatus.GoodGuy: "好人",
41
+ GameStatus.Werewolf: "狼人",
42
+ GameStatus.Joker: "小丑",
43
+ }
44
+
45
+ report_text: dict[KillReason, tuple[str, str]] = {
46
+ KillReason.Werewolf: ("🔪", "刀了"),
47
+ KillReason.Poison: ("🧪", "毒死"),
48
+ KillReason.Shoot: ("🔫", "射杀"),
49
+ KillReason.Vote: ("🗳️", "票出"),
50
+ }
88
51
 
89
- default_role_preset: RolePresetDict = {
52
+ default_role_preset: dict[int, tuple[int, int, int]] = {
90
53
  # 总人数: (狼, 神, 民)
91
54
  6: (1, 2, 3),
92
55
  7: (2, 2, 3),
@@ -96,7 +59,6 @@ default_role_preset: RolePresetDict = {
96
59
  11: (3, 5, 3),
97
60
  12: (4, 5, 3),
98
61
  }
99
-
100
62
  default_werewolf_priority: list[Role] = [
101
63
  Role.Werewolf,
102
64
  Role.Werewolf,
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from typing import TYPE_CHECKING
4
4
 
5
5
  if TYPE_CHECKING:
6
- from .constant import GameStatus
6
+ from .models import GameStatus
7
7
 
8
8
 
9
9
  class Error(Exception):