Example #1
0
class CardStaticAbility(StaticAbility):
    def __init__(self, effects, zone="battlefield", txt='', keyword=''):
        super(CardStaticAbility, self).__init__(effects,
                                                zone=zone,
                                                txt=txt,
                                                keyword=keyword)
        # XXX The zone is not quite right, for attached static abilities that can
        # attach to something out of the battlefield
        self.control_changed = Trigger(
            ControllerChanged(),
            sender="source")  # card with ability changed controller

    def _enable(self):
        super(CardStaticAbility, self)._enable()
        self.control_changed.setup_trigger(self.source,
                                           self.new_controller,
                                           priority=CONTINUOUS_PRIORITY)
        self.effect_tracking = [
            combine(*removal_func)
            if isinstance(removal_func, tuple) else removal_func
            for removal_func in self.effect_generator(self.source)
        ]

    def _disable(self):
        super(CardStaticAbility, self)._disable()
        self.control_changed.clear_trigger()
        for remove in self.effect_tracking:
            remove()
        self.effect_tracking = []

    def leaving(self, card):
        # XXX Don't remove the effect since it's part of LKI
        self.effect_tracking = []

    def new_controller(self, original):
        for remove in self.effect_tracking:
            remove()
        self.effect_tracking = [
            combine(*removal_func)
            if isinstance(removal_func, tuple) else removal_func
            for removal_func in self.effect_generator(self.source)
        ]
Example #2
0
class CardStaticAbility(StaticAbility):
    def __init__(self, effects, zone="battlefield", txt='', keyword=''):
        super(CardStaticAbility, self).__init__(effects, zone=zone, txt=txt, keyword=keyword)
        # XXX The zone is not quite right, for attached static abilities that can 
        # attach to something out of the battlefield
        self.control_changed = Trigger(ControllerChanged(), sender="source")  # card with ability changed controller
    def _enable(self):
        super(CardStaticAbility, self)._enable()
        self.control_changed.setup_trigger(self.source, self.new_controller, priority=CONTINUOUS_PRIORITY)
        self.effect_tracking = [combine(*removal_func) if isinstance(removal_func, tuple) else removal_func for removal_func in self.effect_generator(self.source)]
    def _disable(self):
        super(CardStaticAbility, self)._disable()
        self.control_changed.clear_trigger()
        for remove in self.effect_tracking: remove()
        self.effect_tracking = []
    def leaving(self, card):
        # XXX Don't remove the effect since it's part of LKI
        self.effect_tracking = []
    def new_controller(self, original):
        for remove in self.effect_tracking: remove()
        self.effect_tracking = [combine(*removal_func) if isinstance(removal_func, tuple) else removal_func for removal_func in self.effect_generator(self.source)]
Example #3
0
class CardTrackingAbility(StaticAbility):
    def __init__(self,
                 effects,
                 condition,
                 events=[],
                 tracking="battlefield",
                 zone="battlefield",
                 txt=''):
        super(CardTrackingAbility, self).__init__(effects, zone, txt)
        self.enter_trigger = EnterTrigger(tracking, condition, player="any")
        self.leave_trigger = LeaveTrigger(tracking, player="any")
        self.control_changed = Trigger(
            ControllerChanged(),
            sender="source")  # card with ability changed controller
        if isinstance(events, tuple): events = list(events)
        elif not isinstance(events, list): events = [events]
        self.other_triggers = [
            Trigger(event) for event in [ControllerChanged()] + events
        ]  # triggers for tracked cards
        if not condition: condition = all_match
        self.condition = condition
        self.tracking = tracking
        self.events = events

    def get_current(self):
        controller = self.source.controller
        zone_condition = partial(self.condition, self.source)
        if self.tracking == "battlefield":
            cards = controller.battlefield.get(zone_condition, all=True)
        else:
            zone = getattr(controller, self.tracking)
            cards = zone.get(zone_condition)
            for opponent in controller.opponents:
                opp_zone = getattr(opponent, self.tracking)
                cards.extend(opp_zone.get(zone_condition))
        return cards

    def _enable(self):
        super(CardTrackingAbility, self)._enable()
        self.effect_tracking = {}
        # Get all cards in the tracked zone
        for card in self.get_current():
            self.add_effects(card)

        self.enter_trigger.setup_trigger(self.source,
                                         self.entering,
                                         priority=CONTINUOUS_PRIORITY)
        self.leave_trigger.setup_trigger(self.source,
                                         self.leaving,
                                         priority=CONTINUOUS_PRIORITY)
        self.control_changed.setup_trigger(self.source,
                                           self.new_controller,
                                           priority=CONTINUOUS_PRIORITY)
        for trigger in self.other_triggers:
            trigger.setup_trigger(self.source,
                                  self.card_changed,
                                  priority=CONTINUOUS_PRIORITY)

    def _disable(self):
        super(CardTrackingAbility, self)._disable()
        self.enter_trigger.clear_trigger()
        self.leave_trigger.clear_trigger()
        self.control_changed.clear_trigger()
        for trigger in self.other_triggers:
            trigger.clear_trigger()

        for card in self.effect_tracking.keys():
            self.remove_effects(card)
        self.effect_tracking.clear()

    def new_controller(self, original):
        # Check all current cards, to see if they should be added or removed from the current set
        new_cards, old_cards = set(self.get_current()), set(
            self.effect_tracking)
        for card in new_cards - old_cards:
            self.add_effects(card)
        for card in old_cards - new_cards:
            self.remove_effects(card)

    def entering(self, card):
        # This is called everytime a card that matches condition enters the tracking zone
        if not card in self.effect_tracking: self.add_effects(card)

    def leaving(self, card):
        # This is called everytime a card that matches condition leaves the tracking zone
        # The card might already be removed if the tracked card is removed and this card leaves the battlefield
        # XXX Don't remove the effect since it's part of LKI
        #if card in self.effect_tracking: self.remove_effects(card)
        if card in self.effect_tracking: del self.effect_tracking[card]

    def add_effects(self, card):
        self.effect_tracking[
            card] = True  # this is to prevent recursion when the effect is called
        self.effect_tracking[card] = [
            combine(*removal_func)
            if isinstance(removal_func, tuple) else removal_func
            for removal_func in self.effect_generator(self.source, card)
        ]

    def remove_effects(self, card):
        for remove in self.effect_tracking[card]:
            remove()
        del self.effect_tracking[card]  # necessary to prevent recursion

    def card_changed(self, sender):
        tracking = sender in self.effect_tracking
        pass_condition = self.condition(self.source, sender)
        # If card is already tracked, but doesn't pass the condition, remove it
        # XXX Note the condition can't rely on any trigger data
        if not tracking and pass_condition: self.add_effects(sender)
        elif tracking and not pass_condition and not self.effect_tracking[
                sender] == True:
            self.remove_effects(sender)

    def copy(self):
        return self.__class__(self.effect_generator, self.condition,
                              self.events, self.tracking, self.zone, self.txt)
