Coverage for thb/characters/medicine.py : 30%
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 game.base import ActionShootdown
8from thb.actions import Damage, DrawCards, DropCards, FatetellStage, GenericAction, LaunchCard
9from thb.actions import LifeLost, ShowCards, UseCard, UserAction, user_choose_cards
10from thb.cards.base import Card, Skill, VirtualCard
11from thb.cards.classes import Wine, t_None
12from thb.characters.base import Character, register_character_to
13from thb.inputlets import ChooseOptionInputlet
14from thb.mode import THBEventHandler
17# -- code --
18class Ciguatera(Skill):
19 associated_action = None
20 skill_category = ['character', 'passive']
21 target = t_None()
24class CiguateraAction(UserAction):
25 def __init__(self, source, target, cards):
26 self.source = source
27 self.target = target
28 self.cards = cards
30 def apply_action(self):
31 tgt = self.target
32 src = self.source
33 g = self.game
34 g.process_action(DropCards(src, src, self.cards))
35 g.process_action(LifeLost(src, tgt, 1))
36 g.process_action(Wine(src, tgt))
38 return True
41class CiguateraHandler(THBEventHandler):
42 interested = ['action_before']
43 card_usage = 'drop'
45 def handle(self, evt_type, act):
46 if evt_type == 'action_before' and isinstance(act, FatetellStage):
47 if act.target.dead: return act
48 g = self.game
49 for p in g.players:
50 if p.dead:
51 continue
53 if not p.has_skill(Ciguatera):
54 continue
56 cards = user_choose_cards(self, p, ('cards', 'showncards', 'equips'))
57 if cards:
58 g.process_action(CiguateraAction(p, act.target, cards))
60 return act
62 def cond(self, cl):
63 return \
64 len(cl) == 1 and \
65 not cl[0].is_card(Skill) and \
66 cl[0].resides_in.type in ('cards', 'showncards', 'equips') and \
67 cl[0].color == Card.BLACK
70class Melancholy(Skill):
71 associated_action = None
72 skill_category = ['character', 'passive']
73 target = t_None()
76class MelancholyPoison(VirtualCard):
77 associated_action = None
78 target = t_None()
81class MelancholyLimit(ActionShootdown):
82 pass
85class MelancholyAction(GenericAction):
86 def __init__(self, source, target, amount):
87 self.source = source
88 self.target = target
89 self.amount = amount
91 def apply_action(self):
92 src = self.source
93 tgt = self.target
94 draw = DrawCards(src, self.amount)
95 g = self.game
96 g.process_action(draw)
97 g.process_action(ShowCards(src, draw.cards))
98 if [c for c in draw.cards if c.suit != Card.CLUB]: # any non-club
99 tgt.tags['melancholy_tag'] = g.turn_count
100 self.effective = True
102 else:
103 self.effective = False
105 return True
108class MelancholyHandler(THBEventHandler):
109 interested = ['action_after', 'action_shootdown']
110 execute_after = [
111 'DyingHandler',
112 'AyaRoundfanHandler',
113 'NenshaPhoneHandler',
114 ]
116 def handle(self, evt_type, act):
117 if evt_type == 'action_after' and isinstance(act, Damage):
118 act = act
119 tgt = act.target
120 src = act.source
122 if not src:
123 return act
125 if not tgt.has_skill(Melancholy):
126 return act
128 g = self.game
129 if not g.user_input([tgt], ChooseOptionInputlet(self, (False, True))):
130 return act
132 g.process_action(MelancholyAction(tgt, src, amount=1))
134 elif evt_type == 'action_shootdown' and isinstance(act, (LaunchCard, UseCard)):
135 src = act.source
136 g = self.game
137 if src.tags.get('melancholy_tag') != g.turn_count:
138 return act
140 def walk(c):
141 if not c.is_card(VirtualCard):
142 return [c]
144 if c.usage not in ('launch', 'use'):
145 return []
147 cards = c.associated_cards
148 return walk(cards[0]) if len(cards) == 1 else cards
150 cards = walk(act.card)
151 zone = src.cards, src.showncards
152 for c in cards:
153 if c.resides_in in zone:
154 raise MelancholyLimit
156 return act
159@register_character_to('common', '-kof')
160class Medicine(Character):
161 skills = [Ciguatera, Melancholy]
162 eventhandlers = [CiguateraHandler, MelancholyHandler]
163 maxlife = 3