Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
    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)