nonebot-plugin-werewolf 1.1.5__py3-none-any.whl → 1.1.7__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 (31) hide show
  1. nonebot_plugin_werewolf/__init__.py +2 -1
  2. nonebot_plugin_werewolf/config.py +21 -58
  3. nonebot_plugin_werewolf/constant.py +14 -74
  4. nonebot_plugin_werewolf/exception.py +1 -1
  5. nonebot_plugin_werewolf/game.py +217 -226
  6. nonebot_plugin_werewolf/matchers/__init__.py +2 -0
  7. nonebot_plugin_werewolf/matchers/depends.py +17 -5
  8. nonebot_plugin_werewolf/matchers/edit_preset.py +263 -0
  9. nonebot_plugin_werewolf/matchers/message_in_game.py +8 -3
  10. nonebot_plugin_werewolf/matchers/start_game.py +140 -48
  11. nonebot_plugin_werewolf/matchers/superuser_ops.py +24 -0
  12. nonebot_plugin_werewolf/models.py +73 -0
  13. nonebot_plugin_werewolf/player_set.py +1 -1
  14. nonebot_plugin_werewolf/players/can_shoot.py +4 -3
  15. nonebot_plugin_werewolf/players/civilian.py +1 -1
  16. nonebot_plugin_werewolf/players/guard.py +2 -1
  17. nonebot_plugin_werewolf/players/hunter.py +1 -1
  18. nonebot_plugin_werewolf/players/idiot.py +1 -1
  19. nonebot_plugin_werewolf/players/joker.py +6 -2
  20. nonebot_plugin_werewolf/players/player.py +18 -25
  21. nonebot_plugin_werewolf/players/prophet.py +2 -1
  22. nonebot_plugin_werewolf/players/werewolf.py +25 -26
  23. nonebot_plugin_werewolf/players/witch.py +2 -1
  24. nonebot_plugin_werewolf/players/wolfking.py +1 -1
  25. nonebot_plugin_werewolf/utils.py +69 -5
  26. {nonebot_plugin_werewolf-1.1.5.dist-info → nonebot_plugin_werewolf-1.1.7.dist-info}/METADATA +71 -67
  27. nonebot_plugin_werewolf-1.1.7.dist-info/RECORD +34 -0
  28. {nonebot_plugin_werewolf-1.1.5.dist-info → nonebot_plugin_werewolf-1.1.7.dist-info}/WHEEL +1 -1
  29. nonebot_plugin_werewolf-1.1.5.dist-info/RECORD +0 -31
  30. {nonebot_plugin_werewolf-1.1.5.dist-info → nonebot_plugin_werewolf-1.1.7.dist-info}/LICENSE +0 -0
  31. {nonebot_plugin_werewolf-1.1.5.dist-info → nonebot_plugin_werewolf-1.1.7.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.5"
13
+ __version__ = "1.1.7"
13
14
  __plugin_meta__ = PluginMetadata(
14
15
  name="狼人杀",
15
16
  description="适用于 Nonebot2 的狼人杀插件",
@@ -1,82 +1,45 @@
1
- from typing import Any, Literal, overload
1
+ import json
2
2
 
3
- from nonebot import get_plugin_config, logger
4
- from nonebot.compat import PYDANTIC_V2
3
+ import nonebot
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
 
81
- config = get_plugin_config(Config).werewolf
82
- logger.debug(f"加载插件配置: {config}")
40
+ preset_data_file = get_plugin_data_file("preset.json")
41
+ if not preset_data_file.exists():
42
+ PresetData().save()
43
+
44
+ config = nonebot.get_plugin_config(Config).werewolf
45
+ nonebot.logger.debug(f"加载插件配置: {config}")
@@ -1,14 +1,6 @@
1
- from __future__ import annotations
2
-
3
- import dataclasses
4
- from enum import Enum, auto
5
- from typing import TYPE_CHECKING
6
-
7
1
  import nonebot
8
2
 
9
- if TYPE_CHECKING:
10
- from .players import Player
11
-
3
+ from .models import GameStatus, KillReason, Role, RoleGroup
12
4
 
13
5
  COMMAND_START = next(
14
6
  iter(sorted(nonebot.get_driver().config.command_start, key=len)), ""
@@ -17,67 +9,6 @@ STOP_COMMAND_PROMPT = f"{COMMAND_START}stop"
17
9
  STOP_COMMAND = "{{stop}}"
18
10
 
19
11
 
20
- class Role(Enum):
21
- # 狼人
22
- Werewolf = 1
23
- WolfKing = 2
24
-
25
- # 神职
26
- Prophet = 11
27
- Witch = 12
28
- Hunter = 13
29
- Guard = 14
30
- Idiot = 15
31
-
32
- # 其他
33
- Joker = 51
34
-
35
- # 平民
36
- Civilian = 0
37
-
38
-
39
- class RoleGroup(Enum):
40
- Werewolf = auto()
41
- GoodGuy = auto()
42
- Others = auto()
43
-
44
-
45
- class KillReason(Enum):
46
- Werewolf = auto()
47
- Poison = auto()
48
- Shoot = auto()
49
- Vote = auto()
50
-
51
-
52
- class GameStatus(Enum):
53
- GoodGuy = auto()
54
- Werewolf = auto()
55
- Joker = auto()
56
-
57
-
58
- @dataclasses.dataclass
59
- class GameState:
60
- day: int
61
- """当前天数记录, 不会被 `reset()` 重置"""
62
- killed: Player | None = None
63
- """当晚狼人击杀目标, `None` 则为空刀"""
64
- shoot: Player | None = None
65
- """当前执行射杀操作的玩家"""
66
- antidote: set[Player] = dataclasses.field(default_factory=set)
67
- """当晚女巫使用解药的目标"""
68
- poison: set[Player] = dataclasses.field(default_factory=set)
69
- """当晚使用了毒药的女巫"""
70
- protected: set[Player] = dataclasses.field(default_factory=set)
71
- """当晚守卫保护的目标"""
72
-
73
- def reset(self) -> None:
74
- self.killed = None
75
- self.shoot = None
76
- self.antidote = set()
77
- self.poison = set()
78
- self.protected = set()
79
-
80
-
81
12
  role_name_conv: dict[Role | RoleGroup, str] = {
82
13
  Role.Werewolf: "狼人",
83
14
  Role.WolfKing: "狼王",
@@ -105,10 +36,20 @@ role_emoji: dict[Role, str] = {
105
36
  Role.Civilian: "👨🏻‍🌾",
106
37
  }
107
38
 
108
- RolePresetDict = dict[int, tuple[int, int, int]]
109
- 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
+ }
110
44
 
111
- default_role_preset: RolePresetDict = {
45
+ report_text: dict[KillReason, tuple[str, str]] = {
46
+ KillReason.Werewolf: ("🔪", "刀了"),
47
+ KillReason.Poison: ("🧪", "毒死"),
48
+ KillReason.Shoot: ("🔫", "射杀"),
49
+ KillReason.Vote: ("🗳️", "票出"),
50
+ }
51
+
52
+ default_role_preset: dict[int, tuple[int, int, int]] = {
112
53
  # 总人数: (狼, 神, 民)
113
54
  6: (1, 2, 3),
114
55
  7: (2, 2, 3),
@@ -118,7 +59,6 @@ default_role_preset: RolePresetDict = {
118
59
  11: (3, 5, 3),
119
60
  12: (4, 5, 3),
120
61
  }
121
-
122
62
  default_werewolf_priority: list[Role] = [
123
63
  Role.Werewolf,
124
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):