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

5# -- third party -- 

6# -- own -- 

7from thb.actions import ActionLimitExceeded, ActionShootdown, DrawCards, LaunchCard, Pindian 

8from thb.actions import PrepareStage, UserAction 

9from thb.cards.base import Skill, VirtualCard 

10from thb.cards.classes import AttackCard, TreatAs, WineCard, t_None, t_OtherOne 

11from thb.characters.base import Character, register_character_to 

12from thb.mode import THBEventHandler 

13 

14 

15# -- code -- 

16class HeavyDrinkerWine(TreatAs, VirtualCard): 

17 treat_as = WineCard 

18 

19 

20class HeavyDrinkerFailed(ActionShootdown): 

21 pass 

22 

23 

24class HeavyDrinkerAction(UserAction): 

25 def apply_action(self): 

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

27 g = self.game 

28 src.tags['suika_target'].append(tgt) 

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

30 g.process_action(LaunchCard(src, [src], HeavyDrinkerWine(src), bypass_check=True)) 

31 g.process_action(LaunchCard(tgt, [tgt], HeavyDrinkerWine(src), bypass_check=True)) 

32 

33 else: 

34 src.tags['suika_failed'] = src.tags['turn_count'] 

35 

36 return True 

37 

38 def is_valid(self): 

39 tags = self.source.tags 

40 if tags['suika_failed'] >= tags['turn_count']: 

41 raise HeavyDrinkerFailed 

42 

43 if self.target in tags['suika_target']: 

44 raise ActionLimitExceeded 

45 

46 Pindian(self.source, self.target).action_shootdown_exception() 

47 

48 return True 

49 

50 

51class HeavyDrinker(Skill): 

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

53 associated_action = HeavyDrinkerAction 

54 target = t_OtherOne() 

55 

56 def check(self): 

57 return not self.associated_cards 

58 

59 

60class HeavyDrinkerHandler(THBEventHandler): 

61 interested = ['action_apply'] 

62 execute_before = ['WineHandler'] 

63 

64 def handle(self, evt_type, act): 

65 if evt_type == 'action_apply' and isinstance(act, PrepareStage): 

66 act.target.tags['suika_target'] = [] 

67 

68 return act 

69 

70 

71class DrunkenDream(Skill): 

72 target = t_None() 

73 associated_action = None 

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

75 

76 

77class DrunkenDreamDrawCards(DrawCards): 

78 pass 

79 

80 

81class DrunkenDreamHandler(THBEventHandler): 

82 interested = ['action_apply', 'calcdistance'] 

83 execute_before = ['WineHandler'] 

84 

85 def handle(self, evt_type, act): 

86 if evt_type == 'calcdistance': 

87 src, card, dist = act 

88 if card.is_card(AttackCard): 

89 if not src.has_skill(DrunkenDream): 

90 return act 

91 

92 if not src.tags['wine']: 

93 return act 

94 

95 for p in dist: 

96 dist[p] -= 2 

97 

98 elif evt_type == 'action_apply' and isinstance(act, PrepareStage): 

99 tgt = act.target 

100 if not tgt.has_skill(DrunkenDream): 

101 return act 

102 

103 if not tgt.tags['wine']: 

104 return act 

105 

106 g = self.game 

107 g.process_action(DrunkenDreamDrawCards(tgt, 1)) 

108 

109 return act 

110 

111 

112@register_character_to('common') 

113class Suika(Character): 

114 skills = [HeavyDrinker, DrunkenDream] 

115 eventhandlers = [ 

116 HeavyDrinkerHandler, 

117 DrunkenDreamHandler, 

118 ] 

119 maxlife = 4