def handle(self, evt_type, act): if evt_type == 'action_after' and isinstance(act, Damage): tgt = act.target if tgt.dead: return act if not tgt.has_skill(Echo): return act g = Game.getgame() pact = g.action_stack[-1] card = getattr(pact, 'associated_card', None) if not card: return act if not card.detached or card.unwrapped: return act if not VirtualCard.unwrap([card]): return act if not user_input([tgt], ChooseOptionInputlet(self, (False, True))): return act attack = card.is_card(AttackCard) pl = attack and user_choose_players(self, tgt, [p for p in g.players if not p.dead]) p = pl[0] if pl else tgt g.process_action(EchoAction(tgt, p, card)) return act
def handle(self, evt_type, act): if evt_type == 'action_after' and isinstance(act, Damage): tgt = act.target if tgt.dead: return act if not tgt.has_skill(Echo): return act g = Game.getgame() pact = g.action_stack[-1] card = getattr(pact, 'associated_card', None) if not card: return act if not card.detached or card.unwrapped: return act if not VirtualCard.unwrap([card]): return act if not user_input([tgt], ChooseOptionInputlet(self, (False, True))): return act attack = card.is_card(AttackCard) pl = attack and user_choose_players( self, tgt, [p for p in g.players if not p.dead]) p = pl[0] if pl else tgt g.process_action(EchoAction(tgt, p, card)) return act
def handle(self, evt_type, act): if evt_type == 'action_shootdown' and isinstance(act, LaunchCard): src = act.source g = Game.getgame() if not src.tags['mind_hack_effect-%s' % g.turn_count]: return act if any(c for c in VirtualCard.unwrap([act.card]) if c.color == Card.BLACK and c in src.showncards): raise MindReadLimit return act
def apply_action(self): src, tgt = self.source, self.target cl = VirtualCard.unwrap([self.associated_card]) assert len(cl) == 1 g = Game.getgame() ttags(src)['teach_used'] = True g.process_action(Reforge(src, src, cl[0])) cl = user_choose_cards(self, src, ('cards', 'showncards', 'equips')) c = cl[0] if cl else random_choose_card([src.cards, src.showncards, src.equips]) g.process_action(TeachTargetEffect(src, tgt, c)) return True
def handle(self, evt_type, act): if evt_type != 'action_after': return act if not isinstance(act, LaunchCard): return act g = Game.getgame() card = act.card if not card: return act if 'basic' not in card.category: return act if card.color != Card.RED: return act if card.is_card(VirtualCard): rawcards = VirtualCard.unwrap([card]) else: rawcards = [card] if not all(c.resides_in is None or c.resides_in.type == 'droppedcard' for c in rawcards): return act tgt = act.source self.target = tgt # for ui if tgt.dead: return act for p in g.players: if p.dead or p is tgt: continue if not p.has_skill(ImperishableNight): continue if p is g.current_player: continue if not user_input([p], ChooseOptionInputlet(self, (False, True))): continue cards = user_choose_cards(self, p, ('cards', 'showncards', 'equips')) if cards: g.players.reveal(cards) skill = skill_wrap(p, [ImperishableNight], cards, {}) assert skill_check(skill) # should not fail g.deck.register_vcard(skill) rst = g.process_action(LaunchCard(p, [tgt], skill)) assert rst return act
def handle(self, evt_type, act): if evt_type != 'action_after': return act if not isinstance(act, LaunchCard): return act g = Game.getgame() card = act.card if not card: return act if 'basic' not in card.category: return act if card.color != Card.RED: return act if card.is_card(VirtualCard): rawcards = VirtualCard.unwrap([card]) else: rawcards = [card] if not all( c.resides_in is None or c.resides_in.type == 'droppedcard' for c in rawcards ): return act tgt = act.source self.target = tgt # for ui if tgt.dead: return act for p in g.players: if p.dead or p is tgt: continue if not p.has_skill(ImperishableNight): continue if p is g.current_player: continue if not user_input([p], ChooseOptionInputlet(self, (False, True))): continue cards = user_choose_cards(self, p, ('cards', 'showncards', 'equips')) if cards: g.players.reveal(cards) skill = skill_wrap(p, [ImperishableNight], cards, {}) assert skill_check(skill) # should not fail g.deck.register_vcard(skill) rst = g.process_action(LaunchCard(p, [tgt], skill)) assert rst return act
def apply_action(self): card = self.card target_list = self.target_list if not card: return False action = self.force_action or card.associated_action if not action: return False g = Game.getgame() src = self.source card = self.card drop = card.usage == 'drop' try: if drop: # should drop before action g.process_action(DropCards(src, src, cards=[card])) elif not getattr(card, 'no_drop', False): detach_cards([card]) # emit events else: card.detach() _, tl = g.emit_event('choose_target', (self, target_list)) assert _ is self if not tl: return True if isinstance(action, Action): a = action else: assert issubclass(action, UserAction) tgt = tl[0] if tl else src a = action(source=src, target=tgt) a.target_list = tl a.associated_card = card self.card_action = a _ = g.emit_event('post_choose_target', (self, tl)) assert _ == (self, tl) g.process_action(a) return True finally: if not drop and card.detached: # card/skill still in disputed state, # means no actions have done anything to the card/skill, # drop it if not getattr(card, 'no_drop', False) and not card.unwrapped: migrate_cards([card], g.deck.droppedcards, unwrap=True, is_bh=True) else: from .cards import VirtualCard for c in VirtualCard.unwrap([card]): if c.detached: c.attach() return True
def ask_for_action(initiator, actors, categories, candidates, timeout=None, trans=None): # initiator: Action or EH requesting this # actors: players involved # categories: card categories, eg: ['cards', 'showncards'] # candidates: players can be selection target, eg: g.players assert categories or candidates assert actors timeout = timeout or 25 from thb.cards import VirtualCard ilet = ActionInputlet(initiator, categories, candidates) @ilet.with_post_process def process(actor, rst): g = Game.getgame() usage = getattr(initiator, 'card_usage', 'none') try: check(rst) skills, rawcards, players, params = rst [check(not c.detached) for c in rawcards] [check(actor.has_skill(s)) for s in skills] # has_skill may be hooked if skills: cards = [skill_wrap(actor, skills, rawcards, params)] usage = cards[0].usage if usage == 'launch' else usage else: cards = rawcards usage = 'launch' if categories: if len(cards) == 1 and cards[0].is_card(VirtualCard): def walk(c): if not c.is_card(VirtualCard): return if getattr(c, 'no_reveal', False): return g.players.reveal(c.associated_cards) for c1 in c.associated_cards: walk(c1) walk(cards[0]) check(skill_check(cards[0])) else: if not getattr(initiator, 'no_reveal', False): g.players.reveal(cards) check(initiator.cond(cards)) assert not (usage == 'none' and rawcards ) # should not pass check else: cards = [] if candidates: players, valid = initiator.choose_player_target(players) check(valid) ask_for_action_verify = getattr(initiator, 'ask_for_action_verify', None) if ask_for_action_verify: check(ask_for_action_verify(actor, cards, players)) return cards, players, params except CheckFailed: return None p, rst = user_input(actors, ilet, timeout=timeout, type='any', trans=trans) if rst: cards, players, params = rst if len(cards) == 1 and cards[0].is_card(VirtualCard): Game.getgame().deck.register_vcard(cards[0]) if not cards and not players: return p, None [c.detach() for c in VirtualCard.unwrap(cards)] return p, (cards, players) else: return None, None
def ask_for_action(initiator, actors, categories, candidates, timeout=None, trans=None): # initiator: Action or EH requesting this # actors: players involved # categories: card categories, eg: ['cards', 'showncards'] # candidates: players can be selection target, eg: g.players assert categories or candidates assert actors timeout = timeout or 25 from thb.cards import VirtualCard ilet = ActionInputlet(initiator, categories, candidates) @ilet.with_post_process def process(actor, rst): g = Game.getgame() usage = getattr(initiator, 'card_usage', 'none') try: check(rst) skills, rawcards, players, params = rst [check(not c.detached) for c in rawcards] [check(actor.has_skill(s)) for s in skills] # has_skill may be hooked if skills: cards = [skill_wrap(actor, skills, rawcards, params)] usage = cards[0].usage if usage == 'launch' else usage else: cards = rawcards usage = 'launch' if categories: if len(cards) == 1 and cards[0].is_card(VirtualCard): def walk(c): if not c.is_card(VirtualCard): return if getattr(c, 'no_reveal', False): return g.players.reveal(c.associated_cards) for c1 in c.associated_cards: walk(c1) walk(cards[0]) check(skill_check(cards[0])) else: if not getattr(initiator, 'no_reveal', False): g.players.reveal(cards) check(initiator.cond(cards)) assert not (usage == 'none' and rawcards) # should not pass check else: cards = [] if candidates: players, valid = initiator.choose_player_target(players) check(valid) ask_for_action_verify = getattr(initiator, 'ask_for_action_verify', None) if ask_for_action_verify: check(ask_for_action_verify(actor, cards, players)) return cards, players, params except CheckFailed: return None p, rst = user_input(actors, ilet, timeout=timeout, type='any', trans=trans) if rst: cards, players, params = rst if len(cards) == 1 and cards[0].is_card(VirtualCard): Game.getgame().deck.register_vcard(cards[0]) if not cards and not players: return p, None [c.detach() for c in VirtualCard.unwrap(cards)] return p, (cards, players) else: return None, None
def cond(self, cl): if not (cl and len(cl) == 1): return False return bool(cl[0].associated_action) and [self.card] == VirtualCard.unwrap(cl)