Coverage for thb/cards/definition.py : 100%
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 typing import Any, List, Sequence, TYPE_CHECKING, Tuple, Type
7# -- third party --
8# -- own --
9from thb.cards.base import Card, PhysicalCard, Skill, t_All, t_AllInclusive, t_None, t_One
10from thb.cards.base import t_OtherLessEqThanN, t_OtherOne, t_Self
12# -- typing --
13if TYPE_CHECKING:
14 from thb.characters.base import Character # noqa: F401
17# -- code --
18def physical_card(cls: Type[PhysicalCard]):
19 assert issubclass(cls, PhysicalCard)
20 for a in ('associated_action', 'target', 'category'):
21 assert hasattr(cls, a), (cls, a)
22 PhysicalCard.classes[cls.__name__] = cls
23 return cls
26# ==================================================
27from thb.cards import basic
30class BasicCard(PhysicalCard):
31 pass
34@physical_card
35class AttackCard(BasicCard):
36 associated_action = basic.Attack
37 target = t_OtherOne()
38 category = ['basic']
39 distance = 1
42@physical_card
43class GrazeCard(BasicCard):
44 associated_action = None
45 target = t_None()
46 category = ['basic']
49@physical_card
50class HealCard(BasicCard):
51 associated_action = basic.Heal
52 target = t_Self()
53 category = ['basic']
56@physical_card
57class WineCard(BasicCard):
58 associated_action = basic.Wine
59 target = t_Self()
60 category = ['basic']
63@physical_card
64class ExinwanCard(BasicCard):
65 associated_action = basic.Exinwan
66 target = t_Self()
67 category = ['basic']
70# --------------------------------------------------
71from thb.cards import spellcard
74class SpellcardCard(PhysicalCard):
75 pass
78@physical_card
79class DemolitionCard(SpellcardCard):
80 associated_action = spellcard.Demolition
81 target = t_OtherOne()
82 category = ['spellcard', 'instant_spellcard']
85@physical_card
86class RejectCard(SpellcardCard):
87 associated_action = None
88 target = t_None()
89 category = ['spellcard', 'instant_spellcard']
92@physical_card
93class SealingArrayCard(SpellcardCard):
94 associated_action = spellcard.DelayedLaunchCard
95 target = t_OtherOne()
96 category = ['spellcard', 'delayed_spellcard']
97 delayed_action = spellcard.SealingArray
98 no_drop = True
101@physical_card
102class FrozenFrogCard(SpellcardCard):
103 associated_action = spellcard.DelayedLaunchCard
104 target = t_OtherOne()
105 category = ['spellcard', 'delayed_spellcard']
106 distance = 1
107 delayed_action = spellcard.FrozenFrog
108 no_drop = True
111@physical_card
112class NazrinRodCard(SpellcardCard):
113 associated_action = spellcard.NazrinRod
114 target = t_Self()
115 category = ['spellcard', 'instant_spellcard']
118@physical_card
119class SinsackCard(SpellcardCard):
120 associated_action = spellcard.DelayedLaunchCard
121 target = t_Self()
122 category = ['spellcard', 'delayed_spellcard']
123 delayed_action = spellcard.Sinsack
124 no_drop = True
127@physical_card
128class YukariDimensionCard(SpellcardCard):
129 associated_action = spellcard.YukariDimension
130 target = t_OtherOne()
131 category = ['spellcard', 'instant_spellcard']
132 distance = 1
135@physical_card
136class DuelCard(SpellcardCard):
137 associated_action = spellcard.Duel
138 target = t_OtherOne()
139 category = ['spellcard', 'instant_spellcard']
142@physical_card
143class MapCannonCard(SpellcardCard):
144 associated_action = spellcard.MapCannon
145 target = t_All()
146 category = ['group_effect', 'spellcard', 'instant_spellcard']
149@physical_card
150class DemonParadeCard(SpellcardCard):
151 associated_action = spellcard.DemonParade
152 target = t_All()
153 category = ['group_effect', 'spellcard', 'instant_spellcard']
156@physical_card
157class FeastCard(SpellcardCard):
158 associated_action = spellcard.Feast
159 target = t_AllInclusive()
160 category = ['group_effect', 'spellcard', 'instant_spellcard']
163@physical_card
164class HarvestCard(SpellcardCard):
165 associated_action = spellcard.Harvest
166 target = t_AllInclusive()
167 category = ['group_effect', 'spellcard', 'instant_spellcard']
170@physical_card
171class DollControlCard(SpellcardCard):
172 associated_action = spellcard.DollControl
174 def t_DollControl(self: Any, src: Character, tl: Sequence[Character]) -> Tuple[List[Character], bool]:
175 if not tl: return ([], False)
176 tl = [ch for ch in tl if not ch.dead]
177 while tl and src is tl[0]:
178 del tl[0]
179 return (tl[:2], len(tl) >= 2)
181 target = t_DollControl
182 category = ['spellcard', 'instant_spellcard']
183 del t_DollControl
186@physical_card
187class DonationBoxCard(SpellcardCard):
188 associated_action = spellcard.DonationBox
189 target = t_OtherLessEqThanN(2)
190 category = ['spellcard', 'instant_spellcard']
193# --------------------------------------------------
194from thb.cards import equipment
197class EquipmentCard(PhysicalCard):
198 equipment_skill: Type[Skill]
199 equipment_category: str
202@physical_card
203class MomijiShieldCard(EquipmentCard):
204 associated_action = equipment.WearEquipmentAction
205 target = t_Self()
206 category = ['equipment', 'shield']
207 equipment_skill = equipment.MomijiShieldSkill
208 equipment_category = 'shield'
211@physical_card
212class OpticalCloakCard(EquipmentCard):
213 associated_action = equipment.WearEquipmentAction
214 target = t_Self()
215 category = ['equipment', 'shield']
216 equipment_skill = equipment.OpticalCloakSkill
217 equipment_category = 'shield'
220@physical_card
221class GreenUFOCard(EquipmentCard):
222 associated_action = equipment.WearEquipmentAction
223 target = t_Self()
224 category = ['equipment', 'greenufo']
225 equipment_skill = equipment.GreenUFOSkill
226 equipment_category = 'greenufo'
229@physical_card
230class RedUFOCard(EquipmentCard):
231 associated_action = equipment.WearEquipmentAction
232 target = t_Self()
233 category = ['equipment', 'redufo']
234 equipment_skill = equipment.RedUFOSkill
235 equipment_category = 'redufo'
238@physical_card
239class HakuroukenCard(EquipmentCard):
240 associated_action = equipment.WearEquipmentAction
241 target = t_Self()
242 category = ['equipment', 'weapon']
243 equipment_skill = equipment.HakuroukenSkill
244 equipment_category = 'weapon'
247@physical_card
248class ElementalReactorCard(EquipmentCard):
249 associated_action = equipment.WearEquipmentAction
250 target = t_Self()
251 category = ['equipment', 'weapon']
252 equipment_skill = equipment.ElementalReactorSkill
253 equipment_category = 'weapon'
256@physical_card
257class UmbrellaCard(EquipmentCard):
258 associated_action = equipment.WearEquipmentAction
259 target = t_Self()
260 category = ['equipment', 'shield']
261 equipment_skill = equipment.UmbrellaSkill
262 equipment_category = 'shield'
265@physical_card
266class RoukankenCard(EquipmentCard):
267 associated_action = equipment.WearEquipmentAction
268 target = t_Self()
269 category = ['equipment', 'weapon']
270 equipment_skill = equipment.RoukankenSkill
271 equipment_category = 'weapon'
274@physical_card
275class GungnirCard(EquipmentCard):
276 associated_action = equipment.WearEquipmentAction
277 target = t_Self()
278 category = ['equipment', 'weapon']
279 equipment_skill = equipment.GungnirSkill
280 equipment_category = 'weapon'
283@physical_card
284class LaevateinCard(EquipmentCard):
285 associated_action = equipment.WearEquipmentAction
286 target = t_Self()
287 category = ['equipment', 'weapon']
288 equipment_skill = equipment.LaevateinSkill
289 equipment_category = 'weapon'
292@physical_card
293class NenshaPhoneCard(EquipmentCard):
294 associated_action = equipment.WearEquipmentAction
295 target = t_Self()
296 category = ['equipment', 'weapon']
297 equipment_skill = equipment.NenshaPhoneSkill
298 equipment_category = 'weapon'
301@physical_card
302class RepentanceStickCard(EquipmentCard):
303 associated_action = equipment.WearEquipmentAction
304 target = t_Self()
305 category = ['equipment', 'weapon']
306 equipment_skill = equipment.RepentanceStickSkill
307 equipment_category = 'weapon'
310@physical_card
311class SinsackHatCard(EquipmentCard):
312 associated_action = equipment.WearEquipmentAction
313 target = t_One()
314 category = ['equipment', 'shield']
315 equipment_skill = equipment.SinsackHat
316 equipment_category = 'shield'
317 distance = 2
320@physical_card
321class IbukiGourdCard(EquipmentCard):
322 associated_action = equipment.WearEquipmentAction
323 target = t_Self()
324 category = ['equipment', 'redufo']
325 equipment_skill = equipment.IbukiGourdSkill
326 equipment_category = 'redufo'
329@physical_card
330class HouraiJewelCard(EquipmentCard):
331 associated_action = equipment.WearEquipmentAction
332 target = t_Self()
333 category = ['equipment', 'weapon']
334 equipment_skill = equipment.HouraiJewelSkill
335 equipment_category = 'weapon'
338@physical_card
339class MaidenCostumeCard(EquipmentCard):
340 associated_action = equipment.WearEquipmentAction
341 target = t_Self()
342 category = ['equipment', 'shield']
343 equipment_skill = equipment.MaidenCostume
344 equipment_category = 'shield'
347@physical_card
348class AyaRoundfanCard(EquipmentCard):
349 associated_action = equipment.WearEquipmentAction
350 target = t_Self()
351 category = ['equipment', 'weapon']
352 equipment_skill = equipment.AyaRoundfanSkill
353 equipment_category = 'weapon'
356@physical_card
357class ScarletRhapsodyCard(EquipmentCard):
358 associated_action = equipment.WearEquipmentAction
359 target = t_Self()
360 category = ['equipment', 'weapon']
361 equipment_skill = equipment.ScarletRhapsodySkill
362 equipment_category = 'weapon'
365@physical_card
366class DeathSickleCard(EquipmentCard):
367 associated_action = equipment.WearEquipmentAction
368 target = t_Self()
369 category = ['equipment', 'weapon']
370 equipment_skill = equipment.DeathSickleSkill
371 equipment_category = 'weapon'
374@physical_card
375class KeystoneCard(EquipmentCard):
376 associated_action = equipment.WearEquipmentAction
377 target = t_Self()
378 category = ['equipment', 'greenufo']
379 equipment_skill = equipment.KeystoneSkill
380 equipment_category = 'greenufo'
383@physical_card
384class WitchBroomCard(EquipmentCard):
385 associated_action = equipment.WearEquipmentAction
386 target = t_Self()
387 category = ['equipment', 'redufo']
388 equipment_skill = equipment.WitchBroomSkill
389 equipment_category = 'redufo'
392@physical_card
393class YinYangOrbCard(EquipmentCard):
394 associated_action = equipment.WearEquipmentAction
395 target = t_Self()
396 category = ['equipment', 'accessories']
397 equipment_skill = equipment.YinYangOrbSkill
398 equipment_category = 'accessories'
401@physical_card
402class SuwakoHatCard(EquipmentCard):
403 associated_action = equipment.WearEquipmentAction
404 target = t_Self()
405 category = ['equipment', 'accessories']
406 equipment_skill = equipment.SuwakoHatSkill
407 equipment_category = 'accessories'
410@physical_card
411class YoumuPhantomCard(EquipmentCard):
412 associated_action = equipment.WearEquipmentAction
413 target = t_Self()
414 category = ['equipment', 'accessories']
415 equipment_skill = equipment.YoumuPhantomSkill
416 equipment_category = 'accessories'
419@physical_card
420class IceWingCard(EquipmentCard):
421 associated_action = equipment.WearEquipmentAction
422 target = t_Self()
423 category = ['equipment', 'redufo']
424 equipment_skill = equipment.IceWingSkill
425 equipment_category = 'redufo'
428@physical_card
429class GrimoireCard(EquipmentCard):
430 associated_action = equipment.WearEquipmentAction
431 target = t_Self()
432 category = ['equipment', 'weapon']
433 equipment_skill = equipment.GrimoireSkill
434 equipment_category = 'weapon'
437# ==================================================
438SPADE, HEART, CLUB, DIAMOND = Card.SPADE, Card.HEART, Card.CLUB, Card.DIAMOND
439A, J, Q, K = 1, 11, 12, 13
441card_definition = [
442 # ======= Spade =======
443 (SinsackCard, SPADE, A),
444 (DeathSickleCard, SPADE, 2),
445 (RepentanceStickCard, SPADE, 3),
446 (RoukankenCard, SPADE, 4),
447 (HakuroukenCard, SPADE, 5),
448 (GungnirCard, SPADE, 6),
449 (DemonParadeCard, SPADE, 7),
450 (DemonParadeCard, SPADE, 8),
451 (SealingArrayCard, SPADE, 9),
452 (SealingArrayCard, SPADE, 10),
453 (AttackCard, SPADE, J),
454 (AttackCard, SPADE, Q),
455 (KeystoneCard, SPADE, K),
457 (DuelCard, SPADE, A),
458 (RejectCard, SPADE, 2),
459 (AttackCard, SPADE, 3),
460 (AttackCard, SPADE, 4),
461 (YukariDimensionCard, SPADE, 5),
462 (YukariDimensionCard, SPADE, 6),
463 (AttackCard, SPADE, 7),
464 (AttackCard, SPADE, 8),
465 (WineCard, SPADE, 9),
466 (AttackCard, SPADE, 10),
467 (AttackCard, SPADE, J),
468 (RejectCard, SPADE, Q),
469 (WitchBroomCard, SPADE, K),
471 (DonationBoxCard, SPADE, A),
472 (OpticalCloakCard, SPADE, 2),
473 (DemolitionCard, SPADE, 3),
474 (DemolitionCard, SPADE, 4),
475 (AttackCard, SPADE, 8),
476 (IceWingCard, SPADE, 9),
477 (AttackCard, SPADE, 10),
478 (DonationBoxCard, SPADE, J),
479 (AttackCard, SPADE, Q),
480 (YinYangOrbCard, SPADE, K),
482 # ======= Heart =======
483 (FeastCard, HEART, A),
484 (SinsackHatCard, HEART, 2),
485 (HarvestCard, HEART, 3),
486 (HarvestCard, HEART, 4),
487 (AyaRoundfanCard, HEART, 5),
488 (AttackCard, HEART, 6),
489 (NazrinRodCard, HEART, 7),
490 (NazrinRodCard, HEART, 8),
491 (NazrinRodCard, HEART, 9),
492 (SealingArrayCard, HEART, 10),
493 (AttackCard, HEART, J),
494 (DemolitionCard, HEART, Q),
495 (GreenUFOCard, HEART, K),
497 (MapCannonCard, HEART, A),
498 (RejectCard, HEART, 2),
499 (HealCard, HEART, 3),
500 (HealCard, HEART, 4),
501 (HealCard, HEART, 5),
502 (HealCard, HEART, 6),
503 (HealCard, HEART, 7),
504 (HealCard, HEART, 8),
505 (HealCard, HEART, 9),
506 (AttackCard, HEART, 10),
507 (AttackCard, HEART, J),
508 (AttackCard, HEART, Q),
509 (RejectCard, HEART, K),
511 (SinsackCard, HEART, A),
512 (GrazeCard, HEART, 2),
513 (GrazeCard, HEART, 3),
514 (GrazeCard, HEART, 4),
515 (HealCard, HEART, 8),
516 (GrazeCard, HEART, 9),
517 (GrazeCard, HEART, 10),
518 (GrazeCard, HEART, J),
519 (GrazeCard, HEART, Q),
520 (YinYangOrbCard, HEART, K),
522 # ======= Club =======
523 (SuwakoHatCard, CLUB, A),
524 (MomijiShieldCard, CLUB, 2),
525 (AttackCard, CLUB, 3),
526 (DemolitionCard, CLUB, 4),
527 (AttackCard, CLUB, 5),
528 (AttackCard, CLUB, 6),
529 (DemonParadeCard, CLUB, 7),
530 (AttackCard, CLUB, 8),
531 (WineCard, CLUB, 9),
532 (AttackCard, CLUB, 10),
533 (AttackCard, CLUB, J),
534 (ExinwanCard, CLUB, Q),
535 (GreenUFOCard, CLUB, K),
537 (DuelCard, CLUB, A),
538 (AttackCard, CLUB, 2),
539 (AttackCard, CLUB, 3),
540 (AttackCard, CLUB, 4),
541 (FrozenFrogCard, CLUB, 5),
542 (FrozenFrogCard, CLUB, 6),
543 (AttackCard, CLUB, 7),
544 (DemolitionCard, CLUB, 8),
545 (WineCard, CLUB, 9),
546 (AttackCard, CLUB, 10),
547 (AttackCard, CLUB, J),
548 (RejectCard, CLUB, Q),
549 (RedUFOCard, CLUB, K),
551 (YoumuPhantomCard, CLUB, A),
552 (UmbrellaCard, CLUB, 2),
553 (AttackCard, CLUB, 3),
554 (AttackCard, CLUB, 4),
555 (AttackCard, CLUB, 8),
556 (IbukiGourdCard, CLUB, 9),
557 (AttackCard, CLUB, 10),
558 (AttackCard, CLUB, J),
559 (MaidenCostumeCard, CLUB, Q),
560 (DollControlCard, CLUB, K),
562 # ======= Diamond =======
563 (ElementalReactorCard, DIAMOND, A),
564 (GrazeCard, DIAMOND, 2),
565 (GrazeCard, DIAMOND, 3),
566 (GrazeCard, DIAMOND, 4),
567 (ScarletRhapsodyCard, DIAMOND, 5),
568 (GrazeCard, DIAMOND, 6),
569 (GrazeCard, DIAMOND, 7),
570 (GrazeCard, DIAMOND, 8),
571 (GrazeCard, DIAMOND, 9),
572 (NenshaPhoneCard, DIAMOND, 10),
573 (LaevateinCard, DIAMOND, J),
574 (GrimoireCard, DIAMOND, Q),
575 (GreenUFOCard, DIAMOND, K),
577 (DuelCard, DIAMOND, A),
578 (GrazeCard, DIAMOND, 2),
579 (HealCard, DIAMOND, 3),
580 (HealCard, DIAMOND, 4),
581 (YukariDimensionCard, DIAMOND, 5),
582 (YukariDimensionCard, DIAMOND, 6),
583 (AttackCard, DIAMOND, 7),
584 (AttackCard, DIAMOND, 8),
585 (WineCard, DIAMOND, 9),
586 (AttackCard, DIAMOND, 10),
587 (ExinwanCard, DIAMOND, J),
588 (RejectCard, DIAMOND, Q),
589 (RedUFOCard, DIAMOND, K),
591 (HouraiJewelCard, DIAMOND, A),
592 (GrazeCard, DIAMOND, 2),
593 (AttackCard, DIAMOND, 3),
594 (AttackCard, DIAMOND, 4),
595 (GrazeCard, DIAMOND, 8),
596 (WineCard, DIAMOND, 9),
597 (GrazeCard, DIAMOND, 10),
598 (GrazeCard, DIAMOND, J),
599 (HealCard, DIAMOND, Q),
600 (DollControlCard, DIAMOND, K),
601]
603# ANCHOR(card)
604card_definition = [
605] * 1000 or card_definition
607kof_card_definition = [
608 # ======= Spade =======
609 (SinsackCard, SPADE, A),
610 (DeathSickleCard, SPADE, 2),
611 (RepentanceStickCard, SPADE, 3),
612 (AttackCard, SPADE, 4),
613 (HakuroukenCard, SPADE, 5),
614 (GungnirCard, SPADE, 6),
615 (DemonParadeCard, SPADE, 7),
616 (AttackCard, SPADE, 8),
617 (WineCard, SPADE, 9),
618 (SealingArrayCard, SPADE, 10),
619 (AttackCard, SPADE, J),
620 (AttackCard, SPADE, Q),
621 (RejectCard, SPADE, K),
623 (DuelCard, SPADE, A),
624 (OpticalCloakCard, SPADE, 2),
625 (DemolitionCard, SPADE, 3),
626 (DemolitionCard, SPADE, 4),
627 (YukariDimensionCard, SPADE, 5),
628 (YukariDimensionCard, SPADE, 6),
629 (AttackCard, SPADE, 7),
630 (AttackCard, SPADE, 8),
631 (AttackCard, SPADE, 9),
632 (AttackCard, SPADE, 10),
633 (AttackCard, SPADE, J),
634 (AttackCard, SPADE, Q),
635 (RejectCard, SPADE, K),
637 # ======= Heart =======
638 (FeastCard, HEART, A),
639 (GrazeCard, HEART, 2),
640 (HealCard, HEART, 3),
641 (HarvestCard, HEART, 4),
642 (AyaRoundfanCard, HEART, 5),
643 (AttackCard, HEART, 6),
644 (NazrinRodCard, HEART, 7),
645 (NazrinRodCard, HEART, 8),
646 (NazrinRodCard, HEART, 9),
647 (SealingArrayCard, HEART, 10),
648 (AttackCard, HEART, J),
649 (DemolitionCard, HEART, Q),
650 (RejectCard, HEART, K),
652 (MapCannonCard, HEART, A),
653 (AttackCard, HEART, 2),
654 (GrazeCard, HEART, 3),
655 (GrazeCard, HEART, 4),
656 (HealCard, HEART, 5),
657 (HealCard, HEART, 6),
658 (HealCard, HEART, 7),
659 (HealCard, HEART, 8),
660 (GrazeCard, HEART, 9),
661 (AttackCard, HEART, 10),
662 (AttackCard, HEART, J),
663 (GrazeCard, HEART, Q),
664 (DuelCard, HEART, K),
666 # ======= Club =======
667 (YoumuPhantomCard, CLUB, A),
668 (MomijiShieldCard, CLUB, 2),
669 (AttackCard, CLUB, 3),
670 (DemolitionCard, CLUB, 4),
671 (FrozenFrogCard, CLUB, 5),
672 (AttackCard, CLUB, 6),
673 (AttackCard, CLUB, 7),
674 (DemolitionCard, CLUB, 8),
675 (WineCard, CLUB, 9),
676 (AttackCard, CLUB, 10),
677 (AttackCard, CLUB, J),
678 (ExinwanCard, CLUB, Q),
679 (DollControlCard, CLUB, K),
681 (SuwakoHatCard, CLUB, A),
682 (UmbrellaCard, CLUB, 2),
683 (AttackCard, CLUB, 3),
684 (AttackCard, CLUB, 4),
685 (FrozenFrogCard, CLUB, 5),
686 (AttackCard, CLUB, 6),
687 (AttackCard, CLUB, 7),
688 (AttackCard, CLUB, 8),
689 (IbukiGourdCard, CLUB, 9),
690 (AttackCard, CLUB, 10),
691 (AttackCard, CLUB, J),
692 (RejectCard, CLUB, Q),
693 (DuelCard, CLUB, K),
695 # ======= Diamond =======
696 (DuelCard, DIAMOND, A),
697 (GrazeCard, DIAMOND, 2),
698 (HealCard, DIAMOND, 3),
699 (AttackCard, DIAMOND, 4),
700 (LaevateinCard, DIAMOND, 5),
701 (YukariDimensionCard, DIAMOND, 6),
702 (AttackCard, DIAMOND, 7),
703 (GrazeCard, DIAMOND, 8),
704 (AttackCard, DIAMOND, 9),
705 (NenshaPhoneCard, DIAMOND, 10),
706 (GrazeCard, DIAMOND, J),
707 (HealCard, DIAMOND, Q),
708 (GrazeCard, DIAMOND, K),
710 (ElementalReactorCard, DIAMOND, A),
711 (GrazeCard, DIAMOND, 2),
712 (GrazeCard, DIAMOND, 3),
713 (HealCard, DIAMOND, 4),
714 (YukariDimensionCard, DIAMOND, 5),
715 (GrazeCard, DIAMOND, 6),
716 (GrazeCard, DIAMOND, 7),
717 (GrazeCard, DIAMOND, 8),
718 (GrazeCard, DIAMOND, 9),
719 (AttackCard, DIAMOND, 10),
720 (ExinwanCard, DIAMOND, J),
721 (AttackCard, DIAMOND, Q),
722 (GrazeCard, DIAMOND, K),
723]
725del A, J, Q, K