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

## 60 statements 25 run 35 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 from __future__ import annotations

3

4# -- stdlib --

5 from typing import Any

6

7# -- third party --

8# -- own --

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

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

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

12 from thb.characters.base import Character, register_character_to

13 from thb.inputlets import ChooseOptionInputlet

14 from thb.mode import THBEventHandler

15 from utils.misc import classmix

16

17

18# -- code --

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

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

40 class EnvyRecycle(DummyCard):

41 distance = 1

42

43

44 class 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')

87 class Parsee(Character):

88 skills = [Envy]

89 eventhandlers = [EnvyHandler]

90 maxlife = 4