# Coverage for thb/characters/yugi.py : 39%

## 91 statements 44 run 47 missing 2 excluded 0 partial

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 -*-

2 from __future__ import annotations

3

4# -- stdlib --

5 from typing import TYPE_CHECKING, cast

6

7# -- third party --

8# -- own --

9 from thb.actions import Damage, DropCards, FatetellAction, LaunchCard, random_choose_card

10 from thb.cards.base import Card, Skill, VirtualCard

11 from thb.cards.classes import AttackCard, BaseAttack, InevitableAttack, RedUFOSkill, TreatAs, t_None

12 from thb.characters.base import Character, register_character_to

13 from thb.inputlets import ChooseOptionInputlet, ChoosePeerCardInputlet

14 from thb.mode import THBEventHandler, THBAction

15 from utils.misc import classmix

16

17# -- typing --

18 if TYPE_CHECKING:

19 from thb.thbkof import THBattleKOF # noqa: F401

20

21

22# -- code --

23 class Assault(RedUFOSkill):

24 skill_category = ['character', 'passive', 'compulsory']

25 increment = 1

26

27

28 class AssaultKOF(Skill):

29 associated_action = None

30 skill_category = ['character', 'passive']

31 target = t_None()

32

33

34 class AssaultAttack(TreatAs, VirtualCard):

35 treat_as = AttackCard

36

37

38 class AssaultKOFHandler(THBEventHandler):

39 interested = ['character_debut']

40 game: THBattleKOF

41

42 def handle(self, evt_type, arg):

43 if evt_type == 'character_debut':

44 old, new = arg

45 if not new.has_skill(AssaultKOF):

46 return arg

47

48 g = self.game

49 op = g.get_opponent(new)

50 lc = LaunchCard(new, [op], AssaultAttack(new))

51 if not lc.can_fire():

52 return arg

53

54 if g.user_input([new], ChooseOptionInputlet(self, (False, True))):

55 g.process_action(lc)

56

57 return arg

58

59

60 class FreakingPower(Skill):

61 associated_action = None

62 skill_category = ['character', 'passive']

63 target = t_None()

64

65

66 class FreakingPowerAction(FatetellAction):

67 def __init__(self, atkact):

68 self.atkact = atkact

69 self.source = atkact.source

70 self.target = atkact.target

71 self.fatetell_target = atkact.source

72

73 def fatetell_action(self, ft):

74 act = self.atkact

75 if ft.succeeded:

76 act.__class__ = classmix(InevitableAttack, act.__class__)

77 else:

78 act._['freaking_power'] = True

79

80 return True

81

82 @staticmethod

83 def fatetell_cond(c):

84 return c.color == Card.RED

85

86

87 class FreakingPowerHandler(THBEventHandler):

88 interested = ['action_after', 'action_before']

89 execute_before = ['AyaRoundfanHandler']

90

91 def handle(self, evt_type, act):

92 if evt_type == 'action_before' and isinstance(act, BaseAttack) and not act._['freaking_power']:

93 src = act.source

94 g = self.game

95 if not src.has_skill(FreakingPower): return act

96 if not g.user_input([src], ChooseOptionInputlet(self, (False, True))):

97 return act

98 tgt = act.target

99 g.process_action(FreakingPowerAction(act))

100

101 elif evt_type == 'action_after' and isinstance(act, Damage):

102 g = self.game

103

104 if act.cancelled: return act

105

106 pact = cast(THBAction, g.action_stack[-1])

107 if not pact._['freaking_power']:

108 return act

109

110 src, tgt = pact.source, act.target

111 if tgt.dead: return act

112

113 if not (tgt.cards or tgt.showncards or tgt.equips):

114 return act

115

116 catnames = ('cards', 'showncards', 'equips')

117 card = g.user_input([src], ChoosePeerCardInputlet(self, tgt, catnames))

118 card = card or random_choose_card(g, [tgt.cards, tgt.showncards, tgt.equips])

119 if card:

120 g.players.exclude(tgt).reveal(card)

121 g.process_action(DropCards(src, tgt, [card]))

122

123 return act

124

125

126@register_character_to('common', '-kof')

127 class Yugi(Character):

128 skills = [Assault, FreakingPower]

129 eventhandlers = [FreakingPowerHandler]

130 maxlife = 4

131

132

133@register_character_to('kof')

134 class YugiKOF(Character):

135 skills = [AssaultKOF, FreakingPower]

136 eventhandlers = [AssaultKOFHandler, FreakingPowerHandler]

137 maxlife = 4