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 ClassVar, Type 

6 

7# -- third party -- 

8# -- own -- 

9from thb.actions import ActionStage, DropCards, ShowCards, UserAction, migrate_cards 

10from thb.actions import user_choose_cards 

11from thb.cards.base import Card, Skill 

12from thb.cards.classes import t_None, t_OtherOne 

13from thb.characters.base import Character, register_character_to 

14from thb.inputlets import ChooseOptionInputlet, HopeMaskInputlet, HopeMaskKOFInputlet, Inputlet 

15from thb.mode import THBEventHandler, THBAction 

16 

17 

18# -- code -- 

19class BaseHopeMaskAction(UserAction): 

20 inputlet_cls: ClassVar[Type[Inputlet]] 

21 

22 def apply_action(self): 

23 tgt = self.target 

24 g = self.game 

25 n = 1 + tgt.maxlife - tgt.life 

26 cards = g.deck.getcards(n) 

27 

28 tgt.reveal(cards) 

29 putback, acquire = g.user_input([tgt], self.inputlet_cls(self, cards), timeout=20) 

30 for c in acquire: 

31 c.detach() 

32 

33 assert not putback or set(putback) == set(g.deck.getcards(len(putback))) 

34 

35 deck = g.deck.cards 

36 for i, c in enumerate(putback): 

37 deck[i] = c 

38 

39 assert not putback or putback == g.deck.getcards(len(putback)) 

40 

41 if acquire: 

42 g.process_action(ShowCards(tgt, acquire)) 

43 migrate_cards(acquire, tgt.cards) 

44 

45 self.acquire = acquire 

46 

47 return True 

48 

49 

50class HopeMaskAction(BaseHopeMaskAction): 

51 inputlet_cls = HopeMaskInputlet 

52 

53 

54class HopeMaskKOFAction(BaseHopeMaskAction): 

55 inputlet_cls = HopeMaskKOFInputlet 

56 

57 

58class BaseHopeMaskHandler(THBEventHandler): 

59 interested = ['action_apply'] 

60 skill: ClassVar[Type[Skill]] 

61 action: ClassVar[Type[THBAction]] 

62 

63 def handle(self, evt_type, act): 

64 if evt_type == 'action_apply' and isinstance(act, ActionStage): 

65 tgt = act.target 

66 if not tgt.has_skill(self.skill): return act 

67 g = self.game 

68 if not g.user_input([tgt], ChooseOptionInputlet(self, (False, True))): 

69 return act 

70 g.process_action(self.action(tgt, tgt)) 

71 

72 return act 

73 

74 

75class HopeMask(Skill): 

76 associated_action = None 

77 skill_category = ['character', 'passive'] 

78 target = t_None() 

79 

80 

81class HopeMaskKOF(Skill): 

82 associated_action = None 

83 skill_category = ['character', 'passive'] 

84 target = t_None() 

85 

86 

87class HopeMaskHandler(BaseHopeMaskHandler): 

88 skill = HopeMask 

89 action = HopeMaskAction 

90 

91 

92class HopeMaskKOFHandler(BaseHopeMaskHandler): 

93 skill = HopeMaskKOF 

94 action = HopeMaskKOFAction 

95 

96 

97class BaseDarkNohAction(UserAction): 

98 card_usage = 'drop' 

99 

100 def apply_action(self): 

101 src, tgt = self.source, self.target 

102 g = self.game 

103 

104 src.tags['darknoh_tag'] = src.tags['turn_count'] 

105 sk = self.associated_card 

106 assert isinstance(sk, (DarkNoh, DarkNohKOF)) 

107 card = sk.associated_cards[0] 

108 self.card = card 

109 migrate_cards([sk], tgt.showncards, unwrap=True) 

110 self.n = n = len(tgt.cards) + len(tgt.showncards) - tgt.life 

111 if n <= 0: return True 

112 

113 cards = user_choose_cards(self, tgt, ('cards', 'showncards')) 

114 if not cards: 

115 cl = list(tgt.cards) + list(tgt.showncards) 

116 try: 

117 cl.remove(card) 

118 except Exception: 

119 pass 

120 

121 cards = cl[:n] 

122 

123 g.players.reveal(cards) 

124 g.process_action(DropCards(src, tgt, cards)) 

125 

126 return True 

127 

128 def cond(self, cards): 

129 if len(cards) != self.n or self.card in cards: 

130 return False 

131 

132 if any([c.is_card(Skill) for c in cards]): 

133 return False 

134 

135 return True 

136 

137 

138class DarkNohAction(BaseDarkNohAction): 

139 

140 def is_valid(self): 

141 src = self.source 

142 tgt = self.target 

143 

144 if src.tags['darknoh_tag'] >= src.tags['turn_count']: 

145 return False 

146 

147 if src.life > tgt.life: 

148 return False 

149 

150 return True 

151 

152 

153class DarkNohKOFAction(BaseDarkNohAction): 

154 

155 def is_valid(self): 

156 src = self.source 

157 tgt = self.target 

158 

159 if src.tags['darknoh_tag'] > 0: 

160 return False 

161 

162 if src.life > tgt.life: 

163 return False 

164 

165 return True 

166 

167 

168class BaseDarkNoh(Skill): 

169 no_drop = True 

170 skill_category = ['character', 'active'] 

171 target = t_OtherOne() 

172 usage = 'handover' 

173 

174 def check(self): 

175 cards = self.associated_cards 

176 if len(cards) != 1: return False 

177 c = cards[0] 

178 if c.resides_in is None: return False 

179 if c.resides_in.type not in ('cards', 'showncards', 'equips'): return False 

180 if c.suit not in (Card.SPADE, Card.CLUB): return False 

181 return True 

182 

183 

184class DarkNoh(BaseDarkNoh): 

185 associated_action = DarkNohAction 

186 

187 

188class DarkNohKOF(BaseDarkNoh): 

189 associated_action = DarkNohKOFAction 

190 

191 

192@register_character_to('common', '-kof') 

193class Kokoro(Character): 

194 skills = [HopeMask, DarkNoh] 

195 eventhandlers = [HopeMaskHandler] 

196 maxlife = 3 

197 

198 

199@register_character_to('kof') 

200class KokoroKOF(Character): 

201 skills = [HopeMaskKOF, DarkNohKOF] 

202 eventhandlers = [HopeMaskKOFHandler] 

203 maxlife = 3