Coverage for thb/characters/rumia.py : 96%
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, FinalizeStage, LaunchCard, UserAction, user_choose_cards
9from thb.cards.base import PhysicalCard, Skill, t_None, t_OtherN
10from thb.cards.basic import Attack
11from thb.cards.definition import AttackCard, RejectCard
12from thb.cards.spellcard import BaseDuel
13from thb.characters.base import Character, register_character_to
14from thb.mode import THBEventHandler
17# -- code --
18class DarknessDuel(BaseDuel):
19 pass
22class DarknessAction(UserAction):
23 card_usage = 'launch'
25 def apply_action(self):
26 attacker, victim = self.target_list
27 src = self.source
28 g = self.game
29 tags = self.source.tags
30 tags['darkness_tag'] = tags['turn_count']
32 cards = user_choose_cards(self, attacker, ('cards', 'showncards'))
33 if cards:
34 c = cards[0]
35 g.process_action(LaunchCard(attacker, [victim], c))
36 else:
37 g.process_action(Damage(src, attacker, 1))
39 return True
41 def cond(self, cl):
42 if len(cl) != 1: return False
43 c = cl[0]
44 if not c.associated_action: return False
45 return issubclass(c.associated_action, Attack)
47 def ask_for_action_verify(self, p, cl, tl):
48 attacker, victim = self.target_list
49 return LaunchCard(attacker, [victim], cl[0]).can_fire()
51 def is_valid(self):
52 tags = self.source.tags
53 if tags['turn_count'] <= tags['darkness_tag']:
54 return False
56 attacker, victim = self.target_list
57 if not LaunchCard(attacker, [victim], AttackCard()).can_fire():
58 return False
60 return True
63class Darkness(Skill):
64 associated_action = DarknessAction
65 skill_category = ['character', 'active']
66 target = t_OtherN(2)
67 usage = 'drop'
69 def check(self):
70 cl = self.associated_cards
71 if not(cl and len(cl) == 1):
72 return False
74 if cl[0].is_card(Skill): 74 ↛ 75line 74 didn't jump to line 75, because the condition on line 74 was never true
75 return False
77 return True
80class DarknessKOF(Skill):
81 associated_action = None
82 skill_category = ['character', 'passive']
83 target = t_None()
86class DarknessKOFAction(UserAction):
87 def apply_action(self):
88 tgt = self.target
89 g = self.game
90 tgt.tags['darkness_kof_tag'] = max(g.turn_count, 1)
91 return True
94class DarknessKOFLimit(ActionShootdown):
95 pass
98class DarknessKOFHandler(THBEventHandler):
99 interested = ['character_debut', 'action_shootdown']
101 def handle(self, evt_type, arg):
102 if evt_type == 'character_debut':
103 old, new = arg
104 if new.has_skill(DarknessKOF):
105 g = self.game
106 g.process_action(DarknessKOFAction(new, new))
108 elif evt_type == 'action_shootdown' and isinstance(arg, LaunchCard):
109 src = arg.source
110 if not src: 110 ↛ 111line 110 didn't jump to line 111, because the condition on line 110 was never true
111 return arg
113 g = self.game
114 opp = g.get_opponent(arg.source)
115 if opp.tags['darkness_kof_tag'] < g.turn_count: 115 ↛ 116line 115 didn't jump to line 116, because the condition on line 115 was never true
116 return arg
118 card = arg.card
119 if not card.is_card(PhysicalCard) and 'treat_as' not in card.category:
120 return arg
122 if card.is_card(RejectCard):
123 return arg
125 # XXX: DollControl's second target do not count as target
126 # but in KOF the second target is always the launcher,
127 # and never be the opp, so the handle can be same.
128 if opp in arg.target_list:
129 raise DarknessKOFLimit
131 return arg
134class Cheating(Skill):
135 associated_action = None
136 skill_category = ['character', 'passive', 'compulsory']
137 target = t_None()
140class CheatingDrawCards(DrawCards):
141 pass
144class CheatingHandler(THBEventHandler):
145 interested = ('action_apply',)
146 execute_before = ('CiguateraHandler', )
148 def handle(self, evt_type, act):
149 if evt_type == 'action_apply' and isinstance(act, FinalizeStage):
150 tgt = act.target
151 if tgt.has_skill(Cheating) and not tgt.dead:
152 g = self.game
153 g.process_action(CheatingDrawCards(tgt, 1))
154 return act
157@register_character_to('common', '-kof')
158class Rumia(Character):
159 skills = [Darkness, Cheating]
160 eventhandlers = [CheatingHandler]
161 maxlife = 3
164@register_character_to('kof')
165class RumiaKOF(Character):
166 skills = [DarknessKOF, Cheating]
167 eventhandlers = [DarknessKOFHandler, CheatingHandler]
168 maxlife = 3