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, Tuple, List 

5 

6# -- third party -- 

7# -- own -- 

8from thb.actions import DrawCards, LaunchCard, Pindian, UserAction 

9from thb.cards.base import Skill, VirtualCard 

10from thb.cards.classes import AttackCard, BaseAttack, DuelCard, TreatAs, t_None 

11from thb.characters.base import Character, register_character_to 

12from thb.inputlets import ChooseOptionInputlet 

13from thb.mode import THBEventHandler, THBattle 

14 

15 

16# -- code -- 

17class InciteAttack(TreatAs, VirtualCard): 

18 treat_as = AttackCard 

19 

20 def check(self): 

21 return not self.associated_cards 

22 

23 

24class InciteFailAttack(TreatAs, VirtualCard): 

25 treat_as = AttackCard 

26 distance = 99999 

27 

28 def check(self): 

29 return not self.associated_cards 

30 

31 

32class InciteSilentFailAction(UserAction): 

33 def __init__(self, source, target): 

34 self.source = source 

35 self.target = target 

36 

37 def apply_action(self): 

38 return True 

39 

40 

41class InciteAction(UserAction): 

42 def apply_action(self): 

43 src = self.source 

44 tags = src.tags 

45 tgt, victim = self.target_list 

46 

47 tags['incite_tag'] = tags['turn_count'] 

48 

49 g = self.game 

50 if g.process_action(Pindian(src, tgt)): 

51 g.process_action(LaunchCard(tgt, [victim], InciteAttack(tgt))) 

52 

53 else: 

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

55 g.process_action(LaunchCard(tgt, [src], InciteFailAttack(tgt))) 

56 else: 

57 g.process_action(InciteSilentFailAction(src, tgt)) 

58 

59 return True 

60 

61 def is_valid(self): 

62 src = self.source 

63 tags = src.tags 

64 if tags['turn_count'] <= tags['incite_tag']: 

65 return False 

66 

67 tgt, victim = self.target_list 

68 Pindian(src, tgt).action_shootdown_exception() 

69 return LaunchCard(tgt, [victim], InciteAttack(tgt)).can_fire() 

70 

71 

72class Incite(Skill): 

73 associated_action = InciteAction 

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

75 usage = 'none' 

76 

77 def target(self, src: Character, tl: Sequence[Character]) -> Tuple[List[Character], bool]: 

78 tl = [t for t in tl if not t.dead and t is not src] 

79 

80 if not tl: 

81 return ([], False) 

82 

83 tl_, valid = AttackCard().target(tl[0], tl[1:]) 

84 tl = tl[:1] 

85 tl.extend(tl_) 

86 return tl, valid 

87 

88 def check(self): 

89 return not self.associated_cards 

90 

91 

92class Reversal(Skill): 

93 associated_action = None 

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

95 target = t_None() 

96 

97 

98class ReversalDuel(TreatAs, VirtualCard): 

99 treat_as = DuelCard 

100 

101 def check(self): 

102 return not self.associated_cards 

103 

104 

105class ReversalHandler(THBEventHandler): 

106 interested = ['action_before'] 

107 execute_before = [ 

108 'HouraiJewelHandler', 

109 'RejectHandler', 

110 'FreakingPowerHandler', 

111 'RoukankenEffectHandler', 

112 ] 

113 

114 execute_after = ['DeathSickleHandler'] 

115 

116 def handle(self, evt_type, act): 

117 if evt_type == 'action_before' and isinstance(act, BaseAttack): 

118 if hasattr(act, 'roukanken_tag'): 118 ↛ 119line 118 didn't jump to line 119, because the condition on line 118 was never true

119 return act 

120 

121 src = act.source 

122 tgt = act.target 

123 g = self.game 

124 

125 if not tgt.has_skill(Reversal): 

126 return act 

127 

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

129 return act 

130 

131 def nhand(p): 

132 return len(p.cards) + len(p.showncards) 

133 

134 g.process_action(DrawCards(tgt, 1)) 

135 if nhand(tgt) > nhand(src): 

136 g.process_action(LaunchCard(src, [tgt], ReversalDuel(src))) 

137 act.cancelled = True 

138 

139 return act 

140 

141 

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

143class Seija(Character): 

144 skills = [Incite, Reversal] 

145 eventhandlers = [ReversalHandler] 

146 maxlife = 3