Example #4
0
class CardTrackingAbility(StaticAbility):
    def __init__(self, effects, condition, events = [], tracking="battlefield", zone="battlefield", txt=''):
        super(CardTrackingAbility, self).__init__(effects, zone, txt)
        self.enter_trigger = EnterTrigger(tracking, condition, player="any")
        self.leave_trigger = LeaveTrigger(tracking, player="any")
        self.control_changed = Trigger(ControllerChanged(), sender="source")  # card with ability changed controller
        if isinstance(events, tuple): events = list(events)
        elif not isinstance(events, list): events = [events]
        self.other_triggers = [Trigger(event) for event in [ControllerChanged()] + events] # triggers for tracked cards
        if not condition: condition = all_match
        self.condition = condition
        self.tracking = tracking
        self.events = events
    def get_current(self):
        controller = self.source.controller
        zone_condition = partial(self.condition, self.source)
        if self.tracking == "battlefield":
            cards = controller.battlefield.get(zone_condition, all=True)
        else:
            zone = getattr(controller, self.tracking)
            cards = zone.get(zone_condition)
            for opponent in controller.opponents:
                opp_zone = getattr(opponent, self.tracking)
                cards.extend(opp_zone.get(zone_condition))
        return cards
    def _enable(self):
        super(CardTrackingAbility, self)._enable()
        self.effect_tracking = {}
        # Get all cards in the tracked zone
        for card in self.get_current(): self.add_effects(card)

        self.enter_trigger.setup_trigger(self.source, self.entering, priority=CONTINUOUS_PRIORITY)
        self.leave_trigger.setup_trigger(self.source, self.leaving, priority=CONTINUOUS_PRIORITY)
        self.control_changed.setup_trigger(self.source, self.new_controller, priority=CONTINUOUS_PRIORITY)
        for trigger in self.other_triggers: trigger.setup_trigger(self.source, self.card_changed, priority=CONTINUOUS_PRIORITY)
    def _disable(self):
        super(CardTrackingAbility, self)._disable()
        self.enter_trigger.clear_trigger()
        self.leave_trigger.clear_trigger()
        self.control_changed.clear_trigger()
        for trigger in self.other_triggers: trigger.clear_trigger()

        for card in self.effect_tracking.keys(): self.remove_effects(card)
        self.effect_tracking.clear()
    def new_controller(self, original):
        # Check all current cards, to see if they should be added or removed from the current set
        new_cards, old_cards = set(self.get_current()), set(self.effect_tracking)
        for card in new_cards-old_cards:
            self.add_effects(card)
        for card in old_cards-new_cards:
            self.remove_effects(card)
    def entering(self, card):
        # This is called everytime a card that matches condition enters the tracking zone
        if not card in self.effect_tracking: self.add_effects(card)
    def leaving(self, card):
        # This is called everytime a card that matches condition leaves the tracking zone
        # The card might already be removed if the tracked card is removed and this card leaves the battlefield
        # XXX Don't remove the effect since it's part of LKI
        #if card in self.effect_tracking: self.remove_effects(card)
        if card in self.effect_tracking: del self.effect_tracking[card]
    def add_effects(self, card):
        self.effect_tracking[card] = True  # this is to prevent recursion when the effect is called
        self.effect_tracking[card] = [combine(*removal_func) if isinstance(removal_func, tuple) 
                else removal_func for removal_func in self.effect_generator(self.source, card)]
    def remove_effects(self, card):
        for remove in self.effect_tracking[card]: remove()
        del self.effect_tracking[card]   # necessary to prevent recursion
    def card_changed(self, sender):
        tracking = sender in self.effect_tracking
        pass_condition = self.condition(self.source, sender)
        # If card is already tracked, but doesn't pass the condition, remove it
        # XXX Note the condition can't rely on any trigger data
        if not tracking and pass_condition: self.add_effects(sender)
        elif tracking and not pass_condition and not self.effect_tracking[sender] == True: self.remove_effects(sender)
    def copy(self):
        return self.__class__(self.effect_generator, self.condition, self.events, self.tracking, self.zone, self.txt)