Hide keyboard shortcuts

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 

3 

4# -- stdlib -- 

5# -- third party -- 

6# -- own -- 

7from thb.actions import ActionLimitExceeded, DrawCards, LaunchCard, PlayerTurn, Reforge, UserAction 

8from thb.actions import random_choose_card, ttags 

9from thb.cards.base import PhysicalCard, Skill, TreatAs, t_OtherOne 

10from thb.cards.definition import AttackCard 

11from thb.characters.base import Character, register_character_to 

12from thb.inputlets import ChoosePeerCardInputlet 

13from thb.mode import THBEventHandler 

14 

15 

16# -- code -- 

17class DismantleAction(UserAction): 

18 def apply_action(self): 

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

20 ttags(src)['dismantle'] = True 

21 

22 g = self.game 

23 c = g.user_input([src], ChoosePeerCardInputlet(self, tgt, ('equips', ))) 

24 c = c or random_choose_card(g, [tgt.equips]) 

25 if not c: return False 

26 

27 g.process_action(Reforge(src, tgt, c)) 

28 g.process_action(DrawCards(tgt, 1)) 

29 

30 return True 

31 

32 def is_valid(self): 

33 return not ttags(self.source)['dismantle'] and bool(self.target.equips) 

34 

35 

36class Dismantle(Skill): 

37 associated_action = DismantleAction 

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

39 target = t_OtherOne() 

40 

41 def check(self): 

42 return not self.associated_cards 

43 

44 

45class Craftsman(TreatAs, Skill): 

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

47 

48 @property 

49 def treat_as(self): 

50 params = getattr(self, 'action_params', {}) 

51 return PhysicalCard.classes.get(params.get('treat_as'), AttackCard) 

52 

53 def check(self): 

54 cl = self.associated_cards 

55 p = self.character 

56 

57 if 'basic' not in self.treat_as.category: 

58 return False 

59 

60 if not cl or set(cl) != (set(p.cards) | set(p.showncards)): 

61 return False 

62 

63 return True 

64 

65 @classmethod 

66 def list_treat_as(cls): 

67 return [c() for c in PhysicalCard.classes.values() if 'basic' in c.category] 

68 

69 

70class CraftsmanHandler(THBEventHandler): 

71 interested = ['action_after', 'action_shootdown'] 

72 

73 def handle(self, evt_type, act): 

74 if evt_type == 'action_after' and isinstance(act, LaunchCard): 

75 c = act.card 

76 if c.is_card(Craftsman): 

77 src = act.source 

78 ttags(src)['craftsman'] = True 

79 

80 elif evt_type == 'action_shootdown': 

81 if not isinstance(act, LaunchCard): return act 

82 c = act.card 

83 if not c.is_card(Craftsman): return act 

84 g = self.game 

85 try: 

86 current = PlayerTurn.get_current(g).target 

87 except IndexError: 

88 return act 

89 

90 if ttags(act.source)['craftsman'] and current is act.source: 

91 raise ActionLimitExceeded 

92 

93 return act 

94 

95 

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

97class Nitori(Character): 

98 skills = [Dismantle, Craftsman] 

99 eventhandlers = [CraftsmanHandler] 

100 maxlife = 3