# Coverage for thb/characters/tenshi.py : 30%

## 95 statements 38 run 57 missing 0 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

3# -- stdlib --

4# -- third party --

5# -- own --

6 from thb.actions import Damage, DrawCards, Fatetell, GenericAction, LaunchCard, UserAction

7 from thb.actions import ask_for_action, migrate_cards

8 from thb.cards.base import Card, Skill, ShreddedCard

9 from thb.cards.classes import t_None

10 from thb.characters.base import Character, register_character_to

11 from thb.inputlets import ChooseOptionInputlet

12 from thb.mode import THBEventHandler

13

14

15# -- code --

16

17# 「抖M」技能，对应郭嘉的「遗计」

18 class Masochist(Skill):

19 # 技能没有附带的动作，仅被动触发

20 associated_action = None

21 # 技能的分类

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

23 # 技能的目标，因为没有附带动作所以也没有目标

24 target = t_None()

25

26

27# 「抖M」技能动作

28 class MasochistAction(UserAction):

29 # 在请求玩家输入后，不要自动将牌面告知其他玩家

30 no_reveal = True

31 # 卡牌的使用场景是「交给其他人」

32 card_usage = 'handover'

33

34 # 参数分别是动作目标（自己）和受到伤害的数量

35 def __init__(self, target, n):

36 self.source, self.target, self.amount = target, target, n

37

38 # 动作的逻辑

39 def apply_action(self):

40 g = self.game

41 tgt = self.target

42 # 构造自己摸两张牌的动作

43 a = DrawCards(tgt, self.amount * 2)

44 # 执行这个动作

45 g.process_action(a)

46 self.cards = cards = a.cards

47 n = len(cards)

48 # 如果牌还没有送完，继续执行

49 while n > 0:

50 # 选取其他没有阵亡的角色

51 pl = [p for p in g.players if not p.dead]

52 pl.remove(tgt)

53 if not pl:

54 return True

55

56 # 玩家选择给出的牌和目标玩家

57 _, rst = ask_for_action(self, [tgt], ('cards',), pl)

58 if not rst:

59 return True

60

61 cl, pl = rst

62 # 告知目标牌面

63 pl[0].player.reveal(cl)

64 # 转移卡牌

65 migrate_cards(cl, pl[0].cards)

66 n -= len(cl)

67

68 return True

69

70 # ask_for_action 函数用的条件，给出的牌必须是拿到的牌

71 def cond(self, cl):

72 cards = self.cards

73 return all(c in cards for c in cl)

74

75 # ask_for_action 函数用的条件，给出的牌必须是拿到的牌

76 def choose_player_target(self, tl):

77 if not tl:

78 return (tl, False)

79

80 return (tl[-1:], True)

81

82

83# 「抖M」技能的事件触发逻辑

84 class MasochistHandler(THBEventHandler):

85 interested = ['action_after']

86 execute_after = [

87 'DyingHandler',

88 'AyaRoundfanHandler',

89 'NenshaPhoneHandler',

90 ]

91

92 def handle(self, evt_type, act):

93 # 当受到伤害后

94 if evt_type == 'action_after' and isinstance(act, Damage):

95 # 如果目标没有阵亡，且身负「抖M」技能

96 tgt = act.target

97 if tgt.dead: return act

98 if not tgt.has_skill(Masochist): return act

99 if not act.amount: return act

100

101 # 选择是否发动

102 g = self.game

103 if not g.user_input([tgt], ChooseOptionInputlet(self, (False, True))):

104 return act

105

106 # 实际发动技能

107 g.process_action(MasochistAction(tgt, act.amount))

108

109 return act

110

111

112# 「绯想」技能，对应郭嘉「天妒」

113# 锁定技，距离1以内的角色的红色判定牌置入弃牌堆时，你获得之。

114 class ScarletPerception(Skill):

115 distance = 1

116 associated_action = None

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

118 target = t_None()

119

120

121 class ScarletPerceptionAction(GenericAction):

122 def __init__(self, source, target, card):

123 self.source = source

124 self.target = target

125 self.card = card

126

127 def apply_action(self):

128 migrate_cards([self.card], self.source.cards)

129 return True

130

131

132 class ScarletPerceptionHandler(THBEventHandler):

133 interested = ['action_after']

134

135 def handle(self, evt_type, act):

136 # 在判定结束后

137 if evt_type == 'action_after' and isinstance(act, Fatetell):

138 tgt = act.target

139

140 # 如果牌的颜色是红色，而且没有在某个牌区内（不属于任何人，或者牌堆）

141 if act.card.color != Card.RED: return act

142 g = self.game

143 if not act.card.detached:

144 return act

145

146 # 此处只有被小爱的技能 drop 掉这一种情况，没发现其他的

147 if isinstance(act.card, ShreddedCard):

148 return act

149

150 # 寻找场内身负「绯想」技能的人

151 g = self.game

152 pl = [p for p in g.players if p.has_skill(ScarletPerception) and not p.dead]

153

154 for p in pl:

155 p = pl[0]

156 dist = LaunchCard.calc_distance(g, p, ScarletPerception(p))

157 # 若满足距离限制

158 if dist.get(tgt, 1) <= 0:

159 # 执行获得牌的动作

160 g.process_action(ScarletPerceptionAction(p, tgt, act.card))

161 break

162

163 return act

164

165

166# 「比那名居天子」人物

167@register_character_to('common')

168 class Tenshi(Character):

169 # 人物技能

170 skills = [Masochist, ScarletPerception]

171 # 需要的事件处理器

172 eventhandlers = [MasochistHandler, ScarletPerceptionHandler]

173 # 最大体力

174 maxlife = 3