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 collections import defaultdict 

6from typing import Any, ClassVar, Dict, Iterable, List, Set, TYPE_CHECKING, Type 

7 

8# -- third party -- 

9# -- own -- 

10from game.base import GameObject, Player 

11from thb.cards.base import CardList, Skill 

12from thb.mode import THBEventHandler 

13from utils.misc import partition 

14 

15# -- typing -- 

16if TYPE_CHECKING: 

17 from thb.meta.typing import CharacterMeta # noqa: F401 

18 

19 

20# -- code -- 

21# common, id8, faith, kof, 3v3, testing 

22# -id8, ... 

23characters_by_category: Dict[str, Set[Type[Character]]] = defaultdict(set) 

24 

25 

26class Character(GameObject): 

27 classes: ClassVar[Dict[str, Type[Character]]] = {} 

28 

29 # ----- Class Variables ----- 

30 ui_meta: ClassVar[CharacterMeta] 

31 eventhandlers: ClassVar[List[Type[THBEventHandler]]] = () 

32 categories: ClassVar[Iterable[str]] = () 

33 boss_skills: ClassVar[List[Type[Skill]]] = () 

34 

35 skills: List[Type[Skill]] = () 

36 maxlife: int = 0 

37 

38 # ----- Instance Variables ----- 

39 dead: bool 

40 life: int 

41 disabled_skills: Dict[str, Set[Type[Skill]]] 

42 tags: Dict[str, Any] 

43 cards: CardList 

44 showncards: CardList 

45 equips: CardList 

46 fatetell: CardList 

47 special: CardList 

48 showncardlists: List[CardList] 

49 player: Player 

50 

51 def __init__(self, player: Player): 

52 self.player = player 

53 self.disabled_skills = defaultdict(set) 

54 

55 cls = self.__class__ 

56 

57 self.skills = list(cls.skills) 

58 self.maxlife = cls.maxlife 

59 self.life = cls.maxlife 

60 self.dead = False 

61 

62 self.cards = CardList(self, 'cards') # Cards in hand 

63 self.showncards = CardList(self, 'showncards') # Cards which are shown to the others, treated as 'Cards in hand' 

64 self.equips = CardList(self, 'equips') # Equipments 

65 self.fatetell = CardList(self, 'fatetell') # Cards in the Fatetell Zone 

66 self.special = CardList(self, 'special') # used on special purpose 

67 self.showncardlists = [self.showncards, self.fatetell] 

68 self.tags = defaultdict(int) 

69 

70 def get_player(self) -> Player: 

71 return self.player 

72 

73 def get_skills(self, skill: Type['Skill']): 

74 return [s for s in self.skills if issubclass(s, skill)] 

75 

76 def has_skill(self, skill: Type['Skill']): 

77 if self.dead: 

78 return False 

79 

80 if any(issubclass(skill, s) for l in self.disabled_skills.values() for s in l): 

81 return False 

82 

83 return self.get_skills(skill) 

84 

85 def disable_skill(self, skill: Type['Skill'], reason: str): 

86 self.disabled_skills[reason].add(skill) 

87 

88 def reenable_skill(self, reason: str): 

89 self.disabled_skills.pop(reason, '') 

90 

91 def reveal(self, obj: Any) -> None: 

92 self.player.reveal(obj) 

93 

94 def __repr__(self) -> str: 

95 return '<Char: {}>'.format(self.__class__.__name__) 

96 

97 

98def register_character_to(*cats): 

99 sets = [characters_by_category[c] for c in set(cats)] 

100 

101 def register(cls: Type[Character]): 

102 Character.classes[cls.__name__] = cls 

103 

104 for s in sets: 

105 s.add(cls) 

106 

107 cls.categories = cats 

108 return cls 

109 

110 return register 

111 

112 

113def get_characters(*categories): 

114 cats: Set[str] = set(categories) 

115 chars: Set[Type[Character]] = set() 

116 pos, neg = partition(lambda c: not c.startswith('-'), cats) 

117 chars.update(*[characters_by_category[c] for c in pos]) 

118 chars.difference_update(*[characters_by_category['-' + c] for c in pos]) 

119 chars.difference_update(*[characters_by_category[c.strip('-')] for c in neg]) 

120 return list(sorted(chars, key=lambda i: i.__name__))