def handle(self, evt_type, act): if evt_type == 'action_after' and isinstance(act, Damage): src = act.source if not src: return act if not src.has_skill(IbukiGourdSkill): return act g = Game.getgame() ttags(src)['ibukigourd_did_damage'] = True elif evt_type == 'action_apply' and isinstance(act, FinalizeStage): tgt = act.target if not tgt.has_skill(IbukiGourdSkill): return act g = Game.getgame() if ttags(tgt)['ibukigourd_did_damage']: return act g.process_action(basic.Wine(tgt, tgt)) elif evt_type == 'card_migration': from .definition import IbukiGourdCard act, cl, _from, to, _ = arg = act if not any(c.is_card(IbukiGourdCard) for c in cl): return arg if to.type != 'equips': return arg tgt = to.owner g = Game.getgame() g.process_action(basic.Wine(tgt, tgt)) return arg return act
def sound_effect(act): tgt = act.target if ttags(tgt)['__icewing_se']: return None ttags(tgt)['__icewing_se'] = True return 'thb-cv-card_icewing'
def handle(self, evt_type, act): if evt_type == 'action_after' and isinstance(act, Damage): src = act.source if not src: return act if not src.has_skill(DestructionImpulse): return act g = Game.getgame() ttags(src)['destruction_tag'] = True elif evt_type == 'action_after' and isinstance(act, PlayerTurn): tgt = act.target if not tgt.has_skill(DestructionImpulse): return act g = Game.getgame() if ttags(tgt)['destruction_tag']: return act dist = LaunchCard.calc_distance(tgt, DestructionImpulse(tgt)) dist.pop(tgt, '') for k in dist: dist[k] = max(dist[k], 0) nearest = min(dist.values()) candidates = [p for p, d in dist.items() if d == nearest] candidates = [p for p in g.players if p in candidates] # order matters if len(candidates) > 1: pl = user_choose_players(self, tgt, candidates) p = pl[0] if pl else candidates[0] else: p = candidates[0] g.process_action(DestructionImpulseAction(tgt, p)) return act
def clickable(game): me = game.me if not (my_turn() and (me.cards or me.showncards)): return False if ttags(me)['ran_eikof_tag']: return False if not ttags(me)['ran_eikof_card']: return False return True
def apply_action(self): tgt = self.target g = Game.getgame() g.process_action(DrawCards(tgt, 1)) ttags(tgt)['miracle_times'] += 1 if ttags(tgt)['miracle_times'] == 3: candidates = [p for p in g.players if not p.dead and p.life < p.maxlife] if candidates: beneficiery, = user_choose_players(self, tgt, candidates) or (None,) if beneficiery: g.process_action(MiracleHeal(tgt, beneficiery)) return True
def handle(self, evt_type, act): if evt_type == 'action_after' and isinstance(act, ActionStageLaunchCard): c = act.card if c.is_card(Craftsman): src = act.source ttags(src)['craftsman'] = True elif evt_type == 'action_shootdown': if not isinstance(act, ActionStageLaunchCard): return act c = act.card if not c.is_card(Craftsman): return act if ttags(act.source)['craftsman']: raise ActionLimitExceeded return act
def apply_action(self): src, lc = self.source, self.action assert isinstance(lc, (LaunchCard, LaunchFatetellCard)) lc.card_action.cancelled = True ttags(src)['mima_tianyi'] = True if isinstance(lc, LaunchCard): # HACK! RejectCard has no target, but not implemented this way. if lc.force_action and isinstance(lc.force_action, Reject): return True lst = lc.target_list[:] elif isinstance(lc, LaunchFatetellCard): lst = [lc.target] else: assert False, 'WTF?!' g = Game.getgame() for p in lst: g.process_action( LaunchCard(src, [p], TianyiAttack(src), bypass_check=True)) return True
def handle(self, evt_type, act): if evt_type == 'action_before' and hasattr(act, 'associated_card'): g = Game.getgame() lc = g.action_stack[-1] for lc in reversed(g.action_stack): if isinstance(lc, (LaunchCard, LaunchFatetellCard)) and lc.card_action is act: break else: return act me = g.current_player if not me or not me.has_skill(Tianyi): return act while True: if isinstance(act, SpellCardAction): break if isinstance(act, ForEach) and issubclass( act.action_cls, SpellCardAction): break # Another HACK return act if ttags(me)['mima_tianyi']: return act if not user_input([me], ChooseOptionInputlet(self, (False, True))): return act g.process_action(TianyiAction(me, lc)) return act
def clickable(game): me = game.me if ttags(me)['bakadesu']: return False return my_turn()
def is_valid(self): tgt = self.target g = Game.getgame() cl = self.associated_card.associated_cards n = len([p for p in g.players if not p.dead]) / 2 if not 0 < len(cl) <= n: return False return not ttags(tgt)['qiliao']
def handle(self, evt_type, act): if evt_type == 'action_before' and hasattr(act, 'associated_card'): g = Game.getgame() lc = g.action_stack[-1] for lc in reversed(g.action_stack): if isinstance(lc, (LaunchCard, LaunchFatetellCard)) and lc.card_action is act: break else: return act me = g.current_player if not me or not me.has_skill(Tianyi): return act while True: if isinstance(act, SpellCardAction): break if isinstance(act, ForEach) and issubclass(act.action_cls, SpellCardAction): break # Another HACK return act if ttags(me)['mima_tianyi']: return act if not user_input([me], ChooseOptionInputlet(self, (False, True))): return act g.process_action(TianyiAction(me, lc)) return act
def sound_effect(act): if not isinstance(act, actions.LaunchCard): return 'thb-cv-card_attack1' current = G().current_player if act.source is not current: return 'thb-cv-card_attack1' ttags(current)['__attack_graze_count'] += 1 return [ 'thb-cv-card_attack1', 'thb-cv-card_attack2', 'thb-cv-card_attack3', 'thb-cv-card_attack4', ][ttags(current)['__attack_graze_count'] % 4 - 1]
def is_action_valid(g, cl, tl): cards = cl[0].associated_cards expected = ttags(g.me)['miracle_times'] + 1 if len(cards) != expected: return (False, u'奇迹:请选择%d张牌!' % expected) return (True, u'奇迹是存在的!')
def clickable(g): if not my_turn(): return False if ttags(g.me)['qiliao']: return False return True
def clickable(game): me = game.me if ttags(me)['find']: return False if my_turn() and (me.cards or me.showncards or me.equips): return True return False
def handle(self, evt_type, act): if evt_type == 'action_apply' and isinstance(act, ActionStageLaunchCard): if not act.card.is_card(VirtualCard): src = act.source if not src.has_skill(ExtremeIntelligenceKOF): return act c = act.card if 'instant_spellcard' not in c.category: return act ttags(src)['ran_eikof_card'] = c.__class__ elif act.card.is_card(ExtremeIntelligenceKOF): src = act.source ttags(src)['ran_eikof_tag'] = True elif evt_type == 'action_shootdown' and isinstance(act, ActionStageLaunchCard) and act.card.is_card(ExtremeIntelligenceKOF): src = act.source tt = ttags(src) if tt['ran_eikof_tag'] or not tt['ran_eikof_card']: raise ActionLimitExceeded return act
def clickable(g): try: me = g.me if not me.cards and not me.showncards: return False if ttags(me)['craftsman'] and g.current_player is me: return False return True except (IndexError, AttributeError): return False
def apply_action(self): src, tgt = self.source, self.target ttags(src)['dismantle'] = True g = Game.getgame() c = user_input([src], ChoosePeerCardInputlet(self, tgt, ('equips', ))) c = c or random_choose_card([tgt.equips]) if not c: return False g.process_action(Reforge(src, tgt, c)) g.process_action(DrawCards(tgt, 1)) return True
def handle(self, evt_type, act): if evt_type == 'action_before' and isinstance(act, FinalizeStage): tgt = act.target if not tgt.has_skill(KanakoFaithKOF): return act g = Game.getgame() op = g.get_opponent(tgt) if tgt.life > op.life or ttags(tgt)['kanako_faith_kof']: n = tgt.life - (len(tgt.cards) + len(tgt.showncards)) if n > 0: g.process_action(KanakoFaithKOFAction(tgt, n)) elif evt_type == 'action_apply' and isinstance(act, Damage): src, tgt = act.source, act.target g = Game.getgame() if src and src.has_skill(KanakoFaithKOF) and tgt is g.get_opponent(src): ttags(src)['kanako_faith_kof'] = True return act
def apply_action(self): src, tgt = self.source, self.target ttags(src)['bakadesu'] = True cl = user_choose_cards(self, tgt, ('cards', 'showncards')) g = Game.getgame() if cl: g.process_action(LaunchCard(tgt, [src], cl[0])) else: c = user_input([src], ChoosePeerCardInputlet(self, tgt, ('cards', 'showncards', 'equips'))) c = c or random_choose_card([tgt.cards, tgt.showncards, tgt.equips]) c and g.process_action(CirnoDropCards(src, tgt, [c])) return True
def handle(self, evt_type, act): if evt_type == 'action_before' and isinstance(act, FinalizeStage): tgt = act.target if not tgt.has_skill(KanakoFaithKOF): return act g = Game.getgame() op = g.get_opponent(tgt) if tgt.life > op.life or ttags(tgt)['kanako_faith_kof']: n = tgt.life - (len(tgt.cards) + len(tgt.showncards)) if n > 0: g.process_action(KanakoFaithKOFAction(tgt, n)) elif evt_type == 'action_apply' and isinstance(act, Damage): src, tgt = act.source, act.target g = Game.getgame() if src and src.has_skill( KanakoFaithKOF) and tgt is g.get_opponent(src): ttags(src)['kanako_faith_kof'] = True return act
def apply_action(self): src = self.source tl = self.target_list g = Game.getgame() for p in tl: g.process_action(SanaeFaithCollectCardAction(src, p)) g.deck.shuffle(src.cards) for p in tl: g.process_action(SanaeFaithReturnCardAction(src, p)) ttags(src)['faith'] = True return True
def apply_action(self): tgt = self.target ttags(tgt)['qiliao'] = True g = Game.getgame() cl = getattr(tgt, 'meirin_qiliao', None) if cl is None: cl = CardList(tgt, 'meirin_qiliao') tgt.meirin_qiliao = cl tgt.showncardlists.append(cl) migrate_cards([self.associated_card], cl, unwrap=True) g.deck.shuffle(cl) return True
def apply_action(self): src, tgt = self.source, self.target ttags(src)['bakadesu'] = True cl = user_choose_cards(self, tgt, ('cards', 'showncards')) g = Game.getgame() if cl: g.process_action(LaunchCard(tgt, [src], cl[0])) else: c = user_input([src], ChoosePeerCardInputlet( self, tgt, ('cards', 'showncards', 'equips'))) c = c or random_choose_card( [tgt.cards, tgt.showncards, tgt.equips]) c and g.process_action(CirnoDropCards(src, tgt, [c])) return True
def apply_action(self): src, lc = self.source, self.action assert isinstance(lc, (LaunchCard, LaunchFatetellCard)) lc.card_action.cancelled = True ttags(src)['mima_tianyi'] = True if isinstance(lc, LaunchCard): # HACK! RejectCard has no target, but not implemented this way. if lc.force_action and isinstance(lc.force_action, Reject): return True lst = lc.target_list[:] elif isinstance(lc, LaunchFatetellCard): lst = [lc.target] else: assert False, 'WTF?!' g = Game.getgame() for p in lst: g.process_action(LaunchCard(src, [p], TianyiAttack(src), bypass_check=True)) return True
def is_valid(self): tgt = self.target return len(self.associated_card.associated_cards ) == ttags(tgt)['miracle_times'] + 1
def is_valid(self): src = self.source return not ttags(src)['faith']
def is_valid(self): src, tgt = self.source, self.target return not ttags(src)['mind_read'] and bool(tgt.cards)
def is_valid(self): tgt = self.target return len(self.associated_card.associated_cards) == ttags(tgt)['miracle_times'] + 1
def is_valid(self): src, tgt = self.source, self.target if not LaunchCard(tgt, [src], AttackCard()).can_fire(): return False return not ttags(src)['bakadesu']
def clickable(game): me = game.me return my_turn() and not ttags(me)['mind_read']
def clickable(g): return my_turn() and not ttags(g.me)['faith']
def __init__(self, player): Skill.__init__(self, player) self.treat_as = ttags(player).get('ran_eikof_card') or DummyCard
def apply_action(self): g = Game.getgame() src, tgt = self.source, self.target ttags(src)['mind_read'] = True return g.process_action(MindReadEffect(src, tgt))
def apply_action(self): tgt = self.target ttags(tgt)['flan_cs'] = True tgt.tags['flan_targets'] = [] return True
def clickable(g): if ttags(g.me)['dismantle']: return False return my_turn()
def in_critical_strike(self, p): return ( ttags(p)['flan_cs'] and Game.getgame().current_player is p and p.has_skill(CriticalStrike) )
def is_valid(self): return not ttags(self.source)['dismantle'] and bool(self.target.equips)