Coverage for thb/characters/yugi.py : 80%
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 thb.actions import Damage, DropCards, FatetellAction, LaunchCard, random_choose_card
8from thb.cards.base import Card, Skill, VirtualCard
9from thb.cards.classes import AttackCard, BaseAttack, InevitableAttack, RedUFOSkill, TreatAs, t_None
10from thb.characters.base import Character, register_character_to
11from thb.inputlets import ChooseOptionInputlet, ChoosePeerCardInputlet
12from thb.mode import THBEventHandler
13from utils.misc import classmix
16# -- code --
17class Assault(RedUFOSkill):
18 skill_category = ['character', 'passive', 'compulsory']
19 increment = 1
22class AssaultKOF(Skill):
23 associated_action = None
24 skill_category = ['character', 'passive']
25 target = t_None()
28class AssaultAttack(TreatAs, VirtualCard):
29 treat_as = AttackCard
32class AssaultKOFHandler(THBEventHandler):
33 interested = ['character_debut']
35 def handle(self, evt_type, arg):
36 if evt_type == 'character_debut':
37 old, new = arg
38 if not new.has_skill(AssaultKOF):
39 return arg
41 g = self.game
42 op = g.get_opponent(new)
43 lc = LaunchCard(new, [op], AssaultAttack(new))
44 if not lc.can_fire():
45 return arg
47 if g.user_input([new], ChooseOptionInputlet(self, (False, True))):
48 g.process_action(lc)
50 return arg
53class FreakingPower(Skill):
54 associated_action = None
55 skill_category = ['character', 'passive']
56 target = t_None()
59class FreakingPowerAction(FatetellAction):
60 def __init__(self, atkact):
61 self.atkact = atkact
62 self.source = atkact.source
63 self.target = atkact.target
64 self.fatetell_target = atkact.source
66 def fatetell_action(self, ft):
67 act = self.atkact
68 if ft.succeeded:
69 act.__class__ = classmix(InevitableAttack, act.__class__)
70 else:
71 act._['freaking_power'] = True
73 return True
75 @staticmethod
76 def fatetell_cond(c):
77 return c.color == Card.RED
80class FreakingPowerHandler(THBEventHandler):
81 interested = ('action_after', 'action_before', )
82 execute_before = ('AyaRoundfanHandler',)
84 def handle(self, evt_type, act):
85 if evt_type == 'action_before' and isinstance(act, BaseAttack) and not act._['freaking_power']:
86 src = act.source
87 g = self.game
88 if not src.has_skill(FreakingPower): return act
89 if not g.user_input([src], ChooseOptionInputlet(self, (False, True))):
90 return act
91 tgt = act.target
92 g.process_action(FreakingPowerAction(act))
94 elif evt_type == 'action_after' and isinstance(act, Damage):
95 g = self.game
97 if act.cancelled: return act 97 ↛ exitline 97 didn't return from function 'handle', because the return on line 97 wasn't executed
99 pact = g.action_stack[-1]
100 if not pact._['freaking_power']:
101 return act
103 src, tgt = pact.source, act.target
104 if tgt.dead: return act
106 if not (tgt.cards or tgt.showncards or tgt.equips): 106 ↛ 107line 106 didn't jump to line 107, because the condition on line 106 was never true
107 return act
109 catnames = ('cards', 'showncards', 'equips')
110 card = g.user_input([src], ChoosePeerCardInputlet(self, tgt, catnames))
111 card = card or random_choose_card(g, [tgt.cards, tgt.showncards, tgt.equips])
112 if card: 112 ↛ 116line 112 didn't jump to line 116, because the condition on line 112 was never false
113 g.players.exclude(tgt).reveal(card)
114 g.process_action(DropCards(src, tgt, [card]))
116 return act
119@register_character_to('common', '-kof')
120class Yugi(Character):
121 skills = [Assault, FreakingPower]
122 eventhandlers = [FreakingPowerHandler]
123 maxlife = 4
126@register_character_to('kof')
127class YugiKOF(Character):
128 skills = [AssaultKOF, FreakingPower]
129 eventhandlers = [AssaultKOFHandler, FreakingPowerHandler]
130 maxlife = 4