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

5from typing import Any 

6 

7# -- third party -- 

8# -- own -- 

9from thb.actions import DropCards, LaunchCard, detach_cards, migrate_cards 

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

11from thb.cards.classes import Demolition, DemolitionCard, TreatAs 

12from thb.characters.base import Character, register_character_to 

13from thb.inputlets import ChooseOptionInputlet 

14from thb.mode import THBEventHandler 

15from utils.misc import classmix 

16 

17 

18# -- code -- 

19class Envy(TreatAs, Skill): 

20 treat_as = DemolitionCard 

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

22 

23 def check(self): 

24 cards = self.associated_cards 

25 if len(cards) != 1: return False 

26 c = cards[0] 

27 if c.resides_in is None: return False 

28 if c.resides_in.type not in ('cards', 'showncards', 'equips'): return False 

29 if c.suit not in (Card.SPADE, Card.CLUB): return False 

30 return True 

31 

32 

33class EnvyRecycleAction(object): 

34 def apply_action(self: Any): 

35 detach_cards(self.cards) 

36 migrate_cards(self.cards, self.source.cards, unwrap=True) 

37 return True 

38 

39 

40class EnvyRecycle(DummyCard): 

41 distance = 1 

42 

43 

44class EnvyHandler(THBEventHandler): 

45 interested = ['action_before'] 

46 

47 def handle(self, evt_type, act): 

48 if evt_type != 'action_before': return act 

49 if not isinstance(act, DropCards): return act 

50 

51 g = self.game 

52 pact = g.action_stack[-1] 

53 if not isinstance(pact, Demolition): return act 

54 if not pact.source.has_skill(Envy): return act 

55 

56 src = pact.source 

57 tgt = pact.target 

58 self.card = card = pact.card 

59 

60 assert len(act.cards) == 1 

61 assert card is act.cards[0] 

62 

63 if card.resides_in is None: 

64 return act 

65 

66 if card.resides_in.type not in ('cards', 'showncards', 'equips'): 

67 return act 

68 

69 assert tgt is card.resides_in.owner 

70 

71 if src.dead: return act 

72 if card.suit != Card.DIAMOND: return act 

73 

74 dist = LaunchCard.calc_distance(g, src, EnvyRecycle()) 

75 if not dist[tgt] <= 0: return act 

76 

77 g.emit_event('ui_show_disputed', [card]) 

78 

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

80 return act 

81 

82 act.__class__ = classmix(EnvyRecycleAction, act.__class__) 

83 return act 

84 

85 

86@register_character_to('common') 

87class Parsee(Character): 

88 skills = [Envy] 

89 eventhandlers = [EnvyHandler] 

90 maxlife = 4