Coverage for thb/characters/medicine.py : 90%
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 -*-
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
16# -- code --
17class Ciguatera(Skill):
18 associated_action = None
19 skill_category = ['character', 'passive']
20 target = t_None()
23class CiguateraAction(UserAction):
24 def __init__(self, source, target, cards):
25 self.source = source
26 self.target = target
27 self.cards = cards
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))
37 return True
40class CiguateraHandler(THBEventHandler):
41 interested = ('action_before',)
42 card_usage = 'drop'
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
52 if not p.has_skill(Ciguatera):
53 continue
55 cards = user_choose_cards(self, p, ('cards', 'showncards', 'equips'))
56 if cards: 56 ↛ 57line 56 didn't jump to line 57, because the condition on line 56 was never true
57 g.process_action(CiguateraAction(p, act.target, cards))
59 return act
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
69class Melancholy(Skill):
70 associated_action = None
71 skill_category = ['character', 'passive']
72 target = t_None()
75class MelancholyPoison(VirtualCard):
76 associated_action = None
77 target = t_None()
80class MelancholyLimit(ActionShootdown):
81 pass
84class MelancholyAction(GenericAction):
85 def __init__(self, source, target, amount):
86 self.source = source
87 self.target = target
88 self.amount = amount
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
101 else:
102 self.effective = False
104 return True
107class MelancholyHandler(THBEventHandler):
108 interested = ('action_after', 'action_shootdown')
109 execute_after = (
110 'DyingHandler',
111 'AyaRoundfanHandler',
112 'NenshaPhoneHandler',
113 )
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
121 if not src:
122 return act
124 if not tgt.has_skill(Melancholy):
125 return act
127 g = self.game
128 if not g.user_input([tgt], ChooseOptionInputlet(self, (False, True))):
129 return act
131 g.process_action(MelancholyAction(tgt, src, amount=1))
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
139 def walk(c):
140 if not c.is_card(VirtualCard):
141 return [c]
143 if c.usage not in ('launch', 'use'): 143 ↛ 144line 143 didn't jump to line 144, because the condition on line 143 was never true
144 return []
146 cards = c.associated_cards
147 return walk(cards[0]) if len(cards) == 1 else cards
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
155 return act
158@register_character_to('common', '-kof')
159class Medicine(Character):
160 skills = [Ciguatera, Melancholy]
161 eventhandlers = [CiguateraHandler, MelancholyHandler]
162 maxlife = 3