# Coverage for thb/characters/meirin.py : 98%

## 87 statements 87 run 0 missing 0 excluded 2 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

3# -- stdlib --

4# -- third party --

5# -- own --

6 from thb.actions import DropCards, GenericAction, MaxLifeChange, PlayerTurn, random_choose_card

7 from thb.cards.base import DummyCard, Skill, t_None

8 from thb.cards.classes import AttackCard, BaseAttack, GrazeCard, LaunchGraze, TreatAs

9 from thb.characters.base import Character, register_character_to

10 from thb.inputlets import ChooseOptionInputlet, ChoosePeerCardInputlet

11 from thb.mode import THBEventHandler

12

13

14# -- code --

15 class LoongPunch(Skill):

16 associated_action = None

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

18 target = t_None()

19

20

21 class Taichi(TreatAs, Skill):

22 skill_category = ['character', 'active']

23

24 @property

25 def treat_as(self):

26 cl = self.associated_cards

27 if not cl: return DummyCard

28 c = cl[0]

29 if c.is_card(GrazeCard):

30 return AttackCard

31 if c.is_card(AttackCard):

32 return GrazeCard

33 return DummyCard

34

35 def check(self):

36 cl = self.associated_cards

37 if not cl or len(cl) != 1: return False

38 c = cl[0]

39 if not (c.is_card(AttackCard) or c.is_card(GrazeCard)): return False 39 ↛ exit line 39 didn't return from function 'check', because the return on line 39 wasn't executed

40 return c.resides_in is not None and c.resides_in.type in (

41 'cards', 'showncards',

42 )

43

44

45 class RiverBehind(Skill):

46 associated_action = None

47 skill_category = ['character', 'passive', 'awake']

48 target = t_None()

49

50

51 class LoongPunchAction(GenericAction):

52 def __init__(self, source, target, _type):

53 self.source = source

54 self.target = target

55 self.type = _type

56

57 def apply_action(self):

58 g = self.game

59 src, tgt = self.source, self.target

60 c = g.user_input([src], ChoosePeerCardInputlet(self, tgt, ('cards', 'showncards')))

61 c = c or random_choose_card(g, [tgt.cards, tgt.showncards])

62 if not c: return False 62 ↛ exit line 62 didn't return from function 'apply_action', because the return on line 62 wasn't executed

63 g.players.exclude(tgt).reveal(c)

64 g.process_action(DropCards(src, tgt, [c]))

65 return True

66

67

68 class LoongPunchHandler(THBEventHandler):

69 interested = ['action_after']

70 execute_after = ['DeathSickleHandler']

71

72 def handle(self, evt_type, act):

73 if evt_type == 'action_after' and isinstance(act, LaunchGraze):

74 if not act.succeeded: return act

75 g = self.game

76 pact = g.action_stack[-1]

77 if not isinstance(pact, BaseAttack): return act

78 self.do_effect(pact.source, pact.target, 'attack')

79 self.do_effect(pact.target, pact.source, 'graze')

80

81 return act

82

83 def do_effect(self, src, tgt, _type):

84 if not src.has_skill(LoongPunch): return

85 if not (tgt.cards or tgt.showncards): return

86 g = self.game

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

88

89 g.process_action(LoongPunchAction(src, tgt, _type))

90

91

92 class RiverBehindAwake(GenericAction):

93 def apply_action(self):

94 tgt = self.target

95 assert tgt.has_skill(RiverBehind)

96 tgt.skills.remove(RiverBehind)

97 tgt.skills.append(Taichi)

98 g = self.game

99 g.process_action(MaxLifeChange(tgt, tgt, -1))

100 return True

101

102

103 class RiverBehindHandler(THBEventHandler):

104 interested = ['action_apply']

105

106 def handle(self, evt_type, act):

107 if evt_type == 'action_apply' and isinstance(act, PlayerTurn):

108 tgt = act.target

109 if not tgt.has_skill(RiverBehind): return act

110 g = self.game

111 if tgt.life <= 2 and tgt.life <= min(p.life for p in g.players if not p.dead):

112 g.process_action(RiverBehindAwake(tgt, tgt))

113 return act

114

115

116@register_character_to('common')

117 class Meirin(Character):

118 skills = [LoongPunch, RiverBehind]

119 eventhandlers = [RiverBehindHandler, LoongPunchHandler]

120 maxlife = 4