Coverage for thb/characters/base.py : 66%
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
4# -- stdlib --
5from collections import defaultdict
6from typing import Any, ClassVar, Dict, Iterable, List, Set, TYPE_CHECKING, Type
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
15# -- typing --
16if TYPE_CHECKING:
17 from thb.meta.typing import CharacterMeta # noqa: F401
20# -- code --
21# common, id8, faith, kof, 3v3, testing
22# -id8, ...
23characters_by_category: Dict[str, Set[Type[Character]]] = defaultdict(set)
26class Character(GameObject):
27 classes: ClassVar[Dict[str, Type[Character]]] = {}
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]]] = []
35 skills: List[Type[Skill]] = []
36 maxlife: int = 0
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 lists: List[CardList]
49 player: Player
51 def __init__(self, player: Player):
52 self.player = player
53 self.disabled_skills = defaultdict(set)
55 cls = self.__class__
57 self.skills = list(cls.skills)
58 self.maxlife = cls.maxlife
59 self.life = cls.maxlife
60 self.dead = False
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.lists = [
68 self.cards,
69 self.showncards,
70 self.equips,
71 self.fatetell,
72 self.special,
73 ]
74 self.tags = defaultdict(int)
76 self._: dict = {}
78 def get_player(self) -> Player:
79 return self.player
81 def get_skills(self, skill: Type['Skill']):
82 return [s for s in self.skills if issubclass(s, skill)]
84 def has_skill(self, skill: Type['Skill']):
85 if self.dead:
86 return False
88 if any(issubclass(skill, s) for l in self.disabled_skills.values() for s in l):
89 return False
91 return self.get_skills(skill)
93 def disable_skill(self, skill: Type['Skill'], reason: str):
94 self.disabled_skills[reason].add(skill)
96 def reenable_skill(self, reason: str):
97 self.disabled_skills.pop(reason, '')
99 def reveal(self, obj: Any) -> None:
100 self.player.reveal(obj)
102 def __repr__(self) -> str:
103 return '<Char: {}>'.format(self.__class__.__name__)
106def register_character_to(*cats):
107 sets = [characters_by_category[c] for c in set(cats)]
109 def register(cls: Type[Character]):
110 Character.classes[cls.__name__] = cls
112 for s in sets:
113 s.add(cls)
115 cls.categories = cats
116 return cls
118 return register
121def get_characters(*categories):
122 cats: Set[str] = set(categories)
123 chars: Set[Type[Character]] = set()
124 pos, neg = partition(lambda c: not c.startswith('-'), cats)
125 chars.update(*[characters_by_category[c] for c in pos])
126 chars.difference_update(*[characters_by_category['-' + c] for c in pos])
127 chars.difference_update(*[characters_by_category[c.strip('-')] for c in neg])
128 return list(sorted(chars, key=lambda i: i.__name__))