Coverage for thb/characters/nitori.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 thb.actions import ActionLimitExceeded, ActionStageLaunchCard, DrawCards, Reforge, UserAction
7from thb.actions import random_choose_card, ttags
8from thb.cards.base import PhysicalCard, Skill, TreatAs, t_OtherOne
9from thb.cards.definition import AttackCard
10from thb.characters.base import Character, register_character_to
11from thb.inputlets import ChoosePeerCardInputlet
12from thb.mode import THBEventHandler
15# -- code --
16class DismantleAction(UserAction):
17 def apply_action(self):
18 src, tgt = self.source, self.target
19 ttags(src)['dismantle'] = True
21 g = self.game
22 c = g.user_input([src], ChoosePeerCardInputlet(self, tgt, ('equips', )))
23 c = c or random_choose_card(g, [tgt.equips])
24 if not c: return False 24 ↛ exitline 24 didn't return from function 'apply_action', because the return on line 24 wasn't executed
26 g.process_action(Reforge(src, tgt, c))
27 g.process_action(DrawCards(tgt, 1))
29 return True
31 def is_valid(self):
32 return not ttags(self.source)['dismantle'] and bool(self.target.equips)
35class Dismantle(Skill):
36 associated_action = DismantleAction
37 skill_category = ['character', 'active']
38 target = t_OtherOne()
40 def check(self):
41 return not self.associated_cards
44class Craftsman(TreatAs, Skill):
45 skill_category = ['character', 'active']
47 @property
48 def treat_as(self):
49 params = getattr(self, 'action_params', {})
50 return PhysicalCard.classes.get(params.get('treat_as'), AttackCard)
52 def check(self):
53 cl = self.associated_cards
54 p = self.character
56 if 'basic' not in self.treat_as.category: 56 ↛ 57line 56 didn't jump to line 57, because the condition on line 56 was never true
57 return False
59 if not cl or set(cl) != (set(p.cards) | set(p.showncards)):
60 return False
62 return True
64 @classmethod
65 def list_treat_as(cls):
66 return [c() for c in PhysicalCard.classes.values() if 'basic' in c.category]
69class CraftsmanHandler(THBEventHandler):
70 interested = ['action_after', 'action_shootdown']
72 def handle(self, evt_type, act):
73 if evt_type == 'action_after' and isinstance(act, ActionStageLaunchCard):
74 c = act.card
75 if c.is_card(Craftsman):
76 src = act.source
77 ttags(src)['craftsman'] = True
79 elif evt_type == 'action_shootdown':
80 if not isinstance(act, ActionStageLaunchCard): return act
81 c = act.card
82 if not c.is_card(Craftsman): return act
83 if ttags(act.source)['craftsman']: 83 ↛ 84line 83 didn't jump to line 84, because the condition on line 83 was never true
84 raise ActionLimitExceeded
86 return act
89@register_character_to('common', '-kof')
90class Nitori(Character):
91 skills = [Dismantle, Craftsman]
92 eventhandlers = [CraftsmanHandler]
93 maxlife = 3