Coverage for thb/characters/suika.py : 98%
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
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
15# -- code --
16class HeavyDrinkerWine(TreatAs, VirtualCard):
17 treat_as = WineCard
20class HeavyDrinkerFailed(ActionShootdown):
21 pass
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))
33 else:
34 src.tags['suika_failed'] = src.tags['turn_count']
36 return True
38 def is_valid(self):
39 tags = self.source.tags
40 if tags['suika_failed'] >= tags['turn_count']:
41 raise HeavyDrinkerFailed
43 if self.target in tags['suika_target']: 43 ↛ 44line 43 didn't jump to line 44, because the condition on line 43 was never true
44 raise ActionLimitExceeded
46 Pindian(self.source, self.target).action_shootdown_exception()
48 return True
51class HeavyDrinker(Skill):
52 skill_category = ['character', 'active']
53 associated_action = HeavyDrinkerAction
54 target = t_OtherOne()
56 def check(self):
57 return not self.associated_cards
60class HeavyDrinkerHandler(THBEventHandler):
61 interested = ['action_apply']
62 execute_before = ['WineHandler']
64 def handle(self, evt_type, act):
65 if evt_type == 'action_apply' and isinstance(act, PrepareStage):
66 act.target.tags['suika_target'] = []
68 return act
71class DrunkenDream(Skill):
72 target = t_None()
73 associated_action = None
74 skill_category = ['character', 'passive']
77class DrunkenDreamDrawCards(DrawCards):
78 pass
81class DrunkenDreamHandler(THBEventHandler):
82 interested = ['action_apply', 'calcdistance']
83 execute_before = ['WineHandler']
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
92 if not src.tags['wine']:
93 return act
95 for p in dist:
96 dist[p] -= 2
98 elif evt_type == 'action_apply' and isinstance(act, PrepareStage):
99 tgt = act.target
100 if not tgt.has_skill(DrunkenDream):
101 return act
103 if not tgt.tags['wine']:
104 return act
106 g = self.game
107 g.process_action(DrunkenDreamDrawCards(tgt, 1))
109 return act
112@register_character_to('common')
113class Suika(Character):
114 skills = [HeavyDrinker, DrunkenDream]
115 eventhandlers = [
116 HeavyDrinkerHandler,
117 DrunkenDreamHandler,
118 ]
119 maxlife = 4