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 -*- 

2 

3# -- stdlib -- 

4from typing import Sequence, List, cast 

5from functools import wraps 

6import logging 

7 

8# -- third party -- 

9# -- own -- 

10from client.base import Game as ClientGame 

11from thb import actions 

12from thb.actions import BaseActionStage 

13from thb.cards.base import Skill, Card 

14from thb.characters.base import Character 

15from thb.mode import THBattle 

16from thb.meta.common import ui_meta 

17 

18 

19# -- code -- 

20log = logging.getLogger('Inputlets UI Meta') 

21 

22 

23class ActionDisplayResult(Exception): 

24 __slots__ = ( 

25 'valid', 

26 'prompt', 

27 'pl_selecting', 

28 'pl_disabled', 

29 'pl_selected', 

30 ) 

31 

32 def __init__(self, valid, prompt, pl_selecting, pl_disabled, pl_selected): 

33 Exception.__init__(self) 

34 self.valid = valid 

35 self.prompt = prompt 

36 self.pl_selecting = pl_selecting 

37 self.pl_disabled = pl_disabled 

38 self.pl_selected = pl_selected 

39 

40 

41def walk_wrapped(g, cl, check_is_complete): 

42 for c in cl: 

43 if not isinstance(c, Skill): 

44 continue 

45 

46 if check_is_complete: 

47 try: 

48 is_complete = c.ui_meta.is_complete 

49 except Exception: 

50 # skills that cannot combined with other skill 

51 raise ActionDisplayResult(False, '您不能这样出牌', False, [], []) 

52 

53 try: 

54 rst, reason = is_complete(g, c) 

55 except Exception: 

56 log.exception('card.ui_meta.is_complete error') 

57 raise ActionDisplayResult(False, '[card.ui_meta.is_complete错误]', False, [], []) 

58 

59 if not rst: 

60 raise ActionDisplayResult(False, reason, False, [], []) 

61 

62 walk_wrapped(g, c.associated_cards, True) 

63 

64 

65def pasv_handle_card_selection(g, ilet, cards): 

66 if not ilet.categories: 

67 return [], '' 

68 

69 if cards: 

70 walk_wrapped(g, cards, True) 

71 

72 from thb.cards.base import Skill 

73 

74 if cards[0].is_card(Skill) and not actions.skill_check(cards[0]): 

75 raise ActionDisplayResult(False, '您不能这样出牌', False, [], []) 

76 

77 c = ilet.initiator.cond(cards) 

78 c1, text = ilet.initiator.ui_meta.choose_card_text(g, ilet.initiator, cards) 

79 assert c == c1, 'cond = %s, meta = %s' % (c, c1) 

80 

81 if not c: 

82 raise ActionDisplayResult(False, text, False, [], []) 

83 

84 return cards, text 

85 

86 

87def pasv_handle_player_selection(g, ilet, players): 

88 if not ilet.candidates: 

89 return False, [], [], '' 

90 

91 disables = [p for p in g.players if p not in ilet.candidates] 

92 players = [p for p in players if p not in disables] 

93 

94 players, logic_valid = ilet.initiator.choose_player_target(players) 

95 try: 

96 ui_meta_valid, reason = ilet.initiator.ui_meta.target(players) 

97 assert bool(logic_valid) == bool(ui_meta_valid), 'logic: %s, ui: %s' % (logic_valid, ui_meta_valid) 

98 except Exception: 

99 log.exception('act.ui_meta.target error') 

100 raise ActionDisplayResult(False, '[act.ui_meta.target错误]', bool(ilet.candidates), disables, players) 

101 

102 if not logic_valid: 

103 raise ActionDisplayResult(False, reason, True, disables, players) 

104 

105 return True, disables, players, reason 

106 

107 

108def actv_handle_card_selection(g, act, cards): 

109 if len(cards) != 1: 

110 raise ActionDisplayResult(False, '请选择一张牌使用', False, [], []) 

111 

112 walk_wrapped(g, cards, False) 

113 card = cards[0] 

114 

115 c = act.cond(cards) 

116 c1, text = act.ui_meta.choose_card_text(g, act, cards) 

117 assert c == c1, 'cond = %s, meta = %s' % (c, c1) 

118 

119 if not c: 

120 raise ActionDisplayResult(False, text, False, [], []) 

121 

122 return card 

123 

124 

125def actv_handle_target_selection(g: THBattle, stage: BaseActionStage, card: Card, players: Sequence[Character]): 

126 plsel = False 

127 selected: List[Character] = [] 

128 disables: List[Character] = [] 

129 

130 me = g.find_character(cast(ClientGame, g).me) 

131 tl, tl_valid = card.target(g, me, players) 

132 if tl is not None: 

