Coverage for thb/item.py : 41%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2from __future__ import annotations
4# -- stdlib --
5from typing import Dict, List, Optional, Sequence, TYPE_CHECKING, Tuple, Type
6import logging
8# -- third party --
9# -- own --
10from game.base import Game, GameItem, Player
11from server.base import Client, Game as ServerGame
12from server.core import Core as ServerCore
13from utils.misc import BatchList, exceptions
16# -- typing --
17if TYPE_CHECKING:
18 from thb.characters.base import Character # noqa: F401
19 from thb.thbrole import THBRoleRole # noqa: F401
22# -- code --
23log = logging.getLogger('thb.item')
26@GameItem.register
27class ImperialChoice(GameItem):
28 key = 'imperial-choice'
29 args = [str]
31 def __init__(self, char: str):
32 if char == 'Akari' or char not in Character.classes:
33 raise exceptions.CharacterNotFound
35 self.char_cls = Character.classes[char]
37 @property
38 def title(self):
39 return '选将卡(%s)' % self.char_cls.ui_meta.name
41 @property
42 def description(self):
43 return '你可以选择%s出场。2v2模式不可用。' % self.char_cls.ui_meta.name
45 def should_usable(self, core: ServerCore, g: ServerGame, u: Client):
46 from thb.thb2v2 import THBattle2v2
47 if isinstance(g, THBattle2v2):
48 raise exceptions.IncorrectGameMode
50 items = core.item.items_of(g)
52 for l in items.values():
53 if self.sku in l:
54 raise exceptions.ChooseCharacterConflict
56 @classmethod
57 def get_chosen(cls, items: Dict[Player, List[GameItem]], pl: BatchList[Player]) -> Dict[Player, Type[Character]]:
58 chosen: Dict[Player, Type[Character]] = {}
60 for p in pl:
61 if p not in items:
62 continue
64 for i in items[p]:
65 if not isinstance(i, cls):
66 continue
68 chosen[p] = i.char_cls
69 break
71 return chosen
74@GameItem.register
75class ImperialRole(GameItem):
76 key = 'imperial-role'
77 args = [str]
79 def __init__(self, role: str):
80 if role not in ('attacker', 'accomplice', 'curtain', 'boss'): 80 ↛ 81line 80 didn't jump to line 81, because the condition on line 80 was never true
81 raise exceptions.InvalidItemSKU
83 self.role = role
84 mapping = {
85 'attacker': '城管',
86 'boss': 'BOSS',
87 'accomplice': '道中',
88 'curtain': '黑幕',
89 }
90 self.disp_name = mapping[role]
92 @property
93 def title(self):
94 return '身份卡(%s)' % self.disp_name
96 @property
97 def description(self):
98 return '你可以选择%s身份。身份场可用。' % self.disp_name
100 def should_usable(self, core: ServerCore, g: ServerGame, u: Client):
101 from thb.thbrole import THBattleRole
102 if not isinstance(g, THBattleRole): 102 ↛ 105line 102 didn't jump to line 105
103 raise exceptions.IncorrectGameMode
105 threshold = {
106 'attacker': 4,
107 'boss': 1,
108 'accomplice': 2,
109 'curtain': 1,
110 }
111 params = core.game.params_of(g)
112 if params['double_curtain']:
113 threshold['curtain'] += 1
114 threshold['attacker'] -= 1
116 threshold[self.role] -= 1
118 items = core.item.items_of(g)
119 uid = core.auth.uid_of(u)
120 for _uid, l in items.items():
121 for i in l:
122 if not isinstance(i, self.__class__):
123 continue
125 if _uid == uid:
126 raise exceptions.RoleAlreadyChosen
128 assert i.role in threshold
130 threshold[i.role] -= 1
132 if any(i < 0 for i in threshold.values()):
133 raise exceptions.ChooseRoleConflict
135 @classmethod
136 def get_chosen(cls, items: Dict[Player, List[GameItem]], pl: Sequence[Player]) -> List[Tuple[Player, THBRoleRole]]:
137 from thb.thbrole import THBRoleRole as T
139 mapping = {
140 'boss': T.BOSS,
141 'attacker': T.ATTACKER,
142 'accomplice': T.ACCOMPLICE,
143 'curtain': T.CURTAIN,
144 }
146 rst = []
147 for p in pl:
148 if p not in items:
149 continue
151 for i in items[p]:
152 if not isinstance(i, cls):
153 continue
155 rst.append((p, mapping[i.role]))
157 return rst
160@GameItem.register
161class European(GameItem):
162 key = 'european'
164 title = '欧洲卡'
165 description = 'Roll点保证第一。身份场不可用。'
167 def __init__(self):
168 pass
170 def should_usable(self, core: ServerCore, g: ServerGame, u: Client):
171 cls = self.__class__
173 from thb.thbrole import THBattleRole
174 if isinstance(g, THBattleRole): 174 ↛ 175line 174 didn't jump to line 175, because the condition on line 174 was never true
175 raise exceptions.IncorrectGameMode
177 items = core.item.items_of(g)
179 for uid, l in items.items():
180 if any(isinstance(i, cls) for i in l): 180 ↛ exit, 180 ↛ 1792 missed branches: 1) line 180 didn't finish the generator expression on line 180, 2) line 180 didn't jump to line 179, because the condition on line 180 was never false
181 raise exceptions.EuropeanConflict
183 @classmethod
184 def get_european(cls, g: Game, items: Dict[Player, List[GameItem]]) -> Optional[Player]:
185 for p, l in items.items():
186 for i in l: 186 ↛ 185line 186 didn't jump to line 185, because the loop on line 186 didn't complete
187 if isinstance(i, cls): 187 ↛ 186line 187 didn't jump to line 186, because the condition on line 187 was never false
188 return p
190 return None