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

4# -- third party -- 

5# -- own -- 

6from game.base import ActionShootdown 

7from thb.actions import Damage, DrawCards, DropCards, FatetellStage, GenericAction, LaunchCard 

8from thb.actions import LifeLost, ShowCards, UseCard, UserAction, user_choose_cards 

9from thb.cards.base import Card, Skill, VirtualCard 

10from thb.cards.classes import Wine, t_None 

11from thb.characters.base import Character, register_character_to 

12from thb.inputlets import ChooseOptionInputlet 

13from thb.mode import THBEventHandler 

14 

15 

16# -- code -- 

17class Ciguatera(Skill): 

18 associated_action = None 

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

20 target = t_None() 

21 

22 

23class CiguateraAction(UserAction): 

24 def __init__(self, source, target, cards): 

25 self.source = source 

26 self.target = target 

27 self.cards = cards 

28 

29 def apply_action(self): 

30 tgt = self.target 

31 src = self.source 

32 g = self.game 

33 g.process_action(DropCards(src, src, self.cards)) 

34 g.process_action(LifeLost(src, tgt, 1)) 

35 g.process_action(Wine(src, tgt)) 

36 

37 return True 

38 

39 

40class CiguateraHandler(THBEventHandler): 

41 interested = ('action_before',) 

42 card_usage = 'drop' 

43 

44 def handle(self, evt_type, act): 

45 if evt_type == 'action_before' and isinstance(act, FatetellStage): 

46 if act.target.dead: return act 46 ↛ exitline 46 didn't return from function 'handle', because the return on line 46 wasn't executed

47 g = self.game 

48 for p in g.players: 

49 if p.dead: 

50 continue 

51 

52 if not p.has_skill(Ciguatera): 

53 continue 

54 

55 cards = user_choose_cards(self, p, ('cards', 'showncards', 'equips')) 

56 if cards: 

57 g.process_action(CiguateraAction(p, act.target, cards)) 

58 

59 return act 

60 

61 def cond(self, cl): 

62 return \ 

63 len(cl) == 1 and \ 

64 not cl[0].is_card(Skill) and \ 

65 cl[0].resides_in.type in ('cards', 'showncards', 'equips') and \ 

66 cl[0].color == Card.BLACK 

67 

68 

69class Melancholy(Skill): 

70 associated_action = None 

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

72 target = t_None() 

73 

74 

75class MelancholyPoison(VirtualCard): 

76 associated_action = None 

77 target = t_None() 

78 

79 

80class MelancholyLimit(ActionShootdown): 

81 pass 

82 

83 

84class MelancholyAction(GenericAction): 

85 def __init__(self, source, target, amount): 

86 self.source = source 

87 self.target = target 

88 self.amount = amount 

89 

90 def apply_action(self): 

91 src = self.source 

92 tgt = self.target 

93 draw = DrawCards(src, self.amount) 

94 g = self.game 

95 g.process_action(draw) 

96 g.process_action(ShowCards(src, draw.cards)) 

97 if [c for c in draw.cards if c.suit != Card.CLUB]: # any non-club 

98 tgt.tags['melancholy_tag'] = g.turn_count 

99 self.effective = True 

100 

101 else: 

102 self.effective = False 

103 

104 return True 

105 

106 

107class MelancholyHandler(THBEventHandler): 

108 interested = ('action_after', 'action_shootdown') 

109 execute_after = ( 

110 'DyingHandler', 

111 'AyaRoundfanHandler', 

112 'NenshaPhoneHandler', 

113 ) 

114 

115 def handle(self, evt_type, act): 

116 if evt_type == 'action_after' and isinstance(act, Damage): 

117 act = act 

118 tgt = act.target 

119 src = act.source 

120 

121 if not src: 

122 return act 

123 

124 if not tgt.has_skill(Melancholy): 

125 return act 

126 

127 g = self.game 

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

129 return act 

130 

131 g.process_action(MelancholyAction(tgt, src, amount=1)) 

132 

133 elif evt_type == 'action_shootdown' and isinstance(act, (LaunchCard, UseCard)): 

134 src = act.source 

135 g = self.game 

136 if src.tags.get('melancholy_tag') != g.turn_count: 

137 return act 

138 

139 def walk(c): 

140 if not c.is_card(VirtualCard): 

141 return [c] 

142 

143 if c.usage not in ('launch', 'use'): 

144 return [] 

145 

146 cards = c.associated_cards 

147 return walk(cards[0]) if len(cards) == 1 else cards 

148 

149 cards = walk(act.card) 

150 zone = src.cards, src.showncards 

151 for c in cards: 

152 if c.resides_in in zone: 

153 raise MelancholyLimit 

154 

155 return act 

156 

157 

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

159class Medicine(Character): 

160 skills = [Ciguatera, Melancholy] 

161 eventhandlers = [CiguateraHandler, MelancholyHandler] 

162 maxlife = 3