Coverage for thb/characters/kokoro.py : 87%
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 thb.actions import ActionStage, DropCards, ShowCards, UserAction, migrate_cards
7from thb.actions import user_choose_cards
8from thb.cards.base import Card, Skill
9from thb.cards.classes import t_None, t_OtherOne
10from thb.characters.base import Character, register_character_to
11from thb.inputlets import ChooseOptionInputlet, HopeMaskInputlet, HopeMaskKOFInputlet
12from thb.mode import THBEventHandler
15# -- code --
16class BaseHopeMaskAction(UserAction):
18 def apply_action(self):
19 tgt = self.target
20 g = self.game
21 n = 1 + tgt.maxlife - tgt.life
22 cards = g.deck.getcards(n)
24 tgt.reveal(cards)
25 putback, acquire = g.user_input([tgt], self.inputlet_cls(self, cards), timeout=20)
26 for c in acquire: 26 ↛ 27line 26 didn't jump to line 27, because the loop on line 26 never started
27 c.detach()
29 assert not putback or set(putback) == set(g.deck.getcards(len(putback)))
31 deck = g.deck.cards
32 for i, c in enumerate(putback):
33 deck[i] = c
35 assert not putback or putback == g.deck.getcards(len(putback))
37 if acquire: 37 ↛ 38line 37 didn't jump to line 38, because the condition on line 37 was never true
38 g.process_action(ShowCards(tgt, acquire))
39 migrate_cards(acquire, tgt.cards)
41 self.acquire = acquire
43 return True
46class HopeMaskAction(BaseHopeMaskAction):
47 inputlet_cls = HopeMaskInputlet
50class HopeMaskKOFAction(BaseHopeMaskAction):
51 inputlet_cls = HopeMaskKOFInputlet
54class BaseHopeMaskHandler(THBEventHandler):
55 interested = ['action_apply']
57 def handle(self, evt_type, act):
58 if evt_type == 'action_apply' and isinstance(act, ActionStage):
59 tgt = act.target
60 if not tgt.has_skill(self.skill): return act
61 g = self.game
62 if not g.user_input([tgt], ChooseOptionInputlet(self, (False, True))):
63 return act
64 g.process_action(self.action(tgt, tgt))
66 return act
69class HopeMask(Skill):
70 associated_action = None
71 skill_category = ['character', 'passive']
72 target = t_None()
75class HopeMaskKOF(Skill):
76 associated_action = None
77 skill_category = ['character', 'passive']
78 target = t_None()
81class HopeMaskHandler(BaseHopeMaskHandler):
82 skill = HopeMask
83 action = HopeMaskAction
86class HopeMaskKOFHandler(BaseHopeMaskHandler):
87 skill = HopeMaskKOF
88 action = HopeMaskKOFAction
91class BaseDarkNohAction(UserAction):
92 card_usage = 'drop'
94 def apply_action(self):
95 src, tgt = self.source, self.target
96 g = self.game
98 src.tags['darknoh_tag'] = src.tags['turn_count']
99 sk = self.associated_card
100 card = sk.associated_cards[0]
101 self.card = card
102 migrate_cards([sk], tgt.showncards, unwrap=True)
103 self.n = n = len(tgt.cards) + len(tgt.showncards) - tgt.life
104 if n <= 0: return True
106 cards = user_choose_cards(self, tgt, ('cards', 'showncards'))
107 if not cards: 107 ↛ 116line 107 didn't jump to line 116, because the condition on line 107 was never false
108 cl = list(tgt.cards) + list(tgt.showncards)
109 try:
110 cl.remove(card)
111 except Exception:
112 pass
114 cards = cl[:n]
116 g.players.reveal(cards)
117 g.process_action(DropCards(src, tgt, cards))
119 return True
121 def cond(self, cards):
122 if len(cards) != self.n or self.card in cards:
123 return False
125 if any([c.is_card(Skill) for c in cards]): 125 ↛ 128line 125 didn't jump to line 128, because the condition on line 125 was never false
126 return False
128 return True
131class DarkNohAction(BaseDarkNohAction):
133 def is_valid(self):
134 src = self.source
135 tgt = self.target
137 if src.tags['darknoh_tag'] >= src.tags['turn_count']:
138 return False
140 if src.life > tgt.life:
141 return False
143 return True
146class DarkNohKOFAction(BaseDarkNohAction):
148 def is_valid(self):
149 src = self.source
150 tgt = self.target
152 if src.tags['darknoh_tag'] > 0:
153 return False
155 if src.life > tgt.life:
156 return False
158 return True
161class BaseDarkNoh(Skill):
162 no_drop = True
163 skill_category = ['character', 'active']
164 target = t_OtherOne()
165 usage = 'handover'
167 def check(self):
168 cards = self.associated_cards
169 if len(cards) != 1: return False
170 c = cards[0]
171 if c.resides_in is None: return False 171 ↛ exitline 171 didn't return from function 'check', because the return on line 171 wasn't executed
172 if c.resides_in.type not in ('cards', 'showncards', 'equips'): return False 172 ↛ exitline 172 didn't return from function 'check', because the return on line 172 wasn't executed
173 if c.suit not in (Card.SPADE, Card.CLUB): return False
174 return True
177class DarkNoh(BaseDarkNoh):
178 associated_action = DarkNohAction
181class DarkNohKOF(BaseDarkNoh):
182 associated_action = DarkNohKOFAction
185@register_character_to('common', '-kof')
186class Kokoro(Character):
187 skills = [HopeMask, DarkNoh]
188 eventhandlers = [HopeMaskHandler]
189 maxlife = 3
192@register_character_to('kof')
193class KokoroKOF(Character):
194 skills = [HopeMaskKOF, DarkNohKOF]
195 eventhandlers = [HopeMaskKOFHandler]
196 maxlife = 3