133 selected = list(tl) 

134 if card.target.__name__ in ('t_One', 't_OtherOne'): 

135 for p in g.players: 

136 act = stage.launch_card_cls(me, [p], card) 

137 shootdown = act.action_shootdown() 

138 if shootdown is not None: 

139 if shootdown.ui_meta.target_independent: 

140 reason = shootdown.ui_meta.shootdown_message 

141 raise ActionDisplayResult(False, reason, False, [], []) 

142 

143 disables.append(p) 

144 

145 plsel = True 

146 for i in disables: 

147 try: 

148 tl.remove(i) 

149 except ValueError: 

150 pass 

151 

152 try: 

153 rst, reason = card.ui_meta.is_action_valid(g, [card], tl) 

154 except Exception: 

155 log.exception('card.ui_meta.is_action_valid error') 

156 raise ActionDisplayResult(False, '[card.ui_meta.is_action_valid错误]', False, [], []) 

157 

158 if not rst: 

159 raise ActionDisplayResult(False, reason, plsel, disables, selected) 

160 

161 if not tl_valid: # honor result of game logic 

162 raise ActionDisplayResult(False, '您选择的目标不符合规则', plsel, disables, selected) 

163 

164 return tl, disables, reason 

165 

166 

167def action_disp_func(f): 

168 @wraps(f) 

169 def wrapper(*a, **k): 

170 try: 

171 f(*a, **k) 

172 raise Exception("Didn't raise ActionDisplayResult!") 

173 except ActionDisplayResult as e: 

174 return e 

175 

176 except Exception as e: 

177 # Arghhh 

178 log.exception(e) 

179 return ActionDisplayResult(False, str(e), False, [], []) 

180 

181 wrapper.__name__ = f.__name__ 

182 return wrapper 

183 

184 

185@ui_meta(actions.ActionInputlet) 

186class ActionInputlet: 

187 @action_disp_func 

188 def passive_action_disp(self, ilet, skills, rawcards, params, players): 

189 g = ilet.initiator.game 

190 

191 usage = getattr(ilet.initiator, 'card_usage', 'none') 

192 

193 if skills: 

194 if any(not g.me.has_skill(s) for s in skills): 

195 raise ActionDisplayResult(False, '您不能这样出牌', False, [], []) 

196 cards = [actions.skill_wrap(g.me, skills, rawcards, params)] 

197 usage = cards[0].usage if usage == 'launch' else usage 

198 else: 

199 cards = rawcards 

200 

201 cards, prompt_card = pasv_handle_card_selection(g, ilet, cards) 

202 plsel, disables, players, prompt_target = pasv_handle_player_selection(g, ilet, players) 

203 

204 verify = getattr(ilet.initiator, 'ask_for_action_verify', None) 

205 rst = not verify or verify(g.me, cards, players) 

206 if not rst: 

207 raise ActionDisplayResult(False, rst.ui_meta.shootdown_message, plsel, disables, players) 

208 

209 raise ActionDisplayResult(True, prompt_target or prompt_card, plsel, disables, players) 

210 

211 def passive_action_recommend(self, ilet): 

212 g = ilet.initiator.game 

213 

214 if not ilet.categories: return 

215 

216 for c in g.me.showncards: 

217 if not ilet.initiator.cond([c]): continue 

218 return c 

219 

220 for c in g.me.cards: 

221 if not ilet.initiator.cond([c]): continue 

222 return c 

223 

224 @action_disp_func 

225 def active_action_disp(self, ilet, skills, rawcards, params, players): 

226 g = ilet.initiator.game 

227 

228 stage = ilet.initiator 

229 

230 if not skills and not rawcards: 

231 raise ActionDisplayResult(False, stage.ui_meta.idle_prompt, False, [], []) 

232 

233 usage = getattr(ilet.initiator, 'card_usage', 'none') 

234 

235 if skills: 

236 if any(not g.me.has_skill(s) for s in skills): 

237 raise ActionDisplayResult(False, '您不能这样出牌', False, [], []) 

238 cards = [actions.skill_wrap(g.me, skills, rawcards, params)] 

239 usage = cards[0].usage if usage == 'launch' else usage 

240 else: 

241 cards = rawcards 

242 

243 card = actv_handle_card_selection(g, stage, cards) 

244 players, disables, prompt = actv_handle_target_selection(g, stage, card, players) 

245 

246 act = stage.launch_card_cls(g.me, players, card) 

247 

248 shootdown = act.action_shootdown() 

249 if shootdown is not None: 

250 raise ActionDisplayResult(False, shootdown.ui_meta.shootdown_message, True, disables, players) 

251 

252 raise ActionDisplayResult(True, prompt, True, disables, players)