Hide keyboard shortcuts

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 

3 

4# -- stdlib -- 

5from typing import Dict, List, Optional, Sequence, TYPE_CHECKING, Tuple, Type 

6import logging 

7 

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 

14 

15 

16# -- typing -- 

17if TYPE_CHECKING: 

18 from thb.characters.base import Character # noqa: F401 

19 from thb.thbrole import THBRoleRole # noqa: F401 

20 

21 

22# -- code -- 

23log = logging.getLogger('thb.item') 

24 

25 

26@GameItem.register 

27class ImperialChoice(GameItem): 

28 key = 'imperial-choice' 

29 args = [str] 

30 

31 def __init__(self, char: str): 

32 if char == 'Akari' or char not in Character.classes: 

33 raise exceptions.CharacterNotFound 

34 

35 self.char_cls = Character.classes[char] 

36 

37 @property 

38 def title(self): 

39 return '选将卡(%s)' % self.char_cls.ui_meta.name 

40 

41 @property 

42 def description(self): 

43 return '你可以选择%s出场。2v2模式不可用。' % self.char_cls.ui_meta.name 

44 

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 

49 

50 items = core.item.items_of(g) 

51 

52 for l in items.values(): 

53 if self.sku in l: 

54 raise exceptions.ChooseCharacterConflict 

55 

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]] = {} 

59 

60 for p in pl: 

61 if p not in items: 

62 continue 

63 

64 for i in items[p]: 

65 if not isinstance(i, cls): 

66 continue 

67 

68 chosen[p] = i.char_cls 

69 break 

70 

71 return chosen 

72 

73 

74@GameItem.register 

75class ImperialRole(GameItem): 

76 key = 'imperial-role' 

77 args = [str] 

78 

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 

82 

83 self.role = role 

84 mapping = { 

85 'attacker': '城管', 

86 'boss': 'BOSS', 

87 'accomplice': '道中', 

88 'curtain': '黑幕', 

89 } 

90 self.disp_name = mapping[role] 

91 

92 @property 

93 def title(self): 

94 return '身份卡(%s)' % self.disp_name 

95 

96 @property 

97 def description(self): 

98 return '你可以选择%s身份。身份场可用。' % self.disp_name 

99 

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 

104 

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 

115 

116 threshold[self.role] -= 1 

117 

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 

124 

125 if _uid == uid: 

126 raise exceptions.RoleAlreadyChosen 

127 

128 assert i.role in threshold 

129 

130 threshold[i.role] -= 1 

131 

132 if any(i < 0 for i in threshold.values()): 

133 raise exceptions.ChooseRoleConflict 

134 

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 

138 

139 mapping = { 

140 'boss': T.BOSS, 

141 'attacker': T.ATTACKER, 

142 'accomplice': T.ACCOMPLICE, 

143 'curtain': T.CURTAIN, 

144 } 

145 

146 rst = [] 

147 for p in pl: 

148 if p not in items: 

149 continue 

150 

151 for i in items[p]: 

152 if not isinstance(i, cls): 

153 continue 

154 

155 rst.append((p, mapping[i.role])) 

156 

157 return rst 

158 

159 

160@GameItem.register 

161class European(GameItem): 

162 key = 'european' 

163 

164 title = '欧洲卡' 

165 description = 'Roll点保证第一。身份场不可用。' 

166 

167 def __init__(self): 

168 pass 

169 

170 def should_usable(self, core: ServerCore, g: ServerGame, u: Client): 

171 cls = self.__class__ 

172 

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 

176 

177 items = core.item.items_of(g) 

178 

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 

182 

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 

189 

190 return None