Coverage for thb/item.py : 51%
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 core = g.core
51 items = core.item.items_of(g)
53 for l in items.values():
54 if self.sku in l:
55 raise exceptions.ChooseCharacterConflict
57 @classmethod
58 def get_chosen(cls, items: Dict[Player, List[GameItem]], pl: BatchList[Player]) -> Dict[Player, Type[Character]]:
59 chosen: Dict[Player, Type[Character]] = {}
61 for p in pl:
62 if p not in items: 62 ↛ 65line 62 didn't jump to line 65, because the condition on line 62 was never false
63 continue
65 for i in items[p]:
66 if not isinstance(i, cls):
67 continue
69 chosen[p] = i.char_cls
70 break
72 return chosen
75@GameItem.register
76class ImperialRole(GameItem):
77 key = 'imperial-role'
78 args = [str]
80 def __init__(self, role: str):
81 if role not in ('attacker', 'accomplice', 'curtain', 'boss'): 81 ↛ 82line 81 didn't jump to line 82, because the condition on line 81 was never true
82 raise exceptions.InvalidItemSKU
84 self.role = role
85 mapping = {
86 'attacker': '城管',
87 'boss': 'BOSS',
88 'accomplice': '道中',
89 'curtain': '黑幕',
90 }
91 self.disp_name = mapping[role]
93 @property
94 def title(self):
95 return '身份卡(%s)' % self.disp_name
97 @property
98 def description(self):
99 return '你可以选择%s身份。身份场可用。' % self.disp_name
101 def should_usable(self, core: ServerCore, g: ServerGame, u: Client):
102 from thb.thbrole import THBattleRole
103 if not isinstance(g, THBattleRole): 103 ↛ 106line 103 didn't jump to line 106
104 raise exceptions.IncorrectGameMode
106 threshold = {
107 'attacker': 4,
108 'boss': 1,
109 'accomplice': 2,
110 'curtain': 1,
111 }
112 core = g.core
113 params = core.game.params_of(g)
114 if params['double_curtain']:
115 threshold['curtain'] += 1
116 threshold['attacker'] -= 1
118 threshold[self.id] -= 1
120 items = core.item.items_of(g)
121 uid = core.auth.uid_of(u)
122 for _uid, l in items:
123 for i in l:
124 i = GameItem.from_sku(i)
125 if not isinstance(i, self.__class__):
126 continue
128 if _uid == uid:
129 raise exceptions.IdentityAlreadyChosen
131 assert i.id in threshold
133 threshold[i.id] -= 1
135 if any(i < 0 for i in threshold.values()):
136 raise exceptions.ChooseIdentityConflict
138 @classmethod
139 def get_chosen(cls, items: Dict[Player, List[GameItem]], pl: Sequence[Player]) -> List[Tuple[Player, THBRoleRole]]:
140 from thb.thbrole import THBRoleRole as T
142 mapping = {
143 'boss': T.BOSS,
144 'attacker': T.ATTACKER,
145 'accomplice': T.ACCOMPLICE,
146 'curtain': T.CURTAIN,
147 }
149 rst = []
150 for p in pl:
151 if p not in items: 151 ↛ 154line 151 didn't jump to line 154, because the condition on line 151 was never false
152 continue
154 for i in items[p]:
155 if not isinstance(i, cls):
156 continue
158 rst.append((p, mapping[i.role]))
160 return rst
163@GameItem.register
164class European(GameItem):
165 key = 'european'
167 title = '欧洲卡'
168 description = 'Roll点保证第一。身份场不可用。'
170 def __init__(self):
171 pass
173 def should_usable(self, core: ServerCore, g: ServerGame, u: Client):
174 cls = self.__class__
176 from thb.thbrole import THBattleRole
177 if isinstance(g, THBattleRole): 177 ↛ 178line 177 didn't jump to line 178, because the condition on line 177 was never true
178 raise exceptions.IncorrectGameMode
180 items = core.item.items_of(g)
182 for uid, l in items.items():
183 if any(isinstance(i, cls) for i in l): 183 ↛ exit, 183 ↛ 1822 missed branches: 1) line 183 didn't finish the generator expression on line 183, 2) line 183 didn't jump to line 182, because the condition on line 183 was never false
184 raise exceptions.EuropeanConflict
186 @classmethod
187 def get_european(cls, g: Game, items: Dict[Player, List[GameItem]]) -> Optional[Player]:
188 for p, l in items.items():
189 for i in l: 189 ↛ 188line 189 didn't jump to line 188, because the loop on line 189 didn't complete
190 if isinstance(i, cls): 190 ↛ 189line 190 didn't jump to line 189, because the condition on line 190 was never false
191 return p
193 return None