# Coverage for thb/meta/characters/nitori.py : 86%

## 75 statements 67 run 8 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 from __future__ import annotations

3

4# -- stdlib --

5 import random

6

7# -- third party --

8# -- own --

9 from thb import actions, characters

10 from thb.actions import PlayerTurn, ttags

11 from thb.cards.classes import AttackCard, GrazeCard

12 from thb.meta.common import ui_meta

13

14

15# -- code --

16@ui_meta(characters.nitori.Dismantle)

17 class Dismantle:

18 # Skill

19 name = '拆解'

20 description = '出牌阶段限一次，你可以|B重铸|r一名其他角色装备区里的一张装备牌，然后该角色摸一张牌。'

21

22 def clickable(self):

23 if ttags(self.me)['dismantle']:

24 return False

25

26 return self.my_turn()

27

28 def is_action_valid(self, sk, tl):

29 if sk.associated_cards:

30 return (False, '请不要选择牌！')

31

32 if not len(tl):

33 return (False, '请选择一名玩家')

34

35 return (True, '拆解！')

36

37 def sound_effect(self, act):

38 return random.choice([

39 'thb-cv-nitori_dismantle',

40 'thb-cv-nitori_dismantle_other',

41 ])

42

43

44@ui_meta(characters.nitori.Craftsman)

45 class Craftsman:

46 name = '匠心'

47 description = '你可以将你的全部手牌（至少1张）当做任意的一张基本牌使用或打出。你的回合以此方式使用牌时，一回合限一次。'

48

49 params_ui = 'UICraftsmanCardSelection'

50

51 def clickable(self):

52 g = self.game

53 me = self.me

54 try:

55 if not me.cards and not me.showncards:

56 return False

57

58 current = PlayerTurn.get_current(g).target

59 if ttags(me)['craftsman'] and current is me:

60 return False

61

62 return True

63

64 except (IndexError, AttributeError):

65 return False

66

67 def is_complete(self, skill):

68 me = self.me

69 assert skill.is_card(characters.nitori.Craftsman)

70 if set(skill.associated_cards) != set(me.cards) | set(me.showncards):

71 return (False, '请选择所有的手牌（包括明牌）！')

72

73 return (True, '我TMD有老婆了！')

74

75 def is_action_valid(self, sk, tl):

76 assert sk.is_card(characters.nitori.Craftsman)

77 rst, reason = self.is_complete(sk)

78 if not rst:

79 return (rst, reason)

80 else:

81 return sk.treat_as.ui_meta.is_action_valid([sk], tl)

82

83 def effect_string(self, act):

84 # for LaunchCard.effect_string

85 source = act.source

86 s = '|G【%s】|r发动了|G匠心|r。' % (

87 source.ui_meta.name,

88 )

89 return s

90

91 def sound_effect(self, act):

92 if isinstance(act, actions.LaunchCard): 92 ↛ 98 line 92 didn't jump to line 98, because the condition on line 92 was never false

93 if act.card.is_card(AttackCard): 93 ↛ 96 line 93 didn't jump to line 96, because the condition on line 93 was never false

94 l = ['1', '2']

95 else:

96 l = ['_graze']

97

98 elif isinstance(act, actions.AskForCard):

99 atk = act.cond([self.build_handcard(AttackCard, act.target)])

100 graze = act.cond([self.build_handcard(GrazeCard, act.target)])

101 if atk and not graze:

102 l = ['1', '2']

103 else:

104 l = ['_graze']

105 else:

106 l = []

107

108 return l and 'thb-cv-nitori_craftsman%s' % random.choice(l)

109

110

111@ui_meta(characters.nitori.Nitori)

112 class Nitori:

113 # Character

114 name = '河城荷取'

115 title = '水中的工程师'

116 illustrator = '和茶'

117 cv = '简翎'

118

119 port_image = 'thb-portrait-nitori'

120 figure_image = 'thb-figure-nitori'

121 miss_sound_effect = ''

122

123 notes = '|RKOF不平衡角色|